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

121

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

Ответы:

109

используйте [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 "Для использования angular 2.1+ [(ngModel)]вместо [(ng-model)]"

Атал Кишор
источник
7
Какова цель атрибута ng-control? Вроде все работает и без него.
Monsignor
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 ( обновлен с помощью 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

Нидин Винаякан
источник
4
Точно так же, как вопросы должны включать соответствующий код в вопрос , ответы тоже должны быть. Теоретически это может ответить на вопрос, но было бы лучше включить сюда основные части ответа для будущих пользователей и предоставить ссылку для справки. Ответы, в которых преобладают ссылки, могут стать недействительными из-за гниения ссылок .
Mogsdad 08
отлично .. странно, что это не входит в рамки
Мурад Зуаби
Отличное решение! Одно небольшое дополнение: я использую css input [type = "radio"]: проверено на стиль, но у меня это работает только при использовании nativeElement _elementRef вместо только _elementRef:this._renderer.setElementProperty(this._elementRef.nativeElement, 'checked', value == this._elementRef.nativeElement.value);
bas
2
@GregWoods Обновил пост, добавив новые изменения и спасибо за
пулреквест
1
Теперь он изначально поддерживается с использованием angular 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)}}'?
Пардип Джайн,
1
@PardeepJain, см. Plnkr.co/edit/iH3Te9EK7Y1dPXMzfWt6?p=preview . Вы не можете вызывать сеттер как функцию, поэтому Anotherdate('2015-05-18T02:30:56')работать не будет. Сеттеры вызываются, когда вы пытаетесь присвоить значение свойству. В моем плункере я создал setDate()функцию, которая принимает новое значение даты, которое затем присваивается Anotherdate. Это назначение автоматически вызовет сеттер.
Марк Рэйкок
1
@PardeepJain, {{}}привязки переоцениваются каждый цикл обнаружения изменений. Я реализовал ngDoCheck()в AppComponent плункер для подсчета циклов обнаружения изменений. Из этого мы видим, что обнаружение изменений вызывается 3 раза. В режиме разработки привязки проверяются дважды , то есть 6 раз.
Марк Райкок
36

Вот лучший способ использовать переключатели в Angular2. Нет необходимости использовать событие (щелчок) или 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.

Энтони Бренельер
источник
2
Это работает только над добавлением нового режима. Не работает в режиме редактирования. Я не мог найти причину. В свежем открытом назначенном значении для модели работает, но не работает, когда я получаю значения с сервера и показываю на экране. Но если я показываю значение метки, показывающее, но не работающее, проверено.
Винот Кумар
1
@VinothKumar Удалось заставить работать режим редактирования? У меня такая же проблема
Дэйв Ноттэдж,
18

Эта проблема решена в версии Angular 2.0.0-rc.4 соответственно в формах.

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

Затем расширите свой загрузочный файл в main. Соответствующая часть:

...
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>
Zolcsi
источник
это правильный ответ для rc4, и просто чтобы добавить, радио можно использовать с перечислениями.
Рон,
8
при запуске RC7 мне нужно было заключить [значение] в скобки
Брайан Вандер Плаатс
1
Я думаю, вам нужны скобки, потому что ur использует переменную вашего компонента вместо строки, в моем случае ответ @Zolcsi работал нормально!
Наим Баги
1
Эта часть с disableDeprecatedFormsи provideFormsвыглядит волшебной и не имеет никакого смысла. Что они делают? Это избыточный нечитаемый код, создающий непредсказуемые вещи неизвестного масштаба.
Gherman
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: к сожалению, похоже, что семантика нативной отличается .
Киара Гроустра
4

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

<label *ngFor="let item of items">
    <input type="radio" formControlName="options" [value]="item">
    {{item}}
</label>`
Коллин Перселл
источник
1
Как сделать одиночный выбор ??
Belter
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>
rc.adhikari
источник
3

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

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

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

  1. Использование разных моделей для каждой радиокнопки.
  2. Установка атрибута "checked" с помощью модели переключателя.
  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");
    }
  }
}
user2367418
источник
2

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

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

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

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

MrLukrative
источник
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 это не кажется лучшим, но с точки зрения разработчика это намного проще.

KhoPhi
источник
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. В отличие от большинства решений, которые вы увидите, оно очень объектно. Одним из преимуществ является организация: она группирует вместе поля привязки данных радиокнопки, такие как selected, enabled, visible и, возможно, другие.

Пример 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);
    }
  }

}
user2367418
источник
-1

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

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

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

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

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

Пардип Джайн
источник