Home > Software engineering >  Refreshing data in two parts of the same Angular component
Refreshing data in two parts of the same Angular component

Time:02-25

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" >
  • Related