【问题标题】: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 传递给指令?

标签: angular angular2-directives


【解决方案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:stackoverflow.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;
      }
    }
    

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2017-01-23
      • 1970-01-01
      • 2020-02-06
      • 2017-08-30
      • 2011-02-09
      • 2021-10-23
      • 1970-01-01
      • 1970-01-01
      • 2017-11-27
      相关资源
      最近更新 更多