Angular change detection issue in array

148 Views Asked by At

I have the following two components in a parent / child relationship: "Properties" - the parent in this scenario and "listingsList" - the child.

Here's the parent template:


<div class="row"> 

   <div class="col-9 p-2">
       <listings-list [properties] = "properties"   ></listings-list>
    
     <div *ngIf="properties?.length == 0"  class="card-text bg-white p-1" i18n="@@noResult" >No results found!</div>   

     <div *ngIf="properties?.length! > 0 && totalNumberOfRecords == null"  class="alert alert-warning my-1" role="alert" i18n="@@paginationWarning">Pagination will load shortly!</div>   

     <div *ngIf="properties?.length! > 0" class="btn-group float-right"> 
       <ngb-pagination [collectionSize]="totalNumberOfRecords" [pageSize]="state!.propertiesPerPage" [(page)]="state!.page" (pageChange)="changePage($event)" [maxSize]="5" [rotate]="true" [boundaryLinks]="true"></ngb-pagination>      
     </div>               
   </div>
</div>



Here's the child component:

@Component
({
   selector: "listings-list",
   templateUrl:"listings-list.component.html",
   styleUrls:["listings-list.component.css"]
})
export class PropertiesListComponent {      

   @Output()
   public block:EventEmitter<Property> = new EventEmitter();

   @Output()
   public unBlock:EventEmitter<Property> = new EventEmitter();

   @Input()
   public properties: Property[] = [] ;     

}

When the user decides to delete a listing, the following method is called on the parent component

public delete(propertyId: number): void {     

       if (propertyId !== undefined) {
           this.model.deleteProperty(propertyId)
               .subscribe( _ => {
                   this.messageService.reportMessage(new Message(`Property ${propertyId} has been successfully deleted.`));

                   var status: boolean = this.propertyStatus == PROPERTY_STATE_ACTIVE ? true : false;
                   var filter = { createdBy: this.authService.user.userName, isActive: status, pageNumber: this.state!.page, pageSize: this.state!.propertiesPerPage };
                   this.model.getPropertyByFilter(JSON.stringify(filter)).subscribe(data => {
                       this.properties = [...data] ;
                   });

                 
               });
       }
   }

My problem is that even thought the "properties" array has changed, the change is not detected in the child component.

My understanding is that as long the array reference is changed, then the change should be detected.

I believe the array reference is changed in my scenario.

Any ideas about what I am doing wrong?

Thanks for any suggestions.

2

There are 2 best solutions below

0
Meqwz On

You either need to use ngOnChanges or a setter and a getter. I prefer setters and getters. See below. The official docs are here.

@Component
({
   selector: "listings-list",
   templateUrl:"listings-list.component.html",
   styleUrls:["listings-list.component.css"]
})
export class PropertiesListComponent {      

   private _properties: Property[] = [];
   @Output()
   public block:EventEmitter<Property> = new EventEmitter();

   @Output()
   public unBlock:EventEmitter<Property> = new EventEmitter();

   @Input() set properties(value): Property[] {
      this._properties = value;
   } 

   get properties(): Property[] {
      return this._properties;
   }

}
0
toTheBestOfMyKnowledge On

Use ngOnChanges. In your child component-->

@Input() properties: Property[] = [] ;
_properties:Property[] = [] ;

ngOnChanges(){
  _properties=properties;//Use this "_properties" variable in your child list view
 }