1

I used the modal from ng-bootstrap

In my parent component i used modalService to open the modal, and i sent data to the modal using componentInstance.

In the modal component i used ngOnChanges to get the data that i sent. but the ngOnChanges is not trigged.

stackblitz

parent component

  public toAttach(): void {
    let modalRef = this.modalService.open(HelloComponent);
    modalRef.componentInstance.attachments = this.attachments;
  }

modal component

  ngOnChanges(changes: SimpleChanges) {
    console.log("start!");
    if (changes["attachments"] && changes["attachments"].currentValue) {
      console.log(changes["attachments"].currentValue);
    }
  }
hanan
  • 1,768
  • 1
  • 14
  • 19
Aymen Kanzari
  • 1,765
  • 7
  • 41
  • 73

3 Answers3

5

When you set the component instance's values directly, it will not trigger an ngOnChanges. ngOnChanges is triggered when the value binding for a component changes. It also depends on the change detection strategy. If you want to change the value for a component instance variable directly, you can use a setter method in which you could do what you want to do in ngOnChanges. For example -

import {
  Component,
  Input,
  AfterViewInit,
  ChangeDetectorRef,
  SimpleChanges,
  OnChanges
} from "@angular/core";

@Component({
  selector: "hello",
  templateUrl: "./hello.component.html"
})
export class HelloComponent implements AfterViewInit, OnChanges {
  @Input()
  public attachments: any[];

  constructor(private cd: ChangeDetectorRef) {}

  ngAfterViewInit() {
    this.cd.detectChanges();
  }

  setAttachments(attachments: []) {
     this.attachments = attachments.slice();
     // => DO YOUR WORK HERE
     // Like calling change detection.
   }

  ngOnChanges(changes: SimpleChanges) {
    console.log("start!");
    if (changes["attachments"] && changes["attachments"].currentValue) {
      console.log(changes["attachments"].currentValue);
    }
  }
}

And in the parent component, call

public toAttach(): void {
    let modalRef = this.modalService.open(HelloComponent);
    modalRef.componentInstance.setAttachments(this.attachments);
  }
buchipper
  • 606
  • 4
  • 16
1

Seems like by setting property directly angular does not fire ngOnChange

in ngOnInit() this.attachments are populated

  ngOnInit() {
 console.log(this.attachments);
}

you can use them there

enter image description here

if u still want to use ngOnChanges for regular use then in this case use one input for regular usage and one only setter for this purpose in setter u will call on ngOnChange. yep this is a workaround but it will work!!

hanan
  • 1,768
  • 1
  • 14
  • 19
  • i want to use ngOnChanges beacause i have another treatment that updates the attachments array in parent component, then i get the new attachments array in the modal compoenet – Aymen Kanzari Jul 07 '20 at 21:31
0

You can use BehaviorSubject in parent something like this:

export class AppComponent {
  private attachmentsSubject: any = new BehaviorSubject([{
      idChild: "111111111",
      startDate: "2020-06-29T23:00:00.000+0000",
      endDate: "2020-07-21T23:00:00.000+0000",
      motif: "Déménagement"
  }]) ;

  constructor(private modalService: NgbModal) {}

  public toAttach(): void {
    let modalRef = this.modalService.open(HelloComponent);
    modalRef.componentInstance.attachmentsSubject = this.attachmentsSubject;
  }
}

so child component will be simpler:

export class HelloComponent {
  attachmentsSubject: any;
}

<div class="modal-body">
  <div *ngFor="let item of (attachmentsSubject | async)">
    {{ item.idChild}}
  </div>
</div>

It works because in parent component you set the actual data through componentInstance.

I have updated your code: https://stackblitz.com/edit/angular-ivy-rmnvsf?file=src%2Fapp%2Fhello.component.html

Slawa Eremin
  • 5,264
  • 18
  • 28
  • i want to use ngOnChanges beacause i have another treatment that updates the attachments array in parent component, then i get the new attachments array in the modal compoenet – Aymen Kanzari Jul 07 '20 at 21:31
  • @AymenKanzari yep, updated answer, I think, it will work for you – Slawa Eremin Jul 07 '20 at 21:42