4

Following are my undestanding on onPush change detection strategy. OnPush change detection is triggered if one of the following happens

  1. A bound event is received on the component.
  2. An input was updated.
  3. Async pipe received an event.
  4. Change detection was invoked manually.

From the above list, An input was updated has to be reference change, so the input has to immutable.

This is my scenario.

I have parent component Parent where I subscribe to an observable to fetch data from an API call and I pass this data to the child component via @Input.

Parent Component

@Component({
  template: '<child-component [data]="data"></child-component>'
})
export class ParentComponent implements OnInit {
  this.dataService.get().subscribe(data => {this.data = data})
}

Child Component

@Component({
  selector: 'child-component',
  template: '{{data.name}}',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent {
  @Input() data;
  constructor() {
    console.log(this.data) 
    // undefined, because the data is async response and not available while bootstrapping.
  }
  ngAfterContentChecked() {
    console.log(this.data) // available
  }
}

The problem here is if we add onPush change detection strategy to the child component and the input reference is not changed, the changes are not propagated from parent to child. The reason is because onPush strategy expects the inputs to be immutable. How to overcome this situation?

Any help is greatly appreciated.

Update

On googling I found this blog post by Victor Savkin

If a component depends only on its input properties, and they are observable, then this component can change if and only if one of its input properties emits an event.

So can we pass observables to the inputs and fix this? If so please propose a working solution.

Please note that I don't want to use asyn pipe in template or manually trigger change detection.

Vishnu Sureshkumar
  • 2,246
  • 6
  • 35
  • 52
  • "The reason is because onPush strategy expects the inputs to be immutable." Why do you think this is relevant here? You're not modifying an object value. – Günter Zöchbauer May 22 '17 at 10:35
  • 1
    "Since the input reference is not changed" also here, why do you think it's not changed. `this.data = data` does change it. You can pass observables and then bind to it using `data | async` – Günter Zöchbauer May 22 '17 at 10:43
  • @Gunter The input is the value I get subscribing to an observable. So when the response reaches from an API, the object reference is not changed and the change detection is not triggered. – Vishnu Sureshkumar May 22 '17 at 10:44
  • Still no idea why you think that. You always get a new instance from HTTP requests. There is no way to retain object identity. – Günter Zöchbauer May 22 '17 at 10:48
  • 1
    @GünterZöchbauer - Yes the reference is changed here, I would like to know a solution when the reference does not change. – Vishnu Sureshkumar May 22 '17 at 10:48
  • So why do you add a code example about something you don't want to know? ;-) When nothing changes why do you expect the view to update? I still don't get what the question is about. – Günter Zöchbauer May 22 '17 at 10:51

0 Answers0