简体   繁体   中英

Angular component not updating when input changes value

So I have a component that takes in a value from an object. I have the outer div subscribed to a behavior subject. When I update the behavior subjects value using next() the title of the container div updates but the inner component refuses to re-render. Am I doing something wrong here?

Here is the behavior subject in my controller, this is called in the ngOnInit method and the update method that is called on button click in the html:

ngOnInit() {
  this.selectedRole$.next({ name: 'Current Permissions', permissions: this.getUserPermissions()
}

showRoleDetails(role: any): void {
  this.selectedRole$.next(role);
}

here is the parent component html this is where I am using async to subscribe to the behavior subject. the selectedRole.name updates perfectly but the inner c-permissions-display does not re-render:

<div *ngIf="selectedRole$ | async as selectedRole" class="col-8">
  <h5 class="font-weight-medium mb-0 text-gray-500 mb-4 permissions-title">{{ selectedRole.name }}</h5>
  <div class="section-container">
    <c-permissions-display [permissions]="selectedRole.permissions"></c-permissions-display>
  </div>
</div>

here is the c-permissions-display component:

import { Component, OnInit, Input } from '@angular/core';
import { UtilityService } from 'src/app/canopy-common/services/utility.service';

@Component({
  selector: 'c-permissions-display',
  templateUrl: './permissions-display.component.html',
  styleUrls: ['./permissions-display.component.scss']
})
export class PermissionsDisplayComponent implements OnInit {

  @Input() permissions: any[];
  formattedPermissions: any[];

  constructor(
    private util: UtilityService
  ) { }

  ngOnInit() {
    this.formattedPermissions = this.formatPermissionsArray();
  }

  private formatPermissionsArray(): any {
    return stuff
  }
}

if I place a console log in the ngOnInit it calls once when the page loads but never again after calling next() on the behavior subject. I know I can get this to work if I implement OnChanges and then the ngOnChanges() method but I should not have to do that it should update and re-render on its own if its input changes value. Unless they changed that in angular 9

I think i remember it is because selectedRole.permission is an array and angular can't know if a value inside this array is changing or not.

So to make the array refresh too, you must overwrite the permission array with a new one. Something like selectedRole.permission = [new permission array ].

This way angular should be able to detect the change and refresh the view.

Instead of passing value to child component. you can pass observable to child component and subscribe inside child component so that whenver value changes in parent component child component get notified.

Try this

parent.component.html

<div *ngIf="selectedRole$ | async as selectedRole" class="col-8">
  <h5 class="font-weight-medium mb-0 text-gray-500 mb-4 permissions-title">{{ selectedRole.name }}</h5>
  <div class="section-container">
    <c-permissions-display [permissions]="selectedRole$"></c-permissions-display>
  </div>
</div>

child.component.ts

export class PermissionsDisplayComponent implements OnInit {

   @Input() permission = new BehaviorSubject(null);
   formattedPermissions: any[];

  constructor(
    private util: UtilityService
  ) { }

  ngOnInit() {
    this.permission.subscribe(permission=>{
        this.formattedPermissions = this.formatPermissionsArray();
    })

  }

  private formatPermissionsArray(): any {
    return stuff
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM