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

Я хочу использовать радиокнопку в форме с помощью 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

когда страница загружена, первый переключатель не отмечен, и изменения не привязаны к модели

Любая идея?

Ответ 1

используйте [значение] = "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/>

Edit:

Как было предложено thllbrg "Для angular 2.1+ используйте [(ngModel)] вместо [(ng-model)]"

Ответ 2

Примечание. Теперь привязка переключателя привязки поддерживается в RC4 - см. этот ответ

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

Источник: https://github.com/angular2-school/angular2-radio-button

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

Ответ 3

Мое ручное обходное решение, которое включает в себя ручное обновление 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>

Ответ 4

Вот лучший способ использования переключателей в Angular2. Нет необходимости использовать событие (click) или RadioControlValueAccessor для изменения значения свойства привязки, при этом свойство [checked] выполняет трюк.

<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: как создать переключатели из перечисления и добавить двустороннюю привязку? Он работает по меньшей мере с Angular 2 RC5.

Ответ 5

Эта проблема решается в версии 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>

Ответ 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, который передает текущий элемент методу.

Ответ 7

Радиовход пока не поддерживается. Должен быть аксессуар для ввода радиовхода (аналогично флажку one, где он устанавливает 'checked' attr здесь), но я не нашел. Поэтому я реализовал один; вы можете проверить это здесь.

Ответ 8

[значение] = "item" с помощью * ngFor также работает с реактивными формами в Angular 2 и 4

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

Ответ 9

Следующее исправило мою проблему, рассмотрите возможность добавления радиовхода в тег 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>

Ответ 10

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

  1. Работает с шаблоном старого кода, с которым мне приходится работать.
  2. Я создал вспомогательный класс, чтобы попытаться уменьшить количество операторов if  в обработчике кликов и для обработки любой группы переключателей.

Это решение включает в себя

  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 вспомогательного класса вызывается. Передается модель для радио кнопки, которая была нажата. Вспомогательный класс устанавливает для логического поля "selected" переданной модели значение true, а для поля "selected" всех других моделей переключателей устанавливается значение false.

Во время инициализации компонент должен создать экземпляр вспомогательного класса со списком всех моделей переключателей в группе. В этом примере "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");
    }
  }
}

Ответ 11

Простейшее решение и обходное решение:

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

Ответ 12

Я создал версию, используя только событие click для загруженных элементов и передавая значение выбора в функцию "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

Ответ 13

Хотя этот ответ может быть не лучшим в зависимости от вашего варианта использования, он работает. Вместо использования переключателя для выбора мужского и женского пола, использование <select> </select> прекрасно работает как для сохранения, так и для редактирования.

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

Все вышеперечисленное должно хорошо работать для редактирования с использованием FormGroup с patchValue. Для создания вы можете использовать [(ngModel)] вместо formControlName. Все еще работает.

Сантехнические работы, связанные с переключателем один, я выбрал вместо этого выбрать. Визуально и с точки зрения UX, это не кажется лучшим, но с точки зрения разработчика, это намного проще.

Ответ 14

Вот код, который я использую, который работает с 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);
    }
  }

}

Ответ 15

Пример листинга радио Angular 8:

Источник Ссылка

enter image description here

Ответ 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>

Ответ 16

Это может быть неправильное решение, но это вариант, который, возможно, поможет кому-то.

До сих пор я получал значение radioButtons, используя метод (click), например:

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

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

Но после поиска я нашел хороший метод, я еще не пробовал, но кажется, что это хорошо, используя ссылку [(ng-model)] здесь, чтобы github здесь. это использует RadioControlValueAccessor для радио, а также для флажка. здесь работает # plnkr # для этого метода здесь .