0
タグでフォームを検証しようとしています。しかし、それはページが読み込まれ、更新されないときを評価するだけです。カスタムAngular2 Validatorは、オブジェクトが更新されたときではなく、ページがロードされたときにのみ評価されます。
https://plnkr.co/edit/umnhybKhNEjswrUJGh3q?p=preview
検証機能:バリデータを使用して
function notEmpty(control) {
if(control.value == null || control.value.length===0) {
return {
notEmpty: true
}
}
return null;
}
コンポーネントやテンプレート:
@Component({
selector: 'my-app',
template: `
<form [formGroup]="myForm">
<div>
(Comma Separated, no duplicates allowed. Enter also submits a tag.)
<div tags formControlName="list" [(ngModel)]="list"> </div>
<div *ngIf="myForm.get('list').valid">List 1 Not Empty.</div>
<div tags formControlName="list2" [(ngModel)]="list2"> </div>
<div *ngIf="myForm.get('list2').valid">List 2 Not Empty.</div>
</div>
</form>
`,
})
export class App {
list:Array<string>;
list2:Array<string>;
myForm:FormGroup;
myList:FormControl;
myList2:FormControl;
constructor(private fb: FormBuilder) {
this.list = [];
this.list2 = ["test"];
this.myList = fb.control('', notEmpty);
this.myList2 = fb.control('', notEmpty);
this.myForm = fb.group({
list: this.myList,
list2: this.myList2
});
}
addItem(item:string) {
this.list.push(item);
}
}
タグコンポーネントと他の子コンポーネント:
const MY_PROVIDER = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(()=> Tags),
multi: true
};
@Component({
selector: 'tags, [tags]',
template: `
<div>
<tag-item *ngFor="let item of tagsList" item="{{item}}" (remove)="removeTag(item)"></tag-item>
<input class="tagInput" #tagInput
(focus)="focus()"
[(ngModel)]="current"
(keydown)="keyDown($event)"
(keyup)="keyUp($event)"
(blur)="blur()"
placeholder="+ Tag"/>
</div>
`,
providers: [MY_PROVIDER]
})
export class Tags implements ControlValueAccessor {
tagsList : Array<string>;
current : string;
@ViewChild('tagInput') child;
inFocus : boolean = false;
constructor() {
this.current = "";
this.tagsList = new Array<string>();
}
focus() {
this.child.nativeElement.focus();
this.inFocus = true;
}
keyDown(event:KeyboardEvent) {
if (event.keyCode === 188 || event.keyCode === 13) { //188 is Comma, 13 is Enter, 32 is Space.
this.pushTag();
} else if (event.keyCode === 8 && this.current.length == 0 && this.tagsList.length > 0){
this.current = this.tagsList.pop();
}
}
keyUp(event:KeyboardEvent) {
if(event.keyCode === 188) {
this.current = '';
}
}
pushTag() {
let str = this.current;
this.current = '';
if(str.trim() != '') {
for(let s of str.split(',')) {
s = this.sanitize(s);
if(s.trim() != '') {
if(!this.tagsList.some(x => x.toLowerCase() === s.toLowerCase()))
this.tagsList.push(s);
}
}
}
}
sanitize(str: string) : string {
let s = str;
s = s.replace('\'', '').replace('"', '').replace(';', '');
return s;
}
blur() {
this.pushTag();
this.inFocus = false;
}
removeTag(value) {
let index = this.tagsList.indexOf(value, 0);
if (index > -1) {
this.tagsList.splice(index, 1);
}
}
clear() {
this.tagsList = new Array<string>();
}
get value(): Array<string> { return this.tagsList; };
set value(v: Array<string>) {
if (v !== this.tagsList) {
this.tagsList = v;
this.onChange(v);
this.onTouched();
}
}
writeValue(value: Array<string>) {
this.tagsList = value;
this.onChange(value);
}
onChange = (_) => {};
onTouched =() => {};
registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
registerOnTouched(fn:() => void): void { this.onTouched = fn; }
}
@Component({
selector: 'tag-item, [tag-item]',
template: `{{item}} <delete-me (click)="removeTag(item)">x</delete-me>`
})
export class TagItem {
@Input() item : string;
@Output() remove : EventEmitter<string> = new EventEmitter();
removeTag(item) {
this.remove.emit(item);
}
}
@Component({
selector:'delete-me',
template:'x'
})
export class DeleteIcon {
}
私は、問題がどこでも 'this.list.push(item);'のようなものにあると思います。新しい配列で再割り当てするのではなく、配列を変更しようとしているので、おそらく変更が発生したことはわかりません。可能な解決策については、[この回答](http://stackoverflow.com/questions/40829951/angular2-ngfor-onpush-change-detection-with-array-mutations)をチェックしてください。 –