web-dev-qa-db-fra.com

Angular2 - Reliure de bouton radio

Je souhaite utiliser un bouton radio dans un formulaire utilisant Angular 2

Options : <br/>

1 : <input name="options" ng-control="options" type="radio" value="1"  [(ng-model)]="model.options" ><br/>

2 : <input name="options" ng-control="options" type="radio" value="2" [(ng-model)]="model.options" ><br/>

valeur initiale de model.options est 1

lorsque la page est chargée, le premier bouton radio n'est pas coché et les modifications ne sont pas liées au modèle

Une idée ?

119
Mourad Zouabi

utiliser [valeur] = "1" au lieu de valeur = "1"

<input name="options" ng-control="options" type="radio" [value]="1"  [(ngModel)]="model.options" ><br/>

<input name="options" ng-control="options" type="radio" [value]="2" [(ngModel)]="model.options" ><br/>

Edit:

Comme suggéré par thllbrg "Pour angular 2.1+, utilisez [(ngModel)] au lieu de [(ng-model)]"

102
Atal Kishore

Remarque: la liaison des boutons radio est désormais une fonctionnalité prise en charge dans RC4 - voir cette réponse

Exemple de bouton radio utilisant RadioControlValueAccessor personnalisé, similaire à CheckboxControlValueAccessor ( mis à jour avec Angular 2 rc-1 )

App.ts

import {Component} from "@angular/core";
import {FORM_DIRECTIVES} from "@angular/common";
import {RadioControlValueAccessor} from "./radio_value_accessor";
import {bootstrap} from '@angular/platform-browser-dynamic';

@Component({
    selector: "my-app",
    templateUrl: "template.html",
    directives: [FORM_DIRECTIVES, RadioControlValueAccessor]
})
export class App {

    model;

    constructor() {
        this.model = {
            sex: "female"
        };
    }

}

template.html

<div>
    <form action="">
        <input type="radio" [(ngModel)]="model.sex"  name="sex" value="male">Male<br>
        <input type="radio" [(ngModel)]="model.sex"  name="sex" value="female">Female
    </form>

    <input type="button" value="select male" (click)="model.sex='male'">
    <input type="button" value="select female" (click)="model.sex='female'">
    <div>Selected Radio: {{model.sex}}</div>
</div>

radio_value_accessor.ts

import {Directive, Renderer, ElementRef, forwardRef} from '@angular/core';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/common';

export const RADIO_VALUE_ACCESSOR: any = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => RadioControlValueAccessor),
    multi: true
};

@Directive({
   selector:
       'input[type=radio][ngControl],input[type=radio][ngFormControl],input[type=radio][ngModel]',
   Host: {'(change)': 'onChange($event.target.value)', '(blur)': 'onTouched()'},
   bindings: [RADIO_VALUE_ACCESSOR]
})
export class RadioControlValueAccessor implements ControlValueAccessor {
   onChange = (_) => {};
   onTouched = () => {};

   constructor(private _renderer: Renderer, private _elementRef: ElementRef) {}

   writeValue(value: any): void {
       this._renderer.setElementProperty(this._elementRef.nativeElement, 'checked', value == this._elementRef.nativeElement.value);
   }
   registerOnChange(fn: (_: any) => {}): void { this.onChange = fn; }
   registerOnTouched(fn: () => {}): void { this.onTouched = fn; }
}

Source: https://github.com/angular2-school/angular2-radio-button

Démonstration en direct de Plunker: http://plnkr.co/edit/aggee6An1iHfwsqGoE3q?p=preview

61
Nidin Vinayakan

Ma solution de contournement manuelle, qui implique la mise à jour manuelle de model.options lorsqu'un nouveau bouton radio est sélectionné:

template: `
  <label *ngFor="let item of radioItems">
    <input type="radio" name="options" (click)="model.options = item" 
     [checked]="item === model.options">
    {{item}}
  </label>`

class App {
  radioItems = 'one two three'.split(' ');
  model      = { options: 'two' };
}

Cette Plunker illustre ce qui précède, ainsi que l’utilisation d’un bouton pour modifier le bouton radio sélectionné - c’est-à-dire pour prouver que la liaison de données est bidirectionnelle:

