2016-12-21 4 views
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 { 

} 
+0

私は、問題がどこでも 'this.list.push(item);'のようなものにあると思います。新しい配列で再割り当てするのではなく、配列を変更しようとしているので、おそらく変更が発生したことはわかりません。可能な解決策については、[この回答](http://stackoverflow.com/questions/40829951/angular2-ngfor-onpush-change-detection-with-array-mutations)をチェックしてください。 –

答えて

0

これはうまくいくようです。

...//Tags Component pushMethod 
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); 
      this.pushed.emit(s); // created an EventEmitter<string> 
      } 
     } 
     } 
    } 
    } 

そして、私の主成分で:

@Component({ 
    selector: 'my-app', 
    template: ` 
    <form [formGroup]="myForm"> 
    <div> 
    (Comma Separated, no duplicates allowed. Enter also submits a tag.) 
    <div tags formControlName="list" (pushed)="update()" [(ngModel)]="list"> </div> 
     <div *ngIf="myForm.get('list').valid">List 1 Not Empty.</div> 
    <div tags formControlName="list2" (pushed)="update()" [(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 
     }); 
    } 

    update() { 
    this.myList.updateValueAndValidity(); 
    this.myList2.updateValueAndValidity(); 
    } 

    addItem(item:string) { 
    this.list.push(item); 
    } 
} 

1がある場合は、しかし、種類のハックに思えるので、私はまだ良い答えたいと思います。

関連する問題