私のアプリケーションには、さまざまなフォームがあり、そのうちのいくつかにはチェックボックスがあります。
そういうわけで、checkbox-es + カスタムバリデータのディレクティブを作成することにしました。
このディレクティブでは私が使用していますDoCheck
が、おそらくこれは、そのような種類のフォーム ディレクティブを作成する Angular2 の方法ではありません。すべてが正しく機能していますが、チェックボックス/ボタンのフォーム ディレクティブを作成するためのより良い方法があると思います。
Angular2 フォーム API には、CheckboxControlValueAccessor ディレクティブとControlValueAccessorインターフェイスがあることがわかりました。多分私はそれらを使うべきですか?はいの場合、それを使用する方法の例はありますか?
私の質問は: これは Angular2 フォームのチェックボックス ディレクティブを作成する正しい方法ですか?
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);
}
}
}