Within one component, I have a property that's an array with some info displayed in a summary as well as an area for making changes. Trying to get the summary data to update reactively.
Here's a simplified example...
// discovery.component.ts
@Component({
selector: 'app-discovery',
templateUrl: './discovery.component.html',
styleUrls: ['./discovery.component.scss']
})
export class DiscoveryComponent implements OnInit {
levels: [
{ title: 'title1', rating: 0 },
{ title: 'title2', rating: 3 },
{ title: 'title3', rating: 5 },
]
}
<!--discovery.component.html-->
<!--Summary info-->
<div *ngFor="let level of levels">
{{ level.title }} {{ level.rating }}
</div>
<!--Editing area-->
<div *ngFor="let level of levels; let i = index">
{{ level.title }}
<input type="range" min="0" max="5" name="level{{i}}" [(ngModel)]="level.rating" [value]="level.rating">
{{ level.rating }}
</div>
If I change the slider (input type=range), the number following it in the editor area updates dynamically (great). The problem is that the change is not seen in the summary info above.
What is the best approach to having the summary info dynamically update as changes are made in the editor area?
Is an Observable the way to do that? Most of what I've read, Observables are great for sharing info across multiple components.
Is there a simpler approach when all the data is in the same component?
CodePudding user response:
The best approach I can think of is using ReactiveForms
with the FormArray
clause.
In your component declare the value as a form array, I use FormControl as the value of rating
because you need to update it dynamically:
this.ratingsForm = this.formBuilder.array([
{ title: 'title1', rating: new FormControl(0) },
{ title: 'title2', rating: new FormControl(3) },
{ title: 'title3', rating: new FormControl(5) },
]);
Then in your HTML loop through it as controls
<div *ngFor="let level of this.ratingsForm.controls">
{{ level.value.title }} {{ level.value.rating.value }}
</div>
<!--Editing area-->
<div *ngFor="let level of this.ratingsForm.controls; let i = index">
{{ level.value.title }}
<input type="range" min="0" max="5" name="level{{i}}" [formControl]="level.value.rating">
{{ level.value.rating.value }}
</div>
The formBuilder
comes from a DI on the constructor:
contructor(private formBuilder: FormBuilder)
This is a very simple example, you can refactor it to look better.
Generally speaking, its better to use ReactiveForms
instead of the old ngModel
.
CodePudding user response:
please remove the value attributes
<input type="range" min="0" max="5" name="level{{i}}" [(ngModel)]="level.rating" >