Angular2 - Прив'язка радіо кнопок


120

Я хочу використовувати перемикач у формі, що використовує 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/>

Початкове значення model.options дорівнює 1

при завантаженні сторінки перша перемикач не перевіряється і модифікації не прив’язуються до моделі

Будь-яка ідея?


Відповіді:


108

використовувати [value] = "1" замість value = "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/>

Редагувати:

Як запропонував thllbrg "Для кутових 2.1+ використовуйте [(ngModel)]замість [(ng-model)]"


7
Яке призначення атрибута ng-control? Схоже, все працює без цього.
Монсеньйор

4
У Angular 4+ ви повинні використовувати [(ngModel)]замість [(ng-model)]. Прочитайте ще раз .
Клаудіо Голландія

1
Це працює лише над додаванням нового режиму. Не працює в режимі редагування. Я не міг знайти, в чому причина. У свіжому відкритому присвоєному значенні для роботи моделі, але не працює, коли я отримую значення з сервера і показую на екрані.
Вінот Кумар

4
У моєму випадку я закінчила використання value="1" [(ngModel)]="model.options". Замикання valueквадратних дужок не вийшло
Сільван Д Еш

2
Дивно, але і в моєму випадку мені довелося використовувати value = "1" замість [value] = "1". Я використовую Angular 6
codingbbq

61

Примітка - прив'язка радіо кнопок тепер підтримується функцією в RC4 і далі - див. Цю відповідь

Приклад перемикача за допомогою користувальницького RadioControlValueAccessor, подібного до CheckboxControlValueAccessor ( оновлений кутовим 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; }
}

Джерело: https://github.com/angular2-school/angular2-radio-button

Демо-версія Plunker: http://plnkr.co/edit/aggee6An1iHfwsqGoE3q?p=preview


4
Так само, як і запитання повинні містити відповідний код у питанні , і відповіді повинні. Це теоретично може відповісти на питання, але найкраще було б включити сюди основні частини відповіді для майбутніх користувачів і надати посилання для довідки. Відповіді, що переважають у посиланнях, можуть стати недійсними через гниття посилань .
Могсдад

чудово .. дивно, що він не входить в рамки
Мурад Зуабі

Чудове рішення! Одне невелике доповнення: я використовую вхід css [type = "radio"]: перевіряється на стиль, але це працює для мене лише під час використання нативної _Element _elementRef замість лише _elementRef: this._renderer.setElementProperty(this._elementRef.nativeElement, 'checked', value == this._elementRef.nativeElement.value);
bas

2
@GregWoods Оновив публікацію з новими змінами та дякує за запит на тягнення,
Нідін Віняякан

1
Тепер він підтримується в основному, використовуючи кутовий rc4 і вище
Ckln

45

Моє ручне вирішення, яке передбачає оновлення вручну, model.optionsколи вибрана нова перемикача:

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' };
}

Це Plunkerдемонструє вищесказане, а також те, як за допомогою кнопки змінити вибрану радіо кнопку - тобто довести, що прив'язка даних є двосторонньою:

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

У мене є два питання. по-перше: за get debug()функцією, що getозначає? друге: чи є така альтернатива, як ця відповідь для прапорців? введіть код також для прапорців. спасибі +1 за чудову відповідь.
Pardeep Jain

2
@PardeepJain, getє функцією аксесуара TypeScript . Залиште запитання для прапорців.
Марк Райкок

можна надіслати параметри таким чином "{{debug (abc)}}"?
Pardeep Jain

1
@PardeepJain, див. Plnkr.co/edit/iH3Te9EK7Y1dPXMzfWt6?p=preview . Ви не можете викликати сеттера як функцію, тому Anotherdate('2015-05-18T02:30:56')не буде працювати. Інструменти телефонують, коли ви намагаєтеся призначити значення властивості. У своєму планку я створив setDate()функцію \ hat приймає нове значення дати, яке потім призначається Anotherdate. Це призначення автоматично викликає сетер.
Марк Райкок

1
@PardeepJain, {{}}прив'язки переоцінюються кожен цикл виявлення змін. Я реалізований ngDoCheck()в AppComponent в планкурі для підрахунку циклів виявлення змін. З цього ми бачимо, що виявлення змін викликається 3 рази. У режимі розробки прив'язки перевіряються двічі , отже, 6 разів.
Марк Райкок

36

Ось найкращий спосіб використання радіо кнопок у Angular2. Немає необхідності використовувати подію (клік) або RadioControlValueAccessor для зміни значення прив'язаного властивості, налаштування властивості [перевірено] виконує завдання.

<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/>

Я опублікував приклад використання радіо кнопок: Angular 2: як створити радіо кнопки з enum та додати двостороннє прив'язування? Він працює щонайменше з кутового 2 RC5.


