1

I have the following case:

Component @permissions this component has a button that triggers a simple promise and set a value on my other component @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);
        });
    }
}

its not important what is returned but it is a simple JSON.

In my other component @MenuComponent

@Component({
   // ..another configuration non 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);
  }
}

So the concept is after the promise sends some value to my subject I need to push someValue to the menu until this point it's ok all data get there, but I need to re-render the view so the "someValue" shows on the view. but it does nothing, when I change the this._cdRef.markForCheck() to this._cdRef.detectChanges() and put it on a tryCatch it returns Attempt to use a destroyed view: detectChanges. I can't find a way to render the menu with someValue.

This both components are at the same level on the ChangeDetection Tree

halfer
  • 19,824
  • 17
  • 99
  • 186
vasconcelosvcd
  • 119
  • 1
  • 1
  • 11

3 Answers3

1

Try ApplicationRef.tick(). This is "always working" workaround.

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

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

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

Similar question was asked here: Trigger update of component view from service - No Provider for ChangeDetectorRef

More about ApplicationRef: https://angular.io/api/core/ApplicationRef

The best solution for your problem would be to use Component <-> Service <-> Component communication: https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service

Maciej Treder
  • 11,866
  • 5
  • 51
  • 74
1

My solution for this case was a suggestion from Maciej Treder, he said:

'The best solution for your problem would be to use Component <-> Service <-> Component communication: https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service'

So I've created a service that listen to the changes made by @PermissionModule and send a change event to the @MenuComponent from that I was able to push vales into the menus array and render the view, without .tick() or .detectChanges()

ServiceComponent

@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() { }
}

Where do I want to emmit the event:

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

And where I want to listen the change emmited

// ... IrrelevantCode
constructor(private _shared: SharedServicesMenu){}
this._shared.changeEmitted$.subscribe((data) => {
  //Do what ever you want with data emmited here
}, (err) => {
  console.log(err);
}, () => {
  console.log('Complete!');
});
vasconcelosvcd
  • 119
  • 1
  • 1
  • 11
0

Instead of pushing value inside this.menus try something like this

reloadAll() { 
    var tmp = this.menus.slice();
    tmp.push('some valuue');
    this.menus=tmp;
}
Prathmesh Dali
  • 2,250
  • 1
  • 18
  • 21
  • Check this solution it might be helpful... https://stackoverflow.com/questions/34796901/angular2-change-detection-ngonchanges-not-firing-for-nested-object – Prathmesh Dali Jul 17 '17 at 21:11