Angular 2 - 为什么不能注销输入值

Angular 2 - Why can't you log out the input value

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

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

我现在使用了几个不同的选项,包括 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>

您可以像这样使用表单 valueChanges:

this.myForm.get('lastName').valueChanges.subscribe(val => {
     console.log(val);
     this.activeStateCheck(val);
});  

您可以在组件、OnInt 或 AfterViewInit 中的任何位置使用它。

查看这篇文章了解更多详情:

https://alligator.io/angular/reactive-forms-valuechanges/

从你告诉我们的情况来看,我不确定你是否需要自定义指令。如果你真的想将 class "active" 添加到 non-empty 输入的父级,你可以简单地做

<div [ngClass]={'active': groupForm.get('name').value !== ''}>
  <input formControlName="lastName">
</div>

您甚至可以省略 !== '',因为空字符串是假的。

如果您出于其他原因绝对需要指令,您可以将 formControlName 视为指令 @Input() formControlName; 的输入,但如果这样做,您还需要通过formGroup 中。改变子项的父项行为似乎很麻烦,但是,特别是像您正在做的直接 DOM 操作(改为使用 HostBinding)。我可能会建议将 parent/input 组合配对到一个新组件中。

要确保值何时到达,您必须订阅 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;
  }
}

希望对您有所帮助。

当您说页面加载时间超过 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>

并在您的组件中 class 在数据加载完成后将 finishLoading 设置为 true

this.finishLoading = true;

希望对您有所帮助。