Angular 2 - 为啥你不能注销输入值

Posted

技术标签:

【中文标题】Angular 2 - 为啥你不能注销输入值【英文标题】:Angular 2 - Why can't you log out the input valueAngular 2 - 为什么你不能注销输入值 【发布时间】:2018-07-25 05:06:28 【问题描述】:

我觉得我必须在这里遗漏一些东西,并想知道是否有更好的方法来做到这一点。

我有一个指令,它基本上将一个类添加到输入字段的父元素。在加载时我需要检查输入字段是否有值,你会认为这很简单......

我现在使用了几个不同的选项,包括 ngOnInitAfterContentInitAfterViewInit。但是对于下面我仍然在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 注入到登录组件中?

为啥我不能将第 11 个角度更新为第 12 个?

为啥 Angular 2 ngOnChanges 不响应输入数组推送

为啥要撤销访问令牌?

Angular:都2021年了,你为啥还没用Angular