How can Angular components that are not directly related subscribe to and receive changes using a declarative approach?

Here's the issue at hand:

  • I'm facing a problem with my Dashboard component. The Dashboard consists of a Sidebar and Navbar as child components.
  • On the Sidebar, I have applied a custom permission directive to the links to determine if the user has permission to view them or not.
  • The Navbar includes options for Admin, Manager, and staff roles. Whenever the user changes roles, I need to update the sidebar links based on the new scope permissions.

I attempted to pass an observable to the sidebar like this:

scope$: Observable<Roles> = this.scopeService.scope$;

using the async pipe:

<app-sidebar [scope]="scope$ | async"></app-sidebar>

and subscribing in the ngOnInit method:

ngOnInit(): void {
    this.scopeService.scope$.subscribe();
  }

However, this approach didn't work as expected. I've come across suggestions to use event emitters, but I prefer a declarative pattern for this task.

For more details, you can check out this stackblitz link.

Answer №1

Understanding how the async pipe works is crucial in this scenario. The async pipe automatically subscribes to an observable and retrieves its value. However, if you simply want to pass the observable without subscribing to it, then there's no need for the async pipe. You can achieve this by:

<app-sidebar [scope$]="scope$"></app-sidebar>

Then, in the app-sidebar component:

@Input
scope$: Observable<Roles> = this.scopeService.scope$;

ngOnInit(): void {
    this.scope$.subscribe();
  }

Upon reviewing your stackblitz, it's apparent that the issue lies in your has-permission directive. Instead of using a snapshot of the scope, you should subscribe to it like so:

  ngOnInit(): void {
    this.scopeService.scope$.subscribe((newScope) => {
      this.scope = newScope;
      this.checkPermissions();
    });
  }

This approach ensures that the checkPermissions() method is invoked every time the scope changes. Additionally, you may need to adjust how you display elements to address existing permission issues. Consider updating the showElement method as follows:

  showElement(canShow: boolean): void {
    this.viewContainer.clear();
    if (canShow) {
      this.viewContainer.createEmbeddedView(this.templateRef);
    }
  }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular project icons not displaying in the browser

My current project in Angular was functioning properly until recently. I am facing an issue where the images are not being displayed on the browser when I run ng serve, resulting in a 404 error. Interestingly, everything else seems to be working fine witho ...

Tips for validating an Angular form with material form fields:

I am currently working on a form that utilizes Angular material form fields. My goal is to have the submit button disabled until all the form controls have been filled with the appropriate values. You can find the code provided in the links below. When I ...

Guide on displaying a tooltip for an object in an Angular component using Bootstrap syntax

i have a data object structured like this var obj = {"test price type ty dynamic ": 10, test: 7, pricetype1u: 0, Price type 3: 0, Price type 2: 0} in my Angular component HTML, with Bootstrap styles applied, I've written the following code ...

Tips on utilizing index and eliminating React Warning: Ensure every child within a list has a distinct "key" prop

Hello, I am encountering an issue where I need to properly pass the index in this component. Can you help me figure out how to do that? Error: react-jsx-dev-runtime.development.js:117 Warning: Each child in a list should have a unique "key" prop ...

Get a single object from an array with .single method provided by @ngrx

Seeking to retrieve an Observable containing a single object from an array of objects in my store. I aim to utilize the .single operator, which should throw an exception if there is not exactly 1 object present. However, I'm struggling with this as my ...

Using Bootstrap 3 Modal in an Angular 4 Application: A Step-by-Step Guide

After attempting all the solutions provided here, I am still facing this error. My setup includes Bootstrap 3 and Angular 4. The issue arises when I attempt to display a modal using the following code: $("#myModal").modal('show'); ...

Is there a way to invoke a function within a mat-error element?

I need to display an error message in my input field! The function will return true if both passwords match, otherwise it will return false. How can I invoke a boolean function inside mat-error! My Function: checkPasswords(): Boolean { // 'passwords& ...

What is the solution to prevent angular-material components from covering my fixed navbar?

After creating a navbar using regular CSS3, I incorporated input fields and buttons from angular material. However, my sticky navbar is being obscured by the components created with angular material. Here is the CSS for the navbar: position: sticky; top: ...

Asynchronous and nested onSnapshot function in Firestore with await and async functionality

I'm facing an issue with the onSnapshot method. It seems to not await for the second onsnapshot call, resulting in an incorrect returned value. The users fetched in the second onsnapshot call are displayed later in the console log after the value has ...

There is no matching overload for this call in Angular. Error code: TS2769

Having trouble identifying the issue in this TypeScript code snippet. Error reported on line 5, ".subscribe((response: { Token: string }) => {". login() { this.httpClient .post('http://localhost:4000/signin', this.loginForm.value) ...

Swapping the content of the API response with Angular 11 in the HTML

When the output of row.remarks is 1, I want to display it as "passed" and when it's 0, I want it to be displayed as "fail" in the HTML while using mat-table. HTML <ng-container matColumnDef="remarks"> <th class="font& ...

Providing Access to Data Across Various Modules

I currently have an application structured like this: AppModule SubModule Multiple Components SecondSubModule Multiple Components I am looking to perform a data call to a REST API that will be used by both SubModule and SecondSubM ...

Zod data structure featuring optional fields

Is there a more efficient way to define a Zod schema with nullable properties without repeating the nullable() method for each property? Currently, I have defined it as shown below: const MyObjectSchema = z .object({ p1: z.string().nullable(), p2 ...

The ion-progress-bar does not display properly when embedded within an ng-template with the id "loading"

This is my initial inquiry. I have created a loading template with an ion progress bar within it, but for some reason, it does not display at the footer of the page (nor in the header if I attempt to place it there as well). Instead, it appears next to the ...

Using path aliases in a Typescript project with Typescript + Jest is not a viable option

Note I am able to use aliases in my TypeScript file. Unfortunately, I cannot use aliases in my test files (*.test.ts). My Configuration 1. Jest.config.ts import type { Config } from '@jest/types'; const config: Config.InitialOptions = { ve ...

Issue with Angular 2 view not refreshing after receiving ipcRenderer.on event in Electron

Utilizing ipcRenderer to fetch the folder path from a browser dialog in my main.js. However, it is not updating the text string on my view for some unknown reason. I am aware that using setTimeout could potentially fix this issue (thanks Google!). Yet, e ...

Use rowSelected to set the initial selected rows in an Angular Kendo UI grid

Within my Kendo UI Grid, the ability to select individual rows is made possible by clicking a checkbox that adds them to an array. However, my goal is to initially set selected rows based on whether or not the dataItem for each row exists in a specified ar ...

Exporting ExpressJS from a TypeScript wrapper in NodeJS

I've developed a custom ExpressJS wrapper on a private npm repository and I'm looking to export both my library and ExpressJS itself. Here's an example: index.ts export { myExpress } from './my-express'; // my custom express wrap ...

A step-by-step guide on sending a fetch request to TinyURL

I have been attempting to send a post request using fetch to tinyURL in order to shorten a URL that is generated on my website. The following code shows how I am currently writing the script, however, it seems like it's not returning the shortened URL ...

The promise briefly returns a placeholder object before resolving with the actual response

Currently, I am working on a simple check to determine whether myAnswer contains an answer. The checking functionality is operating smoothly; however, the issue arises in the final function that aims to return the string obtained from myAnswer. Instead of ...