无法使用#input 将输入值从视图传递到组件

Posted

技术标签:

【中文标题】无法使用#input 将输入值从视图传递到组件【英文标题】:Cannot pass input value from view to component using #input 【发布时间】:2021-04-02 01:11:55 【问题描述】:

我在 html 中有以下组件,我只是尝试将输入值传递给组件:

<mat-accordion class="example-headers-align">
    <mat-expansion-panel [expanded]="expanded" hideToggle>
      <mat-form-field *ngIf="expanded">
        <input #empName matInput type="text" formControlName="empName"/>
      </mat-form-field>
    </mat-expansion-panel>
      <button *ngIf="expanded" mat-button (click)="add(empName.value)">Add</button>
    </div>
</mat-accordion>

但是,组件方法中的值未定义,即使我尝试传递empName,而不是empName.value,参数也未定义。那么,这种方法的错误是什么?如何在不使用[(ngModel)] 的情况下传递输入值?

add(data)  // data --> undefined
  this.add.emit(data)

我还在&lt;button *ngIf="expanded" mat-button (click)="add(empName.value)"&gt;Add&lt;/button&gt; 上收到“无法读取未定义的属性‘值’”错误。

【问题讨论】:

我没有在我的解决方案中提到这一点,但是有一个额外的 &lt;/div&gt; 会破坏你的模板 【参考方案1】:

说明

你所做的是完全有效的,但你没有考虑到模板变量的范围。

使用结构指令会创建阻止使用这些变量的范围/边界,如您所见:https://angular.io/guide/template-reference-variables#template-variable-scope

因此,要以您希望的方式解决您的问题,您需要处理您的模板并删除 *ngIfs 的使用

部分解决方案

下面的代码只是省略了*ngIfs,就像你期望的那样工作(当然这不是一个完整的解决方案,因为没有*ngIfs 的组件的行为与你想要的不同)

<div>
    <mat-accordion class="example-headers-align">
        <mat-expansion-panel [expanded]="false" hideToggle>
            <mat-form-field>
                <input #empName matInput type="text" formControlName="empName" >
      </mat-form-field>
        </mat-expansion-panel>
        <button mat-button (click)="add(empName.value)">Add</button>
    </mat-accordion>
</div>

您可以在这个 stackblitz 项目中查看它:https://stackblitz.com/edit/angular-ivy-c64ppz?file=src/app/app.component.html(请忽略材料组件上的控制台错误,这些不是这里的重点:P)

一个可能的解决方案

可以在最小程度上更改您的代码但允许您保留实现的一件事可能是避免 *ngIfs 而是通过 css 隐藏元素,如下所示:

模板:

<div>
    <mat-accordion class="example-headers-align">
        <mat-expansion-panel [expanded]="expended" hideToggle>
            <mat-form-field [ngClass]="'hidden': !expanded">
                <input #empName matInput type="text" formControlName="empName" >
      </mat-form-field>
        </mat-expansion-panel>
        <button [ngClass]="'hidden': !expanded" mat-button (click)="add(empName.value)">Add</button>
    </mat-accordion>
</div>

css:

.hidden 
  display: none;

这里又是一个堆栈闪电战,您可以在其中看到它的工作原理:https://stackblitz.com/edit/angular-ivy-iamrut?file=src/app/app.component.html

【讨论】:

我的荣幸 :) ,我认为重要的是解释为什么标准角度特征的东西不起作用,而不是寻找替代方法来完成你想要的。无论如何,我认为范围只是模板变量唯一棘手的方面,所以我相信你在这里亲身体验它是件好事:)【参考方案2】:

您将formControlName 与响应式表单一起使用,因此如果您想访问此字段的值,则必须从formGroup 表单对象访问它。

类似这样的:

employeeForm: FormGroup;

以及您可以像这样访问的表单字段的值:

employeeForm.value.empName

所以在你的函数中尝试像这样传递值:

<button *ngIf="expanded" mat-button (click)="add(employeeForm.value.empName)">Add</button>

【讨论】:

【参考方案3】:

在你的 html 文件中

<mat-accordion class="example-headers-align">
        <mat-expansion-panel [expanded]="expanded" hideToggle>
          <mat-form-field *ngIf="expanded">
            <input matInput type="text" [formControl]="empName"/>
          </mat-form-field>
        </mat-expansion-panel>
          <button *ngIf="expanded" mat-button (click)="add()">Add</button>
        </div>
    </mat-accordion>

在你的 ts 文件中

empName = new FormControl('');

add()  // remove the parameter
  // this.add.emit(data), try if it is working first
     console.log(this.empName);

希望对你有帮助。

编码愉快!

【讨论】:

非常感谢,但实际上我正在寻找不使用[(ngModel)] 的解决方案。有可能吗? @Fredrick 我已经编辑了答案。检查它是否有效。 谢谢,我又想知道为什么不能轻松地传递值?我想知道是否可以不使用表单控件或 ngModel。

以上是关于无法使用#input 将输入值从视图传递到组件的主要内容,如果未能解决你的问题,请参考以下文章

使用@Input 将异步值从父组件传递到子组件

无法通过命令将值从视图传递到viewmodel

如何将值从mysql传递到create视图中的表单域

无法将选中的值从自定义复选框组件传递给父组件

使用 location.href 将值从视图传递到控制器为 null

将输入值从控制器传递到 MVC 中的视图