Angular update array printed via *ngFor
Angular update array printed via *ngFor
How could I update array of elements which is printed via *ngFor
? I've set inputs with two-way bindings but it doesn't seem to change the original array. Also tried to set trackBy
but didn't help.
*ngFor
trackBy
Parent component template
<ul>
<app-skill-item
*ngFor="let skill of skills; trackBy: trackByFn"
[skill]="skill" (edited)="updateSkills()"></app-skill-item>
</ul>
In component skills described as skills: Observable<string>;
and fetched from FireBase. I need to update that array and push it back to update document.
skills: Observable<string>;
Child chomponent
<li class="lead" *ngIf="!isEditing" (click)="editStart()">
{{ skill }}
</li>
<li class="lead" *ngIf="isEditing" (click)="editStart()">
<input [(ngModel)]="skill" type="text" (blur)="editEnd()">
</li>
How I get values
constructor() {
this.skillService.getSkills(this.db).subscribe(names => this.skills = names.name);
}
Service
getSkills(db) {
return db.collection('about').doc('skills').valueChanges();
}
Updated the post.
– Sergey
Jun 29 at 16:50
My guess is simply that the observabel returned by this.skillService.getSkills(this.db) only emits once. What happens if you replace
this.skills = names.name
by { console.log('emitting'); this.skills = names.name; }
? How many times is 'emitting' being printed? What is the code of the getSkills() method?– JB Nizet
Jun 29 at 16:57
this.skills = names.name
{ console.log('emitting'); this.skills = names.name; }
The problem is that data binding on each component from
*ngFor
doesn't update corresponding values in skills
– Sergey
Jun 29 at 17:01
*ngFor
skills
Please, answer the questions you're being asked. Note that your description is already a problem: you say that
skills
is an Observable<string>, but you iterate on it, although Observable is not iterable, and you initialize it with this.skills = names.name
, inside a subscribe to valueChanges, so it is probably an Array<string>, not an observable.– JB Nizet
Jun 29 at 17:14
skills
this.skills = names.name
2 Answers
2
You're never modifying anything in the array. What your code does is basically equivalent to
// input binding with [skill]="skill"
childComponent.skill = parentComponent.skills[index];
// ngModel binding
childComponent.skill = "some new entered value";
And that doesn't change anything in the array.
You need to change your design to actually change the value in the array, i.e. have something that does
parentComponent.skills[index] = "some new entered value";
IF you are working with an observable though, you will not be able to edit it. So what you could/should do is subscribe to it, get the first value, and copy it.
In your class/component
constructor() {
this.skillService.getSkills(this.db).pipe(first()).subscribe(names => this.skills = names.name);
}
The reason why I'm suggesting to only take the first value (by piping the first operator), is because we can not necessarily change the observable values, we do not want the observable to emit a new value and overwrite our newly assigned value with something different. The first pipe will automatically unsubscribe from the observable and prevent that from happening. Hopefully this helps.
Changed nothing
– Sergey
Jun 29 at 16:59
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Please post the code you've written so far.
– DiabolicWords
Jun 29 at 16:45