Використання труб у ngModel для елементів INPUT у кутовій


144

У мене є поле Введення HTML.

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

і я хочу відформатувати його значення та використовувати існуючу трубу:

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

і отримайте повідомлення про помилку:

Не може бути труба в виразі дії

Як я можу використовувати труби в цьому контексті?

Відповіді:


215

Ви не можете використовувати оператори виразів шаблонів (труба, зберегти навігатор) в операторі шаблону:

(ngModelChange)="Template statements"

(ngModelChange) = "item.value | useMyPipeToFormatThatValue = $ подія"

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

Як і вирази шаблонів, висловлювання шаблонів використовують мову, схожу на JavaScript. Аналізатор висловлювань шаблонів відрізняється від аналізатора виразів шаблону і спеціально підтримує як базове призначення (=), так і ланцюгові вирази (з; або,).

Однак певний синтаксис JavaScript заборонено :

  • нові
  • збільшення та зменшення операторів, ++ та -
  • призначення оператора, таких як + = і - =
  • побітові оператори | і &
  • оператори виразів шаблонів

Тож слід написати це так:

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

Приклад Плункер


3
Чи може хтось пояснити, чому це потрібно розколоти так? Я намагаюся прив’язати дату до введення з датою типу: [(ngModel)] = "model.endDate | дата: 'y-MM-dd'", і труба не працюватиме. Однак якщо я скасую синтаксис банана і використовую синтаксис, що розщеплюється вище, він прекрасно працює.
Блейк Рівелл

Це справді спрацювало? це не працювало для мене. в ньому йдеться про те, що не може мати трубу в виразі дії
NoStressDeveloper

4
Це працювало для мене, щоб! @BlakeRivell "[]" прив'язує властивість в одну сторону від джерела даних для перегляду цілі в той момент, ви можете змінити, як воно відображається за допомогою труби. При використанні прив'язки "()" навпаки, змінити формат було б марно. Тож я думаю, ось чому банан у коробці "[()]" не працює з трубою, а їх розщеплення - це шлях. Більше про це можна прочитати тут: angular.io/docs/ts/latest/guide/…
Майк Бовенлендер

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 розпізнає це як стенограму та з'єднує двостороннє зв’язування у вигляді одностороннього зв’язування та прив'язки події до значення компонентного об'єкта.

Причина, яку ви не можете використовувати [()]з трубою, полягає в тому, що труби працюють тільки з односторонніми прив’язками. Тому ви повинні роз'єднати трубу, щоб працювати лише на односторонній прив'язці та обробляти подію окремо.

Докладнішу інформацію див. У синтаксисі кутового шаблону .


1
Як додати вираз умови, як | номер: '3,2-5'?
головний герой

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

Я хотів би додати ще один пункт до прийнятої відповіді.

Якщо тип керування введенням не є текстовим, труба не працюватиме.

Майте це на увазі і заощадите свій час.


люб’язно подумайте над тим, щоб додати більше інформації у свою відповідь
Inder

1
перевірити кутову бібліотеку ngx-locale-mask, яку я зробив, щоб замаскувати поле введення для певної валюти на основі кутової мови
Тібін Томас,

6

Я спробував рішення вище, але значення, яке йде до моделі, було відформатованим значенням, а потім поверненням і наданням мені errorPipe помилок. Так мені довелося

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

ми також спробували обрану відповідь для Percent pipe і написали такий метод, як toDecimal () для (ngModelChange), і 2 методи переслідують один одного. тому ви не можете вводити більше 1 цифри. дивно, що настільки його схвалили
Angela 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);
}

буде добре, якщо буде краще рішення, щоб запобігти цій помилці.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.