Menggunakan Pipa dalam ngModel pada Elemen INPUT di Angular

143

Saya memiliki bidang INPUT HTML.

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

dan saya ingin memformat nilainya dan menggunakan pipa yang ada:

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

dan dapatkan pesan kesalahan:

Tidak dapat memiliki pipa dalam ekspresi tindakan

Bagaimana saya bisa menggunakan pipa dalam konteks ini?

Kesepian
sumber

Jawaban:

213

Anda tidak dapat menggunakan operator ekspresi Templat (pipa, simpan navigator) dalam pernyataan templat:

(ngModelChange)="Template statements"

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

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

Seperti halnya ekspresi template, pernyataan template menggunakan bahasa yang mirip dengan JavaScript. Parser pernyataan template berbeda dari Parser ekspresi template dan secara khusus mendukung penugasan dasar (=) dan ekspresi chaining (dengan; atau,).

Namun, sintaksis JavaScript tertentu tidak diizinkan :

  • baru
  • operator kenaikan dan penurunan, ++ dan -
  • tugas operator, seperti + = dan - =
  • operator bitwise | dan &
  • operator ekspresi template

Jadi Anda harus menuliskannya sebagai berikut:

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

Contoh Plunker

yurzui
sumber
3
Adakah yang bisa menjelaskan mengapa harus dibagi seperti ini? Saya mencoba untuk mengikat tanggal ke input dengan tipe tanggal: [(ngModel)] = "model.endDate | date: 'y-MM-dd'" dan pipa tidak akan berfungsi. Namun, jika saya menghapus sintaks pisang dan menggunakan sintaks membagi di atasnya berfungsi dengan baik.
Blake Rivell
Apakah ini benar-benar berhasil? itu tidak berhasil untuk saya. katanya Tidak dapat memiliki pipa dalam ekspresi aksi
NoStressDeveloper
4
Ini berhasil bagi saya! @BlakeRivell "[]" mengikat properti satu arah dari sumber data untuk melihat target pada titik itu Anda dapat mengubah cara ditampilkan dengan pipa. Saat menggunakan ikatan "()" itu adalah sebaliknya mengubah format tidak akan berguna di sini. Jadi saya kira itulah sebabnya pisang ada di dalam kotak "[()]" tidak bekerja dengan pipa dan membelahnya adalah cara yang harus dilakukan. Anda dapat membaca lebih lanjut tentang ini di sini: angular.io/docs/ts/latest/guide/…
Mike Bovenlander
8
Berhati-hatilah bahwa pada contoh pipa hanya bekerja ke satu arah. Katakanlah item.valueadalah angka, dan Anda gunakan DatePipeuntuk mengubahnya menjadi string tanggal. Ketika tanggal diedit, $eventitu juga akan menjadi string tanggal dan tidak akan cocok kembali ke item.valueAnda harus membalikkan apa yang dilakukan pipa dalam (ngModelChange)ekspresi Anda - yaitu, mengubah string tanggal kembali ke angka.
Tuupertunut
3
@ Protagonis (ngModelChange)="updateItemValue($event)", lalu buat updateItemValue(date: string)metode dan di dalamnya item.value = someConversionFunction(date); Sekarang jika Anda bertanya apa yang harus Anda gunakan sebagai fungsi konversi, saya tidak tahu. Mungkin Date.parse()berhasil.
Tuupertunut
111
<input [ngModel]="item.value | useMyPipeToFormatThatValue" 
      (ngModelChange)="item.value=$event" name="inputField" type="text" />

Solusinya di sini adalah untuk membagi pengikatan menjadi pengikatan satu arah dan pengikatan peristiwa - yang [(ngModel)]sebenarnya mencakup sintaks . []adalah sintaks pengikatan satu arah dan ()sintaks pengikatan acara. Ketika digunakan bersama-sama - [()]Angular mengakui ini sebagai steno dan mengikat pengikatan dua arah dalam bentuk pengikatan satu arah dan peristiwa yang mengikat ke nilai objek komponen.

Alasan Anda tidak dapat menggunakan [()]pipa adalah karena pipa hanya berfungsi dengan binding satu arah. Oleh karena itu Anda harus membagi pipa untuk hanya beroperasi pada penjilidan satu arah dan menangani acara secara terpisah.

Lihat Sintaks Templat Angular untuk info lebih lanjut.

KnowHoper
sumber
1
Bagaimana cara menambahkan ekspresi kondisi seperti | nomor: '3.2-5'?
Protagonis
14
<input [ngModel]="item.value | currency" (ngModelChange)="item.value=$event"
name="name" type="text" />

Saya ingin menambahkan satu poin lagi ke jawaban yang diterima.

Jika jenis kontrol input Anda bukan teks, pipa tidak akan berfungsi.

Ingatlah dan hemat waktu Anda.

Tibin Thomas
sumber
silakan pertimbangkan untuk menambahkan informasi lebih lanjut dalam jawaban Anda
Inder
1
periksa perpustakaan sudut ngx-locale-mask yang saya buat untuk menutupi kotak input untuk mata uang tertentu berdasarkan lokal sudut
Tibin Thomas
6

Saya mencoba solusi di atas namun nilai yang masuk ke model adalah nilai yang diformat kemudian kembali dan memberi saya kesalahan currencyPipe. Jadi saya harus melakukannya

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

Dan pada fungsi addToAmount -> perubahan blur menyebabkan ngModelChange memberi saya masalah kursor.

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

Dan menghapus nilai-nilai non numerik lainnya.

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();
  }
cabaji99
sumber
kami juga mencoba jawaban yang dipilih untuk pipa Persen dan menulis metode seperti toDecimal () untuk (ngModelChange), dan 2 metode saling mengejar. jadi Anda tidak bisa mengetik lebih dari 1 digit. mengherankan bahwa hal itu sangat dinegosiasikan
Angela P
1

Solusi saya diberikan di bawah sini searchDetail adalah objek ..

<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">
Bhasker The Navigator
sumber
0

Anda harus menggunakan [ngModel] alih-alih model dua arah mengikat dengan [(ngModel)]. kemudian gunakan acara perubahan manual dengan (ngModelChange). ini adalah aturan umum untuk semua input dua arah dalam komponen.

karena pipa pada event emitor salah.

hamid_reza hobab
sumber
0

karena dua cara mengikat, Untuk mencegah kesalahan:

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was 
checked.

Anda dapat memanggil fungsi untuk mengubah model seperti ini:

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

akan lebih baik jika ada solusi yang lebih baik untuk mencegah kesalahan ini.

Mohammad Reza Mrg
sumber