Unable to render forcibly in Angular 2 from a different component

Let's consider the following scenario:

We have a component called @permissions which contains a button that triggers a simple promise to set a value on another component called @MenuComponent.

export class Permissions {
    constructor(private _menu: MenuComponent, private _api: ApiService) {}

    btnAction(){
        this._api.getDataID(item.project_name, 'usersbyID', userID).then((data: any) => {
            this._menu.checkPerm(JSON.parse(data.permissions).description);
        });
    }
}

The data returned by the promise is in JSON format.

Now, in the @MenuComponent:

@Component({
   // ...other configuration details not relevant
   changeDetection: ChangeDetectionStrategy.OnPush,
})

export class MenuComponent implements OnInit {
  menus = []
  menuPermisson: any;
  menuObservable = new Subject();

  constructor(private _cdRef: ChangeDetectorRef) {
    this.menuObservable.subscribe(value => {
      this.menuPermisson = value;
      this.reloadAll();
    });
  }

  reloadAll() {
    this.menus.push('someValue');
    this._cdRef.markForCheck();
  }

  checkPerm(data) {
    this.menuObservable.next(data);
  }
}

The goal is to update the view with "someValue" after receiving data from the promise. However, when trying to re-render the view using this._cdRef.detectChanges(), an error message saying "Attempt to use a destroyed view: detectChanges" is returned. It seems challenging to display "someValue" on the menu despite both components being at the same level in the ChangeDetection Tree.

Therefore, there seems to be a struggle in rendering the updated menu with the desired content.

Answer №1

Give ApplicationRef.tick() a shot. It's a reliable workaround that seems to always work.

import { ApplicationRef } from '@angular/core';

export SomeComponent {
    constructor(private appRef: ApplicationRef) {}

    public triggerChangeDetection(): void {
        this.appRef.tick();
    }
}

A similar question has been addressed on Stack Overflow here: Trigger update of component view from service - No Provider for ChangeDetectorRef

To learn more about ApplicationRef, visit: https://angular.io/api/core/ApplicationRef

If you're looking for the best solution, consider utilizing

Component <-> Service <-> Component
communication: https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service

Answer №2

After seeking advice from Maciej Treder, I implemented a solution for this issue:

"The recommended approach for your problem is to use Component <-> Service <-> Component communication: https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service"

I established a service that observes changes initiated by @PermissionModule and triggers a change event to the @MenuComponent. This allowed me to update values in the 'menus' array and display the changes without using .tick() or .detectChanges()

The code for the ServiceComponent is as follows:

@Injectable()
export class SharedServiceMenu {

  // Observable string sources
  private emitChangeSource = new Subject<any>();

  // Observable string streams
  changeEmitted$ = this.emitChangeSource.asObservable();

  // Service message commands
  emitChange(change: any) {
    this.emitChangeSource.next(change);
  }

  constructor() { }
}

Here is where I trigger the event:

// ...irrelevant code 
constructor(private _shared: SharedServiceMenu){}
this._shared.emitChange(data);

And here is where I listen for the emitted change:

// ... IrrelevantCode
constructor(private _shared: SharedServiceMenu){}
this._shared.changeEmitted$.subscribe((data) => {
  //Do whatever you want with the emitted data here
}, (err) => {
  console.log(err);
}, () => {
  console.log('Complete!');
});

Answer №3

Why not consider this approach instead of directly inserting values into the this.menus array?

refreshAll() { 
    var tempArray = this.menus.slice();
    tempArray.push('new value');
    this.menus = tempArray;
}

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

React problem with manipulating JSON arrays