2
Це працює лише над додаванням нового режиму. Не працює в режимі редагування. Я не міг знайти, в чому причина. У свіжому відкритому присвоєному значенні для роботи моделі, але не працює, коли я отримую значення з сервера та показую на екрані.
Вінот Кумар

1
@VinothKumar Вам вдалося зробити так, щоб режим редагування працював? У мене той самий випуск
Дейв Нотаж

18

Це питання вирішується у версії Angular 2.0.0-rc.4 відповідно у формах.

Включати "@angular/forms": "0.2.0" в package.json.

Тоді продовжте головний завантажувач в основному. Відповідна частина:

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

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

Я маю це у .html і працює прекрасно: value: {{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>

це правильна відповідь станом на rc4, і просто додати, радіо можна використовувати із перерахунками.
Рон

8
під керуванням RC7, мені потрібно було розмістити дужки навколо [значення]
Brian Vander Plaats

1
Я думаю, вам потрібні дужки, тому що ур, використовуючи змінну вашого компонента замість рядка, у моєму випадку @ відповідь Zolcsi спрацювала нормально!
Naeem Baghi

1
Ця частина з disableDeprecatedFormsі provideFormsвиглядає чарівною і не має ніякого сенсу. Що роблять ці речі? Це зайвий нечитабельний код, який робить непередбачувані речі невідомого масштабу.
Герман

6

Я шукав правильний метод обробки цих радіо кнопок, ось приклад рішення, яке я знайшов тут:

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

Зауважте onSelectionChange, який передає поточний елемент методу.


4

Здається, радіовведення ще не підтримується. Там повинно бути вхідний значення радіо збруя (аналогічно CheckBox в одному , де він встановлює «перевірив» атр тут ) , але я не знайшов. Тому я реалізував один; ви можете перевірити це тут .



@JimB: на жаль, схоже, семантика рідного є різною .
Kiara Grouwstra

4

[value] = "item" за допомогою * ngFor також працює з Реактивними формами у куті 2 та 4

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

1
Як зробити один вибір ??
Белтер

4

Нижче виправлено мою проблему. Будь ласка, подумайте про те, щоб додати радіо вхід до formтегу та використовувати [value]тег для відображення значення.

<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>

3

Ось рішення, яке працює для мене. Він включає прив'язку радіо кнопок - але не прив'язку до ділових даних, а замість цього прив'язку до стану радіо кнопки. Це, мабуть, НЕ найкраще рішення для нових проектів, але підходить для мого проекту. У моєму проекті є багато існуючих кодів, написаних за іншою технологією, яку я переношу на Angular. Старий код слідує шаблону, в якому код дуже зацікавлений вивчити кожну перемикач, щоб побачити, чи є обраним. Рішення - це варіація рішень для обробки кліків, деякі з яких уже були згадані в Stacka Overflow. Додана вартість цього рішення може бути:

  1. Працює з малюнком старого коду, з яким я маю працювати.
  2. Я створив клас помічників, щоб спробувати зменшити кількість висловлювань "якщо" в обробці кліків і обробити будь-яку групу радіо кнопок.

Це рішення передбачає

  1. Використання іншої моделі для кожної радіо кнопки.
  2. Встановлення атрибута "перевірено" за допомогою моделі перемикача.
  3. Передача моделі натиснутого перемикача класу помічників.
  4. Клас помічників гарантує, що моделі сучасні.
  5. У режимі "часу надсилання" це дозволяє старому коду вивчити стан радіо кнопок, щоб побачити, який з них вибраний, вивчаючи моделі.

Приклад:

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

...

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

...

Коли користувач натискає перемикач, викликається метод selectButton класу помічників. Він передає модель для перемикача, який натиснув. Клас помічників встановлює булеве "вибране" поле переданого в моделі істинного та встановлює значення "вибране" для всіх інших моделей перемикачів на хибне.

Під час ініціалізації компонент повинен побудувати екземпляр класу helper із переліком усіх моделей перемикачів у групі. У прикладі "radioButtonGroupList" буде екземпляром хелперного класу, код якого:

 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");
    }
  }
}

2

Приклад 8 кутового радіопереліку:

Посилання на джерело

введіть тут опис зображення

