AngularのINPUT要素のngModel内でパイプを使用する


143

HTML INPUTフィールドがあります。

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

そして、その値をフォーマットして既存のパイプを使用したいと思います:

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

そしてエラーメッセージを取得します:

アクション式にパイプを含めることはできません

このコンテキストでパイプを使用するにはどうすればよいですか?

回答:


213

テンプレートステートメント内では、テンプレート式演算子(パイプ、保存ナビゲーター)を使用できません。

(ngModelChange)="Template statements"

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

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

テンプレート式のように、テンプレートステートメントはJavaScriptのように見える言語を使用します。テンプレートステートメントパーサーは、テンプレート式パーサーとは異なり、基本的な割り当て(=)とチェーン式(;または、を使用)の両方を具体的にサポートしています。

ただし、特定のJavaScript構文は許可されていません

  • 新着
  • インクリメントおよびデクリメント演算子、++および-
  • + =や-=などの演算子の割り当て
  • ビット演算子| と&
  • テンプレート式演算子

したがって、次のように記述する必要があります。

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

プランカーの例


3
なぜそれをこのように分割する必要があるのか​​誰かが説明できますか?タイプdateの入力に日付をバインドしようとしています:[(ngModel)] = "model.endDate | date: 'y-MM-dd'"で、パイプが機能しません。ただし、バナナ構文を使用せずに上記の分割構文を使用すると、問題なく機能します。
ブレイクリベル2017年

これは本当に機能しましたか?うまくいきませんでした。アクション式にパイプを
含める

4
これは私にとってはうまくいきました!@BlakeRivell "[]"は、データソースからビューターゲットに一方向でプロパティをバインドします。その時点で、パイプでの表示方法を変更できます。「()」バインディングを使用する場合、フォーマットを変更する他の方法はここでは役に立たないでしょう。だから、箱の中のバナナ「[()]」がパイプで機能せず、それらを分割するのが良い方法だと思う。詳細については、こちらをご覧ください。angular.io
Mike Bovenlander

8
この例では、パイプが一方向にしか機能しないことに注意してください。たとえばitem.value、数値で、DatePipeそれを日付文字列に変換するために使用するとします。日付を編集する$eventと、も日付文字列になり、元に戻りませんitem.value(ngModelChange)式でパイプが行ったことを逆にする必要があります。つまり、日付文字列を数値に戻します。
Tuupertunut

3
@Protagonist (ngModelChange)="updateItemValue($event)"、次にupdateItemValue(date: string)メソッドを作成しitem.value = someConversionFunction(date); てその中に変換関数として何を使用するかを尋ねている場合、私にはわかりません。多分Date.parse()うまくいくかもしれません。
Tuupertunut

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

ここでの解決策は、バインディングを一方向バインディングとイベントバインディングに分割すること[(ngModel)]です。これには、構文に実際に含まれています。[]一方向バインディング構文で()あり、イベントバインディング構文です。一緒に使用すると、[()]Angularはこれを省略形として認識し、一方向バインディングの形式で双方向バインディングとコンポーネントオブジェクト値へのイベントバインディングを結び付けます。

[()]パイプで使用できない理由は、パイプは一方向のバインディングでのみ機能するためです。したがって、一方向バインディングでのみ動作するようにパイプを分割し、イベントを個別に処理する必要があります。

詳細については、Angular テンプレート構文を参照してください。


1
|のような条件式を追加するにはどうすればよいですか。番号: '3.2-5'?
主人公

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

受け入れられた回答にもう1点追加したいと思います。

入力コントロールのタイプがテキストでない場合、パイプは機能しません。

それを覚えておいて、あなたの時間を節約してください。


回答にさらに情報を追加することを検討してください
Inder

1
角度ロケールに基づいて特定の通貨の入力ボックスをマスクするために作成したngx-locale-mask角度ライブラリを確認してください
Tibinトーマス

6

私は上記の解決策を試しましたが、モデルに送られる値はフォーマットされた値であり、その後、戻り、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();
  }

また、パーセントパイプに対して選択した回答を試し、(ngModelChange)に対してtoDecimal()のようなメソッドを記述しました。2つのメソッドは互いに追跡します。したがって、1桁を超えて入力することはできません。意外と意外と多い
アンジェラP

1

私のソリューションは以下のとおりです。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">

0

[(ngModel)]との双方向モデルバインディングの代わりに[ngModel]を使用する必要があります。次に、(ngModelChange)で手動変更イベントを使用します。これは、コンポーネントのすべての双方向入力に対するパブリックルールです。

イベントエミッターのパイプが間違っているためです。


0

双方向バインディングのため、次のエラーを防止するには:

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);
}

このエラーを防ぐためのより良い解決策があればそれは良いでしょう。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.