I have a list of players and on selecting a player name , I'm displaying the respective player details by introducing a boolean flag (isPlayerSelected) in each formGroup . One disadvantage with this approach is that the page response is slow (when there are more number of items) as it has to update the boolean flag in each formGroup by using patchValue . Is there a better way to do instead of introducing boolean flag?
Please help . I have attached the
CodePudding user response:
If you get the selected player form control, then you can directly use it in the form
selectedPlayer: FormGroup;
selectPlayer(player: any) {
player.isPlayerSelected = !player.isPlayerSelected;
this.selectedPlayer = this.playerDetailsControls.find(
(item) => player?.id === item.get('id')?.value
) as FormGroup;
}
<form *ngIf="selectedPlayer" [formGroup]="selectedPlayer">
Player Name : <input formControlName="playerName" /><br /><br />
Role: <input formControlName="role" /><br /><br />
Country: <input formControlName="country" /><br /><br />
<hr />
<button (click)="save()" [disabled]="!form.valid">Save</button>
</form>
CodePudding user response:
Why don't you just reuse your existing variable selectedIndex
for this?
You can just set it onClick like (click)="selectedIndex = i"
.
Then you can just get rid of your whole selectPlayer
function.
In your player details section you don't even have to loop over the whole array. You can simply directly bind to the formGroup based on the selectedIndex
variable.
CodePudding user response:
As Fabian Strathaus wrote, you just need to stick to the index. It is not a good idea to pollute the object with fields like isPlayerSelected
as this will be sent to the server on save.
I have altered the stackblitz for an example you can use.
CodePudding user response:
To solve it is better to use the properties of the reactive forms.
In this example I created a "FormDetailSelected" and this formGroup helps me to create a dynamic form detail. Is in the click label where I change the form detail.
<div>
<div *ngFor="let playerDetail of playerDetailsFromServer; let i = index">
<label (click)="changeFormDetail(i)">
{{ playerDetail.playerName }}
</label>
</div>
<hr />
<h3>Player Details</h3>
<div>
<form [formGroup]="formDetailSelected">
<div>
Player Name : <input formControlName="playerName" /><br /><br />
Role: <input formControlName="role" /><br /><br />
Country: <input formControlName="country" /><br /><br />
<hr />
</div>
<button (click)="save()" [disabled]="!form.valid">Save</button>
</form>
</div>
</div>
TS
export class PlayersListComponent implements OnInit {
form: FormGroup;
formDetailSelected: FormGroup;
playerDetailsFromServer = [];
selectedIndex: number = 0;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.playerDetailsFromServer = [
{
id: 'id1',
playerName: 'Sachin',
country: 'INDIA',
role: 'Batsman',
},
{
id: 'id2',
playerName: 'Ponting',
country: 'Australia',
role: 'Batsman',
},
{
id: 'id3',
playerName: 'Kallis',
country: 'RSA',
role: 'All Rounder',
},
{
id: 'id4',
playerName: 'Lara',
country: 'WEST INDIES',
role: 'Batsman',
},
{
id: 'id5',
playerName: 'Flintoff',
country: 'ENGLAND',
role: 'All Rounder',
},
];
this.form = this.fb.group({
playerDetails: this.fb.array([]),
});
const playerDetailsControl = this.form.get('playerDetails') as FormArray;
for (let { id, isPlayerSelected, country, playerName, role } of this
.playerDetailsFromServer) {
const formGroup = new FormGroup({
id: new FormControl(id),
isPlayerSelected: new FormControl(isPlayerSelected),
country: new FormControl(country),
playerName: new FormControl(playerName),
role: new FormControl(role),
});
playerDetailsControl.push(formGroup);
}
this.changeFormDetail(0);
}
save() {
console.log('Saved Details', this.form.value);
}
changeFormDetail(i: number) {
this.selectedIndex = i;
let array = this.form.get('playerDetails') as FormArray;
this.formDetailSelected = array.controls[this.selectedIndex] as FormGroup;
}
}
With this logic you don't need to iterate constantly with "is selected" conditions.