我正在尝试将父组件中的值绑定到子组件,以便它可以重用。
父 - component.ts
profile:any = {name:"", mobile:""}
父-component.html
<app-profile-name label="Name" [(name)]="profile.name"></app-profile-name>
child component.html
<div class="form-group">
<label for="">Name</label>
<input type="text" class="form-control" [(ngModel)]="name" appUppercase
required minlength="3" maxlength="50" pattern="[a-zA-Z\s\.]*" #nameInput="ngModel" (keyup)="onKeyup($event)">
<div *ngIf="nameInput.invalid && (nameInput.dirty || nameInput.touched)" class="form-control-text text-danger animated fadeIn">
<small *ngIf="nameInput.errors.required" class="d-block">Name is required</small>
<small *ngIf="nameInput.errors.pattern" class="d-block">Alphabets dot and space is only allowed</small>
<small *ngIf="nameInput.errors.minlength" class="d-block">Name should be minimum 3 characters</small>
<small *ngIf="nameInput.errors.maxlength" class="d-block">Name should be maximum 3 characters</small>
</div>
</div>
Child component.ts
import { Component, OnInit, Input, Output, EventEmitter, DoCheck, ViewChild } from '@angular/core';
@Component({
selector: 'app-profile-name',
templateUrl: './profile-name.component.html',
styleUrls: ['./profile-name.component.css']
})
export class ProfileNameComponent implements OnInit, DoCheck {
@Input() name: String;
@Output() nameChange: EventEmitter<any> = new EventEmitter();
@ViewChild('nameInput') nameInput:any;
constructor() { }
ngOnInit() {
}
ngDoCheck() {
setTimeout(()=>{
this.nameChange.next(this.name);
});
}
}
这段代码非常好用。
以下是验证失败但仍能看到数据绑定的测试输入案例
所以我在代码中进行了修改
ngDoCheck() {
setTimeout(()=>{
if(this.nameInput.invalid){ // added this if condition
this.nameChange.next("")
return;
}
this.nameChange.next(this.name);
});
}
以下是以下案例
现在,如果我按A并且由于验证最小长度3不符合,我将获得空的profile.name
如果我输入A1ASDF,由于验证失败,我将获得空的profile.name。
现在,如果我输入ALAKS,现在我已经清除了验证,因此我在我的个人资料中获得了价值。名称
如果我输入数字1,将设置ALAKS1,它将失败验证。所以我的profile.name同时转到“”,this.name也消失了,我得到一个空的输入框。
问题是如何恢复输入框值并仅获取父组件中的有效输入值。
希望我明白这个问题。
工作答案 特别感谢@Andiry。
当我最终进入无限循环时,我将@Andiry的逻辑变为模糊,现在它的工作正常。
这是更新后的代码
<input type="text" class="form-control" [(ngModel)]="name" appUppercase
required minlength="3" maxlength="50" pattern="[a-zA-Z\s\.]*" #nameInput="ngModel" (blur)="onInputBlur()">
profile-name.component.ts文件
import { Component, OnInit, Input, Output, EventEmitter, ViewChild } from '@angular/core';
@Component({
selector: 'app-profile-name',
templateUrl: './profile-name.component.html',
styleUrls: ['./profile-name.component.css']
})
export class ProfileNameComponent implements OnInit {
@Input() name:string;
@Output() nameChange: EventEmitter<any> = new EventEmitter();
@ViewChild('nameInput') nameInput:any;
constructor() { }
ngOnInit() {
}
onInputBlur(){
let name = this.name;
this.nameChange.emit(this.nameInput.invalid ? '' : this.name);
setTimeout(()=>{
this.name = name;
});
}
}
答案 0 :(得分:0)
尝试将您的子组件重写为:
export class ProfileNameComponent implements OnInit, DoCheck {
nameValue: string;
lastIsInvalid: boolean = true;
@Input() get name() {
return this.nameValue;
}
@Output() nameChange: EventEmitter<any> = new EventEmitter();
set name(val) {
let name = val;
setTimeout(_ => {
this.nameValue = val;
this.nameChange.emit(this.nameInput.invalid ? '' : this.nameValue);
if (this.lastIsInvalid !== this.nameInput.invalid) {
setTimeout(_ => this.name = name);
}
this.lastIsInvalid = this.nameInput.invalid;
});
}
@ViewChild('nameInput') nameInput:any;
constructor() { }
ngOnInit() {
}
}
STACKBLITZ:https://stackblitz.com/edit/angular-emq3ef?file=app%2Fprofile-name%2Fprofile-name.component.ts