Відповідь JSON

    [
            {
                "moduleId": 1,
                "moduleName": "Employee",
                "subModules":[
                    {
                        "subModuleId": 1,
                        "subModuleName": "Add Employee",
                        "selectedRightType": 1,
                    },{
                        "subModuleId": 2,
                        "subModuleName": "Update Employee",
                        "selectedRightType": 2,
                    },{
                        "subModuleId": 3,
                        "subModuleName": "Delete Employee",
                        "selectedRightType": 3,
                    }
                ]
            },  
            {
                "moduleId": 2,
                "moduleName": "Company",
                "subModules":[
                    {
                        "subModuleId": 4,
                        "subModuleName": "Add Company",
                        "selectedRightType": 1,
                    },{
                        "subModuleId": 5,
                        "subModuleName": "Update Company",
                        "selectedRightType": 2,
                    },{
                        "subModuleId": 6,
                        "subModuleName": "Delete Company",
                        "selectedRightType": 3,
                    }
                ]
            },  
            {
                "moduleId": 3,
                "moduleName": "Tasks",
                "subModules":[
                    {
                        "subModuleId": 7,
                        "subModuleName": "Add Task",
                        "selectedRightType": 1,
                    },{
                        "subModuleId": 8,
                        "subModuleName": "Update Task",
                        "selectedRightType": 2,
                    },{
                        "subModuleId": 9,
                        "subModuleName": "Delete Task",
                        "selectedRightType": 3,
                    }
                ]
            }
    ]

HTML-шаблон

        <div *ngFor="let module of modules_object">
            <div>{{module.moduleName}}</div>
            <table width="100%">

                <thead>
                    <tr>
                        <th>Submodule</th>
                        <th>
                            <input type="radio" name="{{module.moduleName}}_head_radio" [(ngModel)]="module.selHeader" (change)="selAllColumn(module)" [value]="1"> Read Only
                        </th>
                        <th>
                            <input type="radio" name="{{module.moduleName}}_head_radio" [(ngModel)]="module.selHeader" (change)="selAllColumn(module)" [value]="2"> Read Write
                        </th>
                        <th>
                            <input type="radio" name="{{module.moduleName}}_head_radio" [(ngModel)]="module.selHeader" (change)="selAllColumn(module)" [value]="3"> No Access
                        </th>
                    </tr>
                </thead>

                <tbody>
                    <tr *ngFor="let sm of module.subModules">
                        <td>{{sm.subModuleName}}</td>
                        <td>
                            <input type="radio" [checked]="sm.selectedRightType == '1'" [(ngModel)]="sm.selectedRightType" name="{{sm.subModuleId}}_radio" [value]="1"> 
                        </td>
                        <td class="cl-left">
                            <input type="radio" [checked]="sm.selectedRightType == '2'" [(ngModel)]="sm.selectedRightType" name="{{sm.subModuleId}}_radio" [value]="2"> 
                        </td>
                        <td class="cl-left">
                            <input type="radio" [checked]="sm.selectedRightType == '3'" [(ngModel)]="sm.selectedRightType" name="{{sm.subModuleId}}_radio" [value]="3"> 
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>

1

Найпростіший спосіб вирішення:

<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
}

2
Як би ви в цьому випадку встановили для початку перемикач на значення за замовчуванням?
EricC

Також буде ситуація, коли користувач часто міняє вибір, кожного разу буде функція, виконана для кожної перевірки,
blackHawk

1

Я створив версію, використовуючи подію лише клацання на завантажених елементах і передаючи значення виділення у функцію "getSelection" та оновивши модель.

У вашому шаблоні:

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

Ваш клас:

export class App {

  price:string;

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

  constructor() {   }

  model = new SomeData(this.price);

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

Див. Приклад: https://plnkr.co/edit/2Muje8yvWZVL9OXqG0pW?p=info


1

Наскільки ця відповідь може бути не найкращою, залежно від випадку використання, вона працює. Замість використання кнопки "Радіо" для вибору "Чоловік і жінка", <select> </select>ідеально використовує роботи, як для збереження, так і для редагування.

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

Вищезазначене має зробити чудово, для редагування за допомогою FormGroup за допомогою patchValue. Для створення ви можете використовувати [(ngModel)]замістьformControlName . Досі працює.

Сантехнічні роботи, пов'язані з перемикачем, я вирішив замість цього вибрати. Зрозуміло, що це візуально та UX, це не найкраще, але, з точки зору розробника, це набагато простіше.


1

При зміні кнопки Радіо отримайте значення відповідних кнопок за допомогою цих рядків

<label class="radio-inline">
<input class="form-check-input" type="radio" [(ngModel)]="dog" name="cat"  checked (change)="onItemChange($event)" value="Dog" />Dog</label>
<label class="radio-inline">
<input class="form-check-input" type="radio" [(ngModel)]="cat" name="cat"   (change)="onItemChange($event)" value="Cat"  />Cat</label>

https://stackblitz.com/edit/angular-jpo2dm?embed=1&file=src/app/app.component.html


0

Ось якийсь код, який я використовую, який працює з Angular 7

(Примітка. Раніше я іноді використовував інформацію, надану відповіддю Ентоні Бренелье, яку я ціную. Але, принаймні, для Angular 7, ця частина:

 [checked]="model.options==2"

Я виявив себе непотрібним.)

Моє рішення тут має три переваги:

