1

I am using a child component that has an input property.

<child [inputprop]="input"></child>

The child component doesn't implement ngOnChanges. I would like to update the component from parent. What's the best way to do this?

I have looked at using ngIf and re-rendering the component. Is there a cleaner way?

<child [inputprop]="input" ngIf="render"></child>

component

rerender() {
       render=false
       cdRef.detectChanges()
       render=true
}

Edit: I can't change the code of the child component. I am looking for better ways to do this without changing the child component.

soumith
  • 536
  • 1
  • 3
  • 12
  • I used some tricks in this answer that will probably help you https://stackoverflow.com/a/65531547/9546702 – mehranmb78 Mar 22 '21 at 07:44
  • The idea of what you want to do is just plain wrong (sorry, to be candid), instead I'd look making the child component implement ngOnChanges. – Anders Mar 22 '21 at 07:57
  • I would love to make the child component implement that. But I can't make changes to that code. I am trying to reuse a component in a big project. – soumith Mar 22 '21 at 13:52

2 Answers2

1

You can create a 'notifier' class.

export class NotifyHandler<T> {
  private readonly source$: Subject<T> | BehaviorSubject<T>;
  private readonly notifier$: Observable<T>;

  constructor(initialValue?: T) {
    this.source$ = initialValue ? new BehaviorSubject(initialValue) : new Subject();
    this.notifier$ = this.source$.pipe(shareReplay(1));
  }

  get notifier(): Observable<any> {
    return this.notifier$;
  }

  public notify(value?: T): void {
    this.source$.next(value ?? null);
  }
}

and use it like this

<child [inputprop]="input" [notifier]="notifyHandler.notifier"></child>

child component
.....
private subscriptions = new Subscription();
@Input()
notifier:Observable<any>;

constructor(props){
  this.subscriptions.add(this.notifier.subscribe(event=> ...handle update     logic...));
}

ngOnDestroy(){
  this.subscriptions.unsubscribe();
}
....
parent component
...

public notifyHandler= new NotifyHandler<any>();

onChildMustUpdate(){
  notifier.notify(<data if any required>);
}
...
Bogdan B
  • 846
  • 9
  • 23
0

Your logic is very wrong as it will destroy the component once then re-initialize it. if you only want to re-render and trigger change detection you can follow steps below :-

Step1 :- inject ChangeDetectorRef in your child component.

constructor(private cd: ChangeDetectorRef){}

Step2 :- Implement a public method that calls detect changes in child component.

public reRender() {
   this.cd.detectChanges();
}

Step3 :- ViewChild your child component in parent component like :-

@ViewChild(ChildComponent) child: ChildComponent;

Step4 :- Call that method from parent component.

this.child.reRender();
Aakash Garg
  • 10,649
  • 2
  • 7
  • 25
  • Thanks for the answer. I know my method is bad and that's the reason why I'm looking for better solutions. Also, I can't change the child component code and that's the main issue for me here. – soumith Mar 22 '21 at 13:55