3

私のアプリケーションには、さまざまなフォームがあり、そのうちのいくつかにはチェックボックスがあります。
そういうわけで、checkbox-es + カスタムバリデータのディレクティブを作成することにしました。

このディレクティブでは私が使用していますDoCheckが、おそらくこれは、そのような種類のフォーム ディレクティブを作成する Angular2 の方法ではありません。すべてが正しく機能していますが、チェックボックス/ボタンのフォーム ディレクティブを作成するためのより良い方法があると思います。

Angular2 フォーム API には、CheckboxControlValueAccessor ディレクティブとControlValueAccessorインターフェイスがあることがわかりました。多分私はそれらを使うべきですか?はいの場合、それを使用する方法の例はありますか?

私の質問は: これは Angular2 フォームのチェックボックス ディレクティブを作成する正しい方法ですか?

これが私のソリューションPlunkerの例です

app.ts

import {Component, OnInit, NgModule, ViewEncapsulation} from '@angular/core'
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import {BrowserModule} from '@angular/platform-browser'
import { FormBuilder, FormGroup, FormArray, Validators } from '@angular/forms'
import { ValidatedMulticheckboxComponent } from 'src/directives/validated-multicheckbox.component'
import { CustomValidatorsService } from 'src/services/custom-validator.service.ts'

@Component({
  selector: 'my-app',
  templateUrl: 'src/app.html',
  styleUrls: ['src/app.css'],
  encapsulation: ViewEncapsulation.None
})
export class App implements OnInit {
  colorOptions:Array<string> = ["red", "green", "blue"];

  constructor(public fb: FormBuilder, private cvs: CustomValidatorsService) {
  }

  ngOnInit() {
    this.myForm = this.fb.group({
      userName: ['', Validators.compose([Validators.required])],
      colors: new FormArray([], Validators.compose([this.cvs.requiredArray]))
    })
  }

}

@NgModule({
  imports: [ BrowserModule, ReactiveFormsModule ],
  declarations: [ App, ValidatedMulticheckboxComponent ],
  providers: [ CustomValidatorsService ]
  bootstrap: [ App ]
})
export class AppModule {}

app.html

<div>
  <h2>Checkbox validation</h2>
</div>
<form [formGroup]="myForm" novalidate>
  <div class="form-group">
    <label for="userName">User name</label>
    <input type="text" class="form-control" id="userName" name="userName" formControlName="userName"/>
  </div>
   <div class="form-group">
      <validated-multicheckbox [control]="myForm.controls['colors']" [options]="colorOptions"
        [model]="myForm.controls['colors']" >
        <label for="colors">Select your colors</label>
      </validated-multicheckbox>
    </div>
</form>

<pre>Is myForm valid?: <br>{{myForm.valid | json}}</pre>
<pre>form value: <br>{{myForm.value | json}}</pre>

ディレクティブ/validated-multicheckbox.component.ts

import { Component, Input, DoCheck } from '@angular/core'
import { FormArray, FormControl } from '@angular/forms'
import { CustomValidatorsService } from 'src/services/custom-validator.service.ts'

@Component({
  selector: 'validated-multicheckbox',
  templateUrl: 'src/directives//validated-multicheckbox.component.html'
})
export class ValidatedMulticheckboxComponent implements DoCheck {

  @Input() control: FormControl = new FormControl();
  @Input() options: any;
  @Input() model: any;

  private errorMessages: Array<string> = [];
  private isValid: boolean;
  numberOfClicks:number = 0;

  constructor(private svc: CustomValidatorsService) {   }

  ngDoCheck() {
    this.errorMessages = this.svc.buildErrorMessages(this.control);
    this.isValid = this.errorMessages.length === 0;
  }

  public hasOption(option): boolean {
    return (this.model.value.indexOf(option) > -1);
  }

  changeCheckbox(option: any) {  
    this.numberOfClicks++;
    var currentScheduleControls: FormArray = this.model as FormArray;
    var index = currentScheduleControls.value.indexOf(option);
    if (index > -1) currentScheduleControls.removeAt(index);
    else currentScheduleControls.push(new FormControl(option)); 
  }

}

ディレクティブ/validated-multicheckbox.component.html

<div class="form-group">
  <ng-content></ng-content>
  <div class="row">
    <div class="col-xs-12 col-sm-6" *ngFor="let option of options">
       <label ><input type="checkbox" (change)="changeCheckbox(option)" [checked]="hasOption(option)" [value]="option" />{{option}}</label>
    </div>
  </div>
  <div [hidden]="isValid || numberOfClicks === 0" class="alert alert-danger">
    <div *ngFor="let errMsg of errorMessages">
      {{errMsg}}
    </div>
  </div>
</div>

services/custom-validator.service.ts

import { Injectable } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';

const requireMessage = 'The field is required'; 

@Injectable()
export class CustomValidatorsService {

  private errorMessage: Array<string>;

  constructor() { }

  requiredArray(control:FormControl){
    return (control.value.length > 0) ? null : {'required' : true};
  }

  buildErrorMessages( control: FormControl){

    this.errorMessage = [];

    this.buildControlErrorMessages(control);

    return this.errorMessage;
  }

  buildControlErrorMessages(control: FormControl){
    if(control.hasError('required')){
      this.errorMessage.push(requireMessage);
    }

  }

}
4

0 に答える 0