<button (click)="model.options = 'one'">set one</button>
42
Mark Rajcok

Voici la meilleure façon d'utiliser les boutons radio dans Angular2. Il n'est pas nécessaire d'utiliser l'événement (clic) ou un RadioControlValueAccessor pour modifier la valeur de la propriété liée, la définition de la propriété [vérifié] suffit.

<input name="options" type="radio" [(ngModel)]="model.options" [value]="1"
       [checked]="model.options==1" /><br/>
<input name="options" type="radio"  [(ngModel)]="model.options" [value]="2"
       [checked]="model.options==2" /><br/>

J'ai publié un exemple d'utilisation de boutons radio: Angular 2: comment créer des boutons radio à partir d'enum et ajouter une liaison bidirectionnelle? Cela fonctionne à partir d'au moins Angular 2 RC5.

36

Ce problème est résolu dans la version Angular 2.0.0-rc.4, respectivement dans les formulaires.

Incluez "@angular/forms": "0.2.0" dans package.json.

Ensuite, étendez votre bootstrap dans la fenêtre principale. Partie pertinente:

...
import { AppComponent } from './app/app.component';
import { disableDeprecatedForms, provideForms } from '@angular/forms';

bootstrap(AppComponent, [
    disableDeprecatedForms(),
    provideForms(),
    appRouterProviders
]);

J'ai ceci en .html et fonctionne parfaitement: valeur: {{buildTool}}

<form action="">
    <input type="radio" [(ngModel)]="buildTool" name="buildTool" value="gradle">Gradle <br>
    <input type="radio" [(ngModel)]="buildTool" name="buildTool" value="maven">Maven
</form>
18
Zolcsi

Je cherchais la bonne méthode pour gérer ces boutons radio. Voici un exemple de solution trouvée ici:

<tr *ngFor="let entry of entries">
    <td>{{ entry.description }}</td>
    <td>
        <input type="radio" name="radiogroup" 
            [value]="entry.id" 
            (change)="onSelectionChange(entry)">
    </td>
</tr>

Notez que onSelectionChange qui transmet l'élément actuel à la méthode.

6
Pini Cheyni

[valeur] = "item" utilisant * ngFor fonctionne aussi avec les formes réactives dans Angular 2 et 4

<label *ngFor="let item of items">
    <input type="radio" formControlName="options" [value]="item">
    {{item}}