  1. Відповідає найпоширенішим рішенням. Тож це добре для нових проектів.
  2. Також дозволяє код перемикача бути подібним до коду Flex / ActionScript. Це особисто важливо, оскільки я перекладаю Flex-код на Angular. Як і код Flex / ActionScript, він дозволяє коду працювати на об'єкті перемикача, щоб перевірити чи зняти прапорець або дізнатись, чи перевірена перемикач.
  3. На відміну від більшості рішень, які ви побачите, це дуже об'єктно-орієнтоване. Однією з переваг є організація: вона об'єднує в собі поля прив'язки даних радіо-кнопки, такі як вибрані, включені, видимі та, можливо, інші.

Приклад HTML:

       <input type="radio" id="byAllRadioButton"
                 name="findByRadioButtonGroup"
                 [(ngModel)]="findByRadioButtonGroup.dataBindingValue"
                 [value]="byAllRadioButton.MY_DATA_BINDING_VALUE">         

      <input type="radio" id="byNameRadioButton"
                 name="findByRadioButtonGroup" 
                 [(ngModel)]="findByRadioButtonGroup.dataBindingValue"
                 [value]="byNameRadioButton.MY_DATA_BINDING_VALUE">

Приклад TypeScript:

 findByRadioButtonGroup : UIRadioButtonGroupModel
    = new UIRadioButtonGroupModel("findByRadioButtonGroup",
                                  "byAllRadioButton_value",
                                  (groupValue : any) => this.handleCriteriaRadioButtonChange(groupValue)
                                  );

  byAllRadioButton : UIRadioButtonControlModel
    = new UIRadioButtonControlModel("byAllRadioButton",
    "byAllRadioButton_value",
    this.findByRadioButtonGroup) ;

  byNameRadioButton : UIRadioButtonControlModel
    = new UIRadioButtonControlModel("byNameRadioButton",
    "byNameRadioButton_value",
    this.findByRadioButtonGroup) ;



  private handleCriteriaRadioButtonChange = (groupValue : any) : void => {

    if ( this.byAllRadioButton.selected ) {

      // Do something

    } else if ( this.byNameRadioButton.selected ) {

      // Do something

    } else {
      throw new Error("No expected radio button selected");
    }
  };

Використовуються два класи:

Група класів радіо кнопок:

export class UIRadioButtonGroupModel {


  private _dataBindingValue : any;


  constructor(private readonly debugName : string,
              private readonly initialDataBindingValue : any = null,   // Can be null or unspecified
              private readonly notifyOfChangeHandler : Function = null       // Can be null or unspecified
  ) {

    this._dataBindingValue = initialDataBindingValue;
  }


  public get dataBindingValue() : any {

    return this._dataBindingValue;
  }


  public set dataBindingValue(val : any) {

    this._dataBindingValue = val;
    if (this.notifyOfChangeHandler != null) {
      MyAngularUtils.callLater(this.notifyOfChangeHandler, this._dataBindingValue);
    }
  }



  public unselectRadioButton(valueOfOneRadioButton : any) {

    //
    // Warning: This method probably never or almost never should be needed.
    // Setting the selected radio button to unselected probably should be avoided, since
    // the result will be that no radio button will be selected.  That is
    // typically not how radio buttons work.  But we allow it here.
    // Be careful in its use.
    //

    if (valueOfOneRadioButton == this._dataBindingValue) {
      console.warn("Setting radio button group value to null");
      this.dataBindingValue = null;
    }
  }

};

Клас радіо кнопок

export class UIRadioButtonControlModel {


  public enabled : boolean = true;
  public visible : boolean = true;


  constructor(public readonly debugName : string,
              public readonly MY_DATA_BINDING_VALUE : any,
              private readonly group : UIRadioButtonGroupModel,
              ) {

  }


  public get selected() : boolean {

    return (this.group.dataBindingValue == this.MY_DATA_BINDING_VALUE);
  }


  public set selected(doSelectMe : boolean) {

    if (doSelectMe) {
      this.group.dataBindingValue = this.MY_DATA_BINDING_VALUE;
    } else {
      this.group.unselectRadioButton(this.MY_DATA_BINDING_VALUE);
    }
  }

}

-1

Це може бути не правильним рішенням, але це також варіант сподівання, що він комусь допоможе.

До цього моменту я отримував значення радіо-кнопок методом (click), наприклад:

<input type="radio" name="options" #male (click)="onChange(male.value)">Male
<input type="radio" name="options" #female (click)="onChange(female.value)">Female

і у файлі .ts я встановив значення попередньо визначеної змінної, щоб отримати значення onChangeфункції getter .

Але після того як знаходити я знайшов хороший метод я have't спробував ще , але, здається , це один хороший , використовуючи [(ng-model)]посилання тут , щоб GitHub тут . це використовується і RadioControlValueAccessorдля радіо, і для прапорця. ось робочий # plnkr # для цього методу тут .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.