0

i've got some troubles while passing data(Array) between components by @Input, there is some code. parent.component.ts:

public ngOnInit() {
    this.applications = new Array<ApplicationEntryInterface>();
(...)
let shortTermData = new ShortTermApplicationAdapter(application);
this.applications.push(shortTermData);
console.log(this.applications);
}

this console.log shows me normal arrayenter image description here parent.component.html

<student-application-overview [applicationsEntry]="applications"></student-application-overview>

Child component:

@Input('applicationsEntry') public applicationsEntry: Array<ApplicationEntryInterface>;
 ngOnChanges() {
console.log(this.applicationsEntry);
console.log(this.applicationsEntry.length); <--- shows 0
}

which shows enter image description here It's impossible to iterate it in for, foreach, etc, only *ngFor works, this.applicationsEntry.length is equal to 0, how can I handle with it ? Also I used @Input (..) set (..) { (..) } and it gave same result

Jędrek Markowski
  • 444
  • 3
  • 6
  • 25
  • 1
    The way you're passing the array into your child component looks correct, and if that second screen grab is the log from your child, it looks correct there too. Could we see where you're calling a `forEach` or `length` in your component code? My best guess is that the array you're passing in would not be immediately available in your child component, especially if the `*ngFor` in your template HTML *is* working – Jack Koppa Oct 02 '17 at 12:23
  • Just Edited, same forEach treat this array like it's 0 length. – Jędrek Markowski Oct 02 '17 at 12:26
  • Ok I just realised, that I was using async function in parent component(communication with rest api), anyway, newest array is not set on changes(only body). – Jędrek Markowski Oct 02 '17 at 12:36
  • 1
    Hmmm, gotcha. It looks like the async not triggering change detection *could* be related to [this question](https://stackoverflow.com/questions/34561951/ngonchanges-not-firing-when-input-property-changed), which didn't have a satisfying resolution. One option (if change detection is indeed the problem), is to pass in a second input (e.g. `changeTrigger`), not bound to an async call, that you update when you get back the result of your async call. When you call `changeTrigger++` in the parent, it would trigger `ngOnChanges` in the child – Jack Koppa Oct 02 '17 at 12:47
  • Without seeing a plunkr, it's tough to know exactly what will work, though. And I'm fairly confident there's a more elegant solution than the one I mentioned above – Jack Koppa Oct 02 '17 at 12:48
  • Thank you guys, finally I used ViewChild, and modified the variable on end of async function. – Jędrek Markowski Oct 03 '17 at 07:54

3 Answers3

1

I use ngOnChanges with changes. This only will change if the current value is different from the previous value, but if your create an object every time it should work fine.

changes will record every item that is changed within the component.

Try:

ngOnChanges(changes: any) {
        if (changes.applicationsEntry) { // this help to filter out undefined
           console.log(changes.applicationsEntry.currentValue); // your current array should be here
        }
    }
Luca Ritossa
  • 1,118
  • 11
  • 22
Swoox
  • 3,707
  • 2
  • 21
  • 32
1

I very newbie in Angular, but I always use this syntax for input

@Input() applicationsEntry: Array<ApplicationEntryInterface>;
Eliseo
  • 50,109
  • 4
  • 29
  • 67
1

The problem resides in ChangeDetection of Angular, and the way you are "updating" the Array property on the parent component.

Just adding new items to an Array, child components are not noticed in the OnChanges lifecycle hook.

If you want to solve this common issue, on the parent component, do something similar to this:

let shortTermData = new ShortTermApplicationAdapter(application);
this.applications.push(shortTermData);
this.applications = [...this.applications]; // Here is the "magic"

Last line creates a new deep-copy of the Array and allows the ChangeDetection of Angular to be noticed about the change in Arrays.

MigueMike
  • 189
  • 6