Ion-checkbox - setting values and using as an array?


#1

I have an app I’m working on that should allow the user to create a new Team object, by entering some basic details (team name, home venue etc.) and also select Players in that team based on a master list of players configured elsewhere in the app.

In the Team object the selected players will be stored as an array of player IDs (each ID is a UUID formatted string)

For the UI, I’m using in an but I have hit upon two problems:

  1. I can’t set a “value” for the checkbox - it only seems to return either “true” or “false”, but I want it to send through the player ID for the value when checked.

  2. I’d like to have it behave like a HTML form and allow me to read an array of the checked player IDs from the FormGroup. This doesn’t seem possible - it looks like I have to dynamically create a new FormControl for each player so that the true/false value can be bound to it.

I suppose the basic question is, is it possible to do something like this:

<ion-checkbox formControlName="playerIds[]" value="{{ player.id }}"></ion-checkbox>

#2
<form [formGroup]="form">
  <ion-list>
    <ion-item *ngFor="let player of allPlayers">
      <ion-label>{{player.name}}</ion-label>
      <ion-checkbox [formControlName]="player.id"></ion-checkbox>
    </ion-item>

    <ion-item>
      <button ion-button type="button" (click)="makeTeam()">make team</button>
    </ion-item>

    <ion-item *ngFor="let player of teamPlayers">
      <ion-label>{{player}}</ion-label>
    </ion-item>
  </ion-list>
  </form>
allPlayers: Player[] = [
    {id: '123', name: 'joe blow'},
    {id: '234', name: 'carmen miranda'},
    {id: '345', name: 'andy airhead'},
  ];
  teamPlayers: string[] = ['234'];
  form: FormGroup;

constructor(fb: FormBuilder) {
  let fbargs = {};
  this.allPlayers.forEach(player => fbargs[player.id] = []);
  this.form = fb.group(fbargs);
  this.teamPlayers.forEach(playerid => this.form.get(playerid).setValue(true));
}

makeTeam(): void {
  this.teamPlayers = [];
  this.allPlayers.forEach((player) => {
    if (this.form.get(player.id).value) {
      this.teamPlayers.push(player.id);
    }
  });
}

Obviously, this could be extended to prepend something like ‘player-’ to the control names to avoid collisions, and there’s no reason why teamPlayers has to be only ids: it could just as easily be the whole Player. Hopefully this will get you started.


#3

Thanks for the reply, this isn’t a million miles away from what I’m doing currently, so pleased to know that this is the best way rather than trying to emulate the HTML array structure.

Couple of questions though:

  1. What is the purpose of the [] around formControlName in the view template?

  2. I have other standard form controls on the form currently, and am then looping through the players array and adding controls to the form dynamically with addControl - however, when I reload the view (i.e. go to another page and come back to it) I get errors saying that no form control could be found for “playerId-”

I assume this is something to do with Ionic’s caching, but I’ve tried moving my formgroup building code into a private method and calling that on both the constructor and the ionViewWillEnter method and it doesn’t cure it. Am I missing something obvious?

Here’s the code for the private method:

this.teamDetailsForm = this.formBuilder.group( {
	name: [
		( this.selectedTeam.name ) ? this.selectedTeam.name : '',
		Validators.compose( [ Validators.required, Validators.maxLength( 50 ) ] )
	],
	date: [
		( this.selectedTeam.date ) ? this.selectedTeam.date : new Date().toISOString(),
		Validators.compose( [ Validators.required ] )
	]
} );

// add formControls for each player name
this.playerDataStore.loadFromStorage().then( () => {
	for ( let player of this.playerDataStore.store ) {
		let playerIsInTeam = false;
		if ( this.selectedTeam.playerIds && this.selectedTeam.playerIds.indexOf( player.id ) > -1 ) {
			playerIsInTeam = true;
		}
		if ( !this.teamDetailsForm.contains( 'playerId-' + player.id ) ) {
			this.teamDetailsForm.addControl( 'playerId-' + player.id, new FormControl( playerIsInTeam ) );
		}
	}
} );