Обработка и проверка группы флажков в Angular2

я не понимаю, как группы флажков должны обрабатываться в модели, управляемой формой в angular2.

модель имеет свойство languages который я создаю вот так:

this.model = {
  languages: []
};

используя FormBuilder создать форму:

this.modelForm = this.formBuilder.group({
  'languages': [model.languages, Validators.required],
});

и шаблона:

<div *ngFor="let language of translateService.get('languages') | async | key_value">
  <input type="checkbox" name="languages[]" formControlName="languages" value="{{ language.key }}" id="language_{{ language.key }}">
  <label attr.for="language_{{ language.key }}">{{ language.value }}</label>
</div>

на div необходим для стилизации (пользовательский флажок),key_value делает ключи и значения языка доступными в цикле, очевидно.

первый проблема связана с проверкой. Если один проверяет и снимает флажок (а другой флажок не установлен), вход по - прежнему действителен-как-то странно.

вторая проблема связана со значением, которое true если два или более языков проверены и false иначе.

тогда есть третья проблема с начальным значением languages который является просто пустым массивом, но заставляет все флажки проверяться изначально (не происходит, если задано начальное значение к string), хотя я не могу обнаружить любые checked атрибут в DOM.

я работаю с последней ионной бета-версией (2.0.0-beta.10) который использует угловую/основную версию 2.0.0-rc.4 и угловой / формы версии 0.2.0.

Итак, есть ли руководство по работе с группами флажков? Какие-нибудь советы или идеи?

2 ответов


первая проблема связана с проверкой. Если один проверяет и снимает флажок (а другой флажок не установлен), вход по - прежнему действителен-как-то странно.

я заметил, что если значение languages является пустым массивом, передает Validations.required проверка.

вторая проблема связана со значением, которое равно true, если два или более языков проверены и false в противном случае.

тогда есть третья проблема с начальным значением языков, которое является просто пустым массивом, но заставляет все флажки проверяться изначально (не происходит, если начальное значение установлено в строку), хотя я не могу обнаружить какой-либо проверенный атрибут в DOM.

я думаю, что проблема заключается в том, как вы привязываете несколько элементов управления к одному FormControl Я считаю FormArray должен быть вовлечен, потенциально с другой FormControl сохранение результата в массив чекбоксов.

Итак, есть ли руководство по работе с группами флажков? Какие-нибудь советы или идеи?

конечно, я сделал удар по его реализации, я сначала опубликую реализацию, а затем некоторые заметки. Вы можете просмотреть его в действии наhttps://plnkr.co/edit/hFU904?p=preview

@Component({
  template: `
    <template [ngIf]="loading">
      Loading languages...
    </template>
    <template [ngIf]="!loading">
      <form [formGroup]="modelForm">
        <div [formArrayName]="'languages'" [class.invalid]="!modelForm.controls.selectedLanguages.valid">
          <div *ngFor="let language of modelForm.controls.languages.controls; let i = index;" [formGroup]="language">
            <input type="checkbox" formControlName="checked" id="language_{{ language.controls.key.value }}">
            <label attr.for="language_{{ language.controls.key.value }}">{{ language.controls.value.value }}</label>
          </div>
        </div>
        <hr>
        <pre>{{modelForm.controls.selectedLanguages.value | json}}</pre>
      </form>
    </template>
  `
})
export class AppComponent {  
    loading:boolean = true;
    modelForm:FormGroup;
    languages:LanguageKeyValues[];

    constructor(public formBuilder:FormBuilder){
    }

    ngOnInit() {

      this.translateService.get('languages').subscribe((languages:LanguageKeyValues[]) => {

        let languagesControlArray = new FormArray(languages.map((l) => {
          return new FormGroup({
            key: new FormControl(l.key),
            value: new FormControl(l.value),
            checked: new FormControl(false),
          });
        }));

        this.modelForm = new FormGroup({
          languages: languagesControlArray,
          selectedLanguages: new FormControl(this.mapLanguages(languagesControlArray.value), Validators.required)
        });

        languagesControlArray.valueChanges.subscribe((v) => {
          this.modelForm.controls.selectedLanguages.setValue(this.mapLanguages(v));
        });

        this.loading = false;
      });
    }

    mapLanguages(languages) {
      let selectedLanguages = languages.filter((l) => l.checked).map((l) => l.key);
      return selectedLanguages.length ? selectedLanguages : null;
    }
}

главное отличие здесь в том, что я слил ваш model.languages в своем modelForm, а теперь повторяю на modelForm.languages FormArray в шаблоне.

modelForm.languages стало modelForm.selectedLanguages, и теперь является вычисленным значением на основе проверенных значений в modelForm.languages. Если ничего не выбрано, modelForm.selectedLanguages имеет значение null, чтобы не прошли проверку.

modelForm не создается, пока не будут доступны языки, это в основном личные предпочтения, я уверен, что вы можете асинхронно прикрепить languages и selectedLanguages на modelForm, но это упрощает вещи, чтобы построить его синхронно.

достал translateService.get('languages') | async, я заметил, что некоторые странное поведение с этой функцией вызывается в шаблоне, и я предпочитаю разворачивать мои наблюдаемые в компоненте в любом случае, чтобы захватить состояния загрузки/ошибки.

это не так элегантно, как может быть некоторый собственный контроль формы массива флажков, но он чистый и очень гибкий. Проверьте в plunker и дайте мне знать если вы имеете любые вопросы!


Если вы установите флажок, а затем снимите его, FormControl все равно покажет его как действительный, даже если он не установлен. Может случиться так, что он принимает только истинные и ложные ценности.Вы можете попробовать этот образец кода, как он работал для меня -

                             mustBeChecked(control: FormControl): {[key: string]: string} {
                              if (!control.value) {
                              return {mustBeCheckedError: 'Must be checked'};
                               } else {
                                       return null;
                                      }
                                }

вы также можете обратиться к этой plunker

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

существуют различные обходные пути для нескольких флажков, таких как использование

event.target.checked

вместо значения из модели.

вы можете использовать его как в этом примере -

           <input type="checkbox"  
                (change)="expression && expression.Option1=$event.target.checked ? true : undefiend"
                 [ngModel]="expression?.Option1">
           <input type="checkbox"  
                (change)="expression && expression.Option2=$event.target.checked ? true : undefiend"
                 [ngModel]="expression?.Option2">