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();
}





Please post the code you've written so far.
– DiabolicWords
Jun 29 at 16:45





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 skillsis 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.

Comments

Popular posts from this blog

paramiko-expect timeout is happening after executing the command

Export result set on Dbeaver to CSV

Opening a url is failing in Swift