Angular 2使用getter和setter将输入表单值与模型绑定
Posted
技术标签:
【中文标题】Angular 2使用getter和setter将输入表单值与模型绑定【英文标题】:Angular 2 keep input form value in bind with the model using getter and setter 【发布时间】:2017-08-08 19:56:40 【问题描述】:我想使用 getter 和 setter 将输入值绑定到模型。通过这种方式,我可以在写入时防止和/或操纵输入的值。
例如,我想要输入框中的阻止数字。所以,如果写 'abc' 一切正常,那么如果我开始写一个数字,什么都不会发生(模型和输入的值)。问题是,使用下面的代码,我可以在输入框中写任何东西(但模型是正确的)。这意味着输入框的值并不能真正代表我的模型。
注意:除此问题之外的原因是我想使用我的模型来验证表单,例如防止特定字符。我不想使用响应式表单,因为我想将我的验证保存在我的模型而不是组件中。另外请注意,在实际场景中,我将有一个带有内部名称的 UserModel 类和带有验证的其他字段.
@Component(
selector: 'my-app',
template: `
<div>
<h2><input type="text" [(ngModel)]="name"> name</h2>
</div>
`,
)
export class App
_name:string = 'ss';
constructor()
// In real scenario those 2 methods are in a separate class UserModel
get name()
return this._name;
set name()
if ((new RegExp(/^[a-zA-Z]*$/).test(val)))
this._name = val;
【问题讨论】:
有什么问题? 我更新了问题希望现在更清楚了。 请提供一个关于你想要什么的具体例子。你不想要的东西并没有太大帮助;-) 所以如果this._name
持有价值abc
并且用户输入123
但你不想允许数字,那么究竟应该发生什么?
没什么,输入值应该保持abc。 (我在问题中添加了一个更好的例子)
【参考方案1】:
如果您在设置器中操作值,这可能会导致更改检测出现问题,因此ngModel
不会获取更改并且不会更新<input>
要解决你可以使用
export class App
_name:string = 'ss';
constructor(private cdRef:ChangeDetectorRef)
get name()
return this._name;
set name(value:String)
this._name = value + 'x';
this.cdRef.detectChanges()
如果您将值重置为之前的值,您可能需要先传递一个人为的不同值,否则更改检测不会检测到更改,甚至detectChanges()
也不会更新输入。
set name(value:String)
var oldVal = this._name;
this._name = null;
this.cdRef.detectChanges()
this._name = oldVal;
this.cdRef.detectChanges()
【讨论】:
这行得通,但它真的很棘手。我不想在我的所有模型中都有 detectChanges 我不知道更好的方法。 根据我的测试,必须先按上述方法更改值。【参考方案2】:根据@Günter Zöchbauer 的回答,我做了一个解决方法。它不是确定的,可能更抽象,但现在还可以。
export class App implements OnInit
@Input() userModel: UserModel = null;
public _vm;
constructor(private _changeDetectionRef: ChangeDetectorRef)
/**
* Initalize view model, it's important to keep names specular
*/
ngOnInit()
this._vm =
name: this.userModel.name,
surname: this.userModel.surname,
;
/**
* Helper for avoid detectchanges inside the modal, and reduce boilerplate. We could also ad an interface/type of the possibile field value, ie type fieldT= 'name' | 'surname';
* @param field
* @param val
*/
protected updateModel(field, val: string): void
this._vm[field] = null;
this._changeDetectionRef.detectChanges();
this.userModel[field] = val;
this._vm[field] = this.userModel[field];
this._changeDetectionRef.detectChanges();
在用户模型中:
....
public get name(): string
return this.name';
public set name(val: string)
if ((new RegExp(/^[a-zA-Z]*$/).test(val)))
this.name = val;
在模板中:
<input type="text" name="userName" [ngModel]="_vm.name" (ngModelChange)="updateModel('name', $event)">
【讨论】:
【参考方案3】:您可以使用(ngModelChange)
和[ngModel]
在更改时测试模型的内容。
正如您在此 Plunker 中看到的,如果模型无效,则模型不会更改。
@Component(
selector: 'my-app',
template: `
<div>
<h2><input #input type="text" [ngModel]="name" (ngModelChange)='valid(input.value)'> name</h2>
</div>
`,
)
export class App
name:string = 'ss';
constructor()
valid(value)
if(value) //<--- Your test here
this.name = value;
【讨论】:
以上是关于Angular 2使用getter和setter将输入表单值与模型绑定的主要内容,如果未能解决你的问题,请参考以下文章
子模型 getter 和 setter 不能在 angular 2/4 中工作
Angular @Input getter/setter 和非原始值