在 Angular 中的 INPUT 元素上使用 ngModel 中的管道

Using Pipes within ngModel on INPUT Elements in Angular

我有一个 HTML 输入字段。

<input 
    [(ngModel)]="item.value" 
    name="inputField" 
    type="text" 
/>

我想格式化它的值并使用现有管道:

.... 
[(ngModel)]="item.value | useMyPipeToFormatThatValue" 
....

并得到错误信息:

Cannot have a pipe in an action expression

如何在这种情况下使用管道?

您不能在模板语句中使用 Template expression operators(pipe, save navigator):

(ngModelChange)="Template statements"

(ngModelChange)="item.value | useMyPipeToFormatThatValue=$event"

https://angular.io/guide/template-syntax#template-statements

Like template expressions, template statements use a language that looks like JavaScript. The template statement parser differs from the template expression parser and specifically supports both basic assignment (=) and chaining expressions (with ; or ,).

However, certain JavaScript syntax is not allowed:

  • new
  • increment and decrement operators, ++ and --
  • operator assignment, such as += and -=
  • the bitwise operators | and &
  • the template expression operators

所以应该这样写:

<input [ngModel]="item.value | useMyPipeToFormatThatValue" 
      (ngModelChange)="item.value=$event" name="inputField" type="text" />

Plunker Example

<input [ngModel]="item.value | useMyPipeToFormatThatValue" 
      (ngModelChange)="item.value=$event" name="inputField" type="text" />

此处的解决方案是将绑定拆分为 one-way 绑定和事件绑定 - [(ngModel)] 语法实际上包含了它们。 [] 是 one-way 绑定语法,() 是事件绑定语法。一起使用时 - [()] Angular 将其识别为 shorthand 并以 one-way 绑定和事件绑定的形式将 two-way 绑定连接到组件对象值。

不能对管道使用 [()] 的原因是管道只能与 one-way 绑定一起使用。因此,您必须拆分管道以仅对 one-way 绑定进行操作并单独处理事件。

有关详细信息,请参阅 Angular Template Syntax

我尝试了上面的解决方案,但进入模型的值是格式化值,然后返回并给我 currencyPipe 错误。所以我不得不

  [ngModel]="transfer.amount | currency:'USD':true"
                                   (blur)="addToAmount($event.target.value)"
                                   (keypress)="validateOnlyNumbers($event)"

关于 addToAmount 的功能 -> 更改模糊导致 ngModelChange 给我光标问题。

removeCurrencyPipeFormat(formatedNumber){
    return formatedNumber.replace(/[$,]/g,"")
  }

并删除其他非数值。

validateOnlyNumbers(evt) {
  var theEvent = evt || window.event;
  var key = theEvent.keyCode || theEvent.which;
  key = String.fromCharCode( key );
  var regex = /[0-9]|\./;
  if( !regex.test(key) ) {
    theEvent.returnValue = false;
    if(theEvent.preventDefault) theEvent.preventDefault();
  }

我的解决方案在下面给出,这里 searchDetail 是一个对象..

<p-calendar  [ngModel]="searchDetail.queryDate | date:'MM/dd/yyyy'"  (ngModelChange)="searchDetail.queryDate=$event" [showIcon]="true" required name="queryDate" placeholder="Enter the Query Date"></p-calendar>

<input id="float-input" type="text" size="30" pInputText [ngModel]="searchDetail.systems | json"  (ngModelChange)="searchDetail.systems=$event" required='true' name="systems"
            placeholder="Enter the Systems">
<input [ngModel]="item.value | currency" (ngModelChange)="item.value=$event"
name="name" type="text" />

我想对已接受的答案再加一分。

如果输入控件的类型不是文本,则管道将不起作用。

记住它,节省您的时间。

您必须使用 [ngModel] 而不是使用 [(ngModel)] 的双向模型绑定。然后将手动更改事件与 (ngModelChange) 一起使用。这是组件中所有双向输入的 public 规则。

因为事件发射器上的管道是错误的。

由于双向绑定,为了防止错误:

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was 
checked.

您可以像这样调用函数来更改模型:

<input 
  [ngModel]="item.value" 
  (ngModelChange)="getNewValue($event)" 
  name="inputField" 
  type="text" 
/>

import { UseMyPipeToFormatThatValuePipe } from './path';

  //...
  constructor(
    private useMyPipeToFormatThatValue: UseMyPipeToFormatThatValuePipe,
  )
  //....
  getNewValue(ev: any): any {
    item.value= this.useMyPipeToFormatThatValue.transform(ev);
  }  

如果有更好的解决方案来防止这个错误就好了。