Angular 2 - 为啥你不能注销输入值
Posted
技术标签:
【中文标题】Angular 2 - 为啥你不能注销输入值【英文标题】:Angular 2 - Why can't you log out the input valueAngular 2 - 为什么你不能注销输入值 【发布时间】:2018-07-25 05:06:28 【问题描述】:我觉得我必须在这里遗漏一些东西,并想知道是否有更好的方法来做到这一点。
我有一个指令,它基本上将一个类添加到输入字段的父元素。在加载时我需要检查输入字段是否有值,你会认为这很简单......
我现在使用了几个不同的选项,包括 ngOnInit
、AfterContentInit
和 AfterViewInit
。但是对于下面我仍然在AfterContentInit
:
ngAfterContentInit()
console.log(this.el.nativeElement); // Element Object "Value is not empty if you look inside the object."
console.log(this.el.nativeElement.value); // = ''
setTimeout(() =>
console.log(this.el.nativeElement.value); // = 'The Value!'
, 1000);
this.activeStateCheck(this.el.nativeElement);
activeStateCheck(element)
if (element.value !== '')
element.parentElement.classList.add('active');
return true;
我应该指出,所有选项都给出相同的结果。
第一个控制台注销一个空字符串,第二个控制台注销实际字符串。在这种情况下,它是“Grand Tour”。
我的问题是如何在不使用setTimeout
的情况下执行此操作?
似乎必须等待数据加载到页面上才能记录值。但是我的印象是OnInit
是为了等待这个完成?
我之所以想找到更好的解决方案是因为如果页面加载时间超过一秒,那么控制台日志将输出一个空字符串,因此不是一个完整的解决方案。
这是一个被调用指令的例子。注意appPlaceholder
属性:
<fieldset class="form__placeholder">
<input type="text"
id="lastName"
formControlName="lastName"
appPlaceholder>
<label for="lastName"
class="form__placeholder--label">
Lastname:
</label>
</fieldset>
【问题讨论】:
我不确定您为什么要尝试访问本机元素的值。使用响应式表单或模板表单并在组件 ts 文件中设置输入值。显示您的其他组件的代码和 html 会很有帮助 我已将 html 添加到问题中。即将添加 activeStateCheck。 由于您使用的是 formControlName,我假设您使用的是响应式表单。您可以通过执行此操作订阅输入的值更改。[enterFormName].get('lastName') .valueChanges.subscribe(value => 这里你调用你的活动状态检查函数); 对不起,凯文,我不明白。您是否打算将此代码放入指令中?另外,我该如何将 formName 传递给指令? 【参考方案1】:根据您告诉我们的情况,我不确定您是否需要自定义指令。如果你真的想将“活动”类添加到非空输入的父级,你可以简单地做
<div [ngClass]='active': groupForm.get('name').value !== ''>
<input formControlName="lastName">
</div>
您甚至可以省略 !== ''
,因为空字符串是虚假的。
如果您出于其他原因绝对需要指令,您可以将formControlName
视为指令@Input() formControlName;
的输入,但如果您这样做,您还需要传递formGroup
。然而,改变孩子的父母行为似乎很混乱,特别是像你正在做的直接 DOM 操作(使用 HostBinding 代替)。我可能会建议将父/输入组合配对到一个新组件中。
【讨论】:
TypeError: path.split 不是一个函数,如果我只使用 ngClass。如果我使用 NgClass.active 我得到这个错误。 无法绑定到“ngClass.active”,因为它不是“fieldset”的已知属性。 @MaxwellLynn 看起来他们改变了 ngclass 的工作方式,因为我已经阅读了文档。这是[class.active]
,而不是[ngClass.active]
。 Read more here
好的,这就是解决方案,但是您能否将您的代码更新为这个,因为我不得不稍微改变它。 [ngClass]='active': groupForm.get('name').value【参考方案2】:
当您说页面加载时间超过 1 秒时,是否意味着它从服务加载数据以填写表单?
您可以尝试使用ng-container
包装您的表单,并且仅在数据加载完成时才呈现表单。
类似
<ng-container *ngIf="finishLoading">
// ......
<fieldset class="form__placeholder">
<input type="text"
id="lastName"
formControlName="lastName"
appPlaceholder>
<label for="lastName"
class="form__placeholder--label">
Lastname:
</label>
</fieldset>
// ......
</ng-container>
并在数据加载完成后在您的组件类中将 finishLoading 设置为 true
this.finishLoading = true;
希望这会有所帮助。
【讨论】:
【参考方案3】:你可以像这样使用表单 valueChanges:
this.myForm.get('lastName').valueChanges.subscribe(val =>
console.log(val);
this.activeStateCheck(val);
);
您可以在组件、OnInt 或 AfterViewInit 中的任何位置使用它。
查看这篇文章了解更多详情:
https://alligator.io/angular/reactive-forms-valuechanges/
【讨论】:
该逻辑可以保留在指令中吗? 这难道不是只有在用户更新输入而不是页面加载时才有效吗? 尝试将@input 添加到您的指令中,将其传递给 myForm.value.lastName 并在您的指令中使用类似这样的 ngOnChange:***.com/questions/41728043/…【参考方案4】:要确定值何时到达,您必须订阅 HTMLInputElement 输入事件发射器。有了这个,你将永远不会有竞争条件左右。我认为它很适合您的目的。
ngOnInit()
fromEvent(this.el.nativeElement, 'input').subscribe((event) => activeStateCheck(event.target.value);
activeStateCheck(value)
if (value !== '')
this.el.element.parentElement.classList.add('active');
return true;
希望这会有所帮助。
【讨论】:
以上是关于Angular 2 - 为啥你不能注销输入值的主要内容,如果未能解决你的问题,请参考以下文章
为啥 angular.js 在添加动态元素时不够聪明,无法编译 DOM?
为啥我不能在 Angular 2 应用程序中将 RouterStateSnapshot 注入到登录组件中?