In my React application, I am working with an array that looks like this: [ { year: 2014, field: "Coal", value: 100 }, { year: 2014, field: "power", value: 200 }, { year: 2014, field: "oil", value: 20 }, { ...

A guide to utilizing ngFor in Angular 7 to loop through nested JSON and display it in a ul li

Looking to insert a nested JSON into an unordered list using ngFor loop in Angular. Here's the expected output format in HTML: home.component.html <div class="col-md-3" id="leftNavBar"> <ul *ngFor="let item of nestedjson"> <li c ...

Facing difficulties in Angular 8 while trying to import firestore and firebase for an authentication system

While attempting to implement Firestore/Firebase functionalities for Google OAuth signin, I encountered an error indicating that Firebase is not imported: https://i.sstatic.net/oL4rY.png CODE: ERROR in node_modules/@angular/fire/auth/auth.d.ts:4:28 - er ...

"Exploring the advancements in inner calls and the deprecation of forkJoin

Here is the code snippet I am currently working with: ngOnInit(): void { this.issueService.getIssues().pipe( switchMap(issues => { this.issuesList = issues; const observables = this.issuesList.map(issue => this.issueService.getChild ...

Is there a way to eliminate the initial and final double quotes within Angular 4?

Similar to JavaScript, TypeScript also uses either double quotes (") or single quotes (') to enclose string data. I have data coming from the backend that includes HTML content. Here is an example of my API response: <p>afjhjhfsd</p> Wh ...

Angular Material's *matNoDataRow directive is malfunctioning

I am having an issue with using the *matNoDataRow directive in Angular Material. I have created a MatTable with filtering functionality, and when no data matches the filter, I want to display a specific text. However, the directive does not seem to be work ...

Toggling classes in Angular for dynamic elements can easily be achieved by using the

I am trying to toggle between the right and wrong classes based on boolean values from an array. The goal is to add a red background class for incorrect answers and a green background class for correct answers. Unfortunately, I'm having trouble getti ...

Transforming a TypeScript data type into a comparable type

I'm facing a challenge with two interfaces that represent the data returned by an API and the actual data itself. interface APIModelCommon { id: number createdAt: string updatedAt: string } interface ModelCommon { id: number creat ...

Angular9: construction involves an additional compilation process

After updating my Angular8 project to Angular9, I noticed a new step in the build process which involves compiling to esm. This additional step has added approximately 1 minute to my build time. A snippet of what this step looks like: Compiling @angular/ ...

What is the best way to search a list with a button click using Angular?

I'm currently working with Angular 6 to create a search functionality for my list. The current code I have successfully performs the search when I type text into the search input box. However, I want the search to only be executed after I click on a b ...

Referencing 'this' in Angular and Typescript: Best practices

When setting up TypeScript in an Angular project, I use the following syntax to declare a controller: module app { class MyController { public myvar: boolean; constructor() { this.myvar= false; } } angula ...

Issue with bi-directional data binding in Angular's matInput component

When working on my template... <input matInput placeholder="Amount" [(value)]="amount"> In the corresponding component... class ExampleComponent implements OnInit { amount: number = 0; ... } The binding doesn't seem to work as expect ...

The alignment of ngx-dropdown in the bottom sidebar element of Bootstrap 5 seems to be misaligned

Struggling with dropdown positioning? Check out the examples I created on stackblitz: As I was referring to examples from bootstrap-5, the issue I faced pertained to the user panel in the sidebar (both collapsed and expanded view): example 1 example 2 ...

Limit the values in the array to only match the keys defined in the interface

I'm trying to restrict an array's elements to specific keys of an interface: interface Foo { bar: string; baz: number; foo: string; } type SelectedKeysArray<T, K extends keyof T> = Pick<T, K>[]; const selectedKeys: SelectedKey ...

The specified dependency, * core-js/fn/symbol, could not be located

I am in the process of developing a Vue.js application with Vuex and have encountered some errors during the build. I attempted to resolve the issue by installing npm install --save core-js/fn/symbol, but unfortunately, it did not work as expected. https:/ ...

The *ngIf directive is refusing to display a template

I am currently facing an issue with my .html file where I am trying to display values based on a condition using "*ngIf". The condition is to find a value that ends with "Rechercher ...", but I am having trouble getting it to work. I have tried various app ...

Encountering issues while constructing a .Net Core Angular application in TFS due to the error of webpack.optimize.UglifyJsPlugin removal

After creating my Angular project using the default Angular template in Visual 2017 .net Core, I encountered some issues. The project runs smoothly locally on IIS without any problems. However, when attempting to publish the project to local IIS or exter ...

Encountering an Issue with Registering the Angular 7 Service Worker - Error with ngsw-worker

Problem: Encountering ERR_INVALID_RESPONSE and /ngsw-config.json:-Infinity Parser error when trying to access the ngsw-worker.js file in network traffic. Refer to the image below: https://i.stack.imgur.com/Ejozw.png Technology Used: Angular CLI with An ...

Analyze the information presented in an HTML table and determine the correct response in a Q&A quiz application

I need to compare each row with a specific row and highlight the border accordingly: <table *ngFor="let Question from Questions| paginate: { itemsPerPage: 1, currentPage: p }"> <tr><td>emp.question</td></tr> <tr> ...

Ways to retrieve a json file within Angular4

Seeking guidance on accessing the data.json file within my myservice.service.ts file. Any suggestions on how to accomplish this task? Overview of directory structure https://i.stack.imgur.com/WiQmB.png Sample code from myservice.service.ts file ht ...