</label>`
4
Colleen Purcell

Ce qui suit corrige mon problème, pensez à ajouter une entrée radio à l'intérieur de la balise form et à utiliser la balise [value] pour afficher la valeur.

<form name="form" (ngSubmit)="">
    <div *ngFor="let item of options">
        <input [(ngModel)]="model.option_id" type="radio" name="options" [value]="item.id"> &nbsp; {{ item.name }}
    </div>
</form>
4
rc.adhikari

L'entrée radio ne semble pas encore être prise en charge. Il devrait y avoir un accesseur de valeur d'entrée radio (semblable à la case à cocher n , où il définit 'vérifié' attr ici ) mais je n'en ai trouvé aucun. Alors j'ai mis en place un; vous pouvez le vérifier ici .

4
barbatus

Voici une solution qui fonctionne pour moi. Cela implique une liaison par bouton radio - mais pas par liaison aux données de l'entreprise, mais par opposition à l'état du bouton radio. Ce n'est probablement pas la meilleure solution pour les nouveaux projets, mais convient à mon projet. Mon projet a une tonne de code existant écrit dans une technologie différente que je porte à Angular. L'ancien code suit un schéma dans lequel le code est très intéressé à examiner chaque bouton radio pour voir s'il s'agit du bouton sélectionné. La solution est une variante des solutions de gestion des clics, dont certaines ont déjà été mentionnées dans Stack Overflow. La valeur ajoutée de cette solution peut être:

  1. Fonctionne avec le modèle de code ancien avec lequel je dois travailler.
  2. J'ai créé une classe d'assistance pour tenter de réduire le nombre d'instructions "if" dans le gestionnaire de clics et pour gérer un groupe de boutons radio.

Cette solution implique

  1. Utiliser un modèle différent pour chaque bouton radio.
  2. Définir l'attribut "vérifié" avec le modèle du bouton radio.
  3. Passer le modèle du bouton radio cliqué à la classe d'assistance.
  4. La classe d'assistance s'assure que les modèles sont à jour.
  5. Lors de la "soumission", ceci permet à l'ancien code d'examiner l'état des boutons radio pour voir celui qui est sélectionné en examinant les modèles.

Exemple:

<input type="radio"
    [checked]="maleRadioButtonModel.selected"
    (click)="radioButtonGroupList.selectButton(maleRadioButtonModel)"

...

 <input type="radio"
    [checked]="femaleRadioButtonModel.selected"
    (click)="radioButtonGroupList.selectButton(femaleRadioButtonModel)"

...

Lorsque l'utilisateur clique sur un bouton radio, la méthode selectButton de la classe d'assistance est appelée. Il est passé le modèle pour le bouton radio qui a été cliqué. La classe d'assistance définit le champ "sélectionné" booléen du modèle passé dans le paramètre true et le champ "sélectionné" de tous les autres modèles de bouton radio à la valeur false.

Lors de l'initialisation, le composant doit construire une instance de la classe d'assistance avec une liste de tous les modèles de boutons radio du groupe. Dans l'exemple, "radioButtonGroupList" serait une instance de la classe d'assistance dont le code est:

 import {UIButtonControlModel} from "./ui-button-control.model";


 export class UIRadioButtonGroupListModel {

  private readonly buttonList : UIButtonControlModel[];
  private readonly debugName : string;


  constructor(buttonList : UIButtonControlModel[], debugName : string) {

    this.buttonList = buttonList;
    this.debugName = debugName;

    if (this.buttonList == null) {
      throw new Error("null buttonList");
    }

    if (this.buttonList.length < 2) {
      throw new Error("buttonList has less than 2 elements")
    }
  }



  public selectButton(buttonToSelect : UIButtonControlModel) : void {

    let foundButton : boolean = false;
    for(let i = 0; i < this.buttonList.length; i++) {
      let oneButton : UIButtonControlModel = this.buttonList[i];
      if (oneButton === buttonToSelect) {
        oneButton.selected = true;
        foundButton = true;
      } else {
        oneButton.selected = false;
      }

    }

    if (! foundButton) {
      throw new Error("button not found in buttonList");
    }
  }
}
3
user2367418

Autant que cette réponse risque de ne pas être la meilleure en fonction de votre cas d'utilisation, cela fonctionne. Au lieu d'utiliser le bouton Radio pour une sélection Masculin et Féminin, l'utilisation de <select> </select> fonctionne parfaitement, à la fois pour la sauvegarde et pour l'édition.

<select formControlName="gender" name="gender" class="">
  <option value="M">Male</option>
  <option value="F">Female</option>
</select>

Ce qui précède devrait suffire, pour l'édition à l'aide de FormGroup avec patchValue. Pour créer, vous pouvez utiliser [(ngModel)] au lieu de formControlName. Fonctionne encore.

Les travaux de plomberie impliqués avec le bouton radio un, j'ai choisi d'aller avec le select. Visuellement et au niveau UX, cela ne semble pas être le meilleur, mais du point de vue du développeur, c'est beaucoup plus facile.

1
Rexford

J'ai créé une version en utilisant simplement un événement de clic sur les éléments chargés, en passant la valeur de la sélection à la fonction "getSelection" et en mettant à jour le modèle.

Dans votre modèle:

<ul>
     <li *ngFor="let p of price"><input type="radio" name="price"      (click)="getValue(price.value)" value="{{p}}" #price> {{p}} 
     </li>
</ul>

Ta classe:

export class App {

  price:string;

  price = ["1000", "2000", "3000"];

  constructor() {   }

  model = new SomeData(this.price);

  getValue(price){
    this.model.price = price;
  }
}

Voir l'exemple: https://plnkr.co/edit/2Muje8yvWZVL9OXqG0pW?p=info

1
MrLukrative

Solution la plus simple et solution de contournement:

<input name="toRent" type="radio" (click)="setToRentControl(false)">
<input name="toRent" type="radio" (click)="setToRentControl(true)">

setToRentControl(value){
    this.vm.toRent.updateValue(value);
    alert(value); //true/false
}
1
Jacek Pudysz