Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

1.6K
Views
Cómo usar tuberías en la entrada de forma reactiva Angular 5

Estoy tratando de descubrir cómo usar una tubería dentro de una forma reactiva para que la entrada se fuerce en un formato de moneda. Ya creé mi propia tubería para esto, la cual probé en otras áreas del código, así que sé que funciona como una tubería simple. Mi nombre de tubería es 'udpCurrency'

La respuesta más cercana que pude encontrar en el desbordamiento de pila fue esta: Uso de tuberías dentro de ngModel en elementos INPUT en Angular2-View Sin embargo, esto no funciona en mi caso y sospecho que tiene algo que ver con el hecho de que mi forma es reactiva

Aquí está todo el código relevante:

La plantilla

 <form [formGroup]="myForm" #f="ngForm"> <input class="form-control col-md-6" formControlName="amount" [ngModel]="f.value.amount | udpCurrency" (ngModelChange)="f.value.amount=$event" placeholder="Amount"> </form>

El componente

 import { Component, OnInit, HostListener } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; export class MyComponent implements OnInit { myForm: FormGroup; constructor( private builder: FormBuilder ) { this.myForm = builder.group({ amount: ['', Validators.required] }); } }

El error:

 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined: '. Current value: 'undefined: undefined'
over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

Esto es lo que puede suceder cuando mezclas formularios basados en plantillas y formularios reactivos. Tienes dos ataduras luchando entre sí. Elija una forma basada en plantillas o reactiva. Si desea seguir la ruta reactiva, puede usar [value] para su canalización...

Tenga en cuenta que esta tubería es más bien solo para mostrar la salida deseada en la vista.

 <form [formGroup]="myForm"> <input [value]="myForm.get('amount').value | udpCurrency" formControlName="amount" placeholder="Amount"> </form>
over 4 years ago · Santiago Trujillo Report

0

Pensé que esto funcionaba, pero resultó que estaba equivocado (y acepté una respuesta incorrecta). Acabo de rehacer mi lógica de una manera nueva que funciona mejor para mí y responde a la preocupación de Jacob Roberts en los comentarios anteriores. Aquí está mi nueva solución:

La plantilla:

 <form [formGroup]="myForm"> <input formControlName="amount" placeholder="Amount"> </form>

El componente:

 import { Component, OnInit, HostListener } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { UdpCurrencyMaskPipe } from '../../../_helpers/udp-currency-mask.pipe'; export class MyComponent implements OnInit { myForm: FormGroup; constructor( private builder: FormBuilder, private currencyMask: UdpCurrencyMaskPipe, ) { this.myForm = builder.group({ amount: ['', Validators.required] }); this.myForm.valueChanges.subscribe(val => { if (typeof val.amount === 'string') { const maskedVal = this.currencyMask.transform(val.amount); if (val.amount !== maskedVal) { this.myForm.patchValue({amount: maskedVal}); } } }); } }

El tubo:

 import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'udpCurrencyMask' }) export class UdpCurrencyMaskPipe implements PipeTransform { amount: any; transform(value: any, args?: any): any { let amount = String(value); const beforePoint = amount.split('.')[0]; let integers = ''; if (typeof beforePoint !== 'undefined') { integers = beforePoint.replace(/\D+/g, ''); } const afterPoint = amount.split('.')[1]; let decimals = ''; if (typeof afterPoint !== 'undefined') { decimals = afterPoint.replace(/\D+/g, ''); } if (decimals.length > 2) { decimals = decimals.slice(0, 2); } amount = integers; if (typeof afterPoint === 'string') { amount += '.'; } if (decimals.length > 0) { amount += decimals; } return amount; } }

Ahora hay varias cosas que aprendí aquí. Una era que lo que dijo Jacob era cierto, la otra forma solo funcionó inicialmente pero no se actualizaría cuando el valor hubiera cambiado. Otra cosa muy importante a tener en cuenta es que necesito un tipo de tubería completamente diferente para una máscara en comparación con una tubería de visualización. Por ejemplo, una canalización en una vista podría tomar este valor "100" y convertirlo en "$100,00". Por esta razón, creé mi tubería de máscara de moneda que simplemente elimina los números no numéricos y restringe el decimal a dos lugares.

over 4 years ago · Santiago Trujillo Report

0

Iba a escribir un control personalizado, pero descubrí que anular el "onChange" de la clase FormControl a través de ngModelChange era más fácil. emitViewToModelChange: false es fundamental durante la lógica de actualización para evitar bucles recurrentes de eventos de cambio. Toda la canalización a la moneda ocurre en el componente y no tiene que preocuparse por los errores de la consola.

 <input matInput placeholder="Amount" (ngModelChange)="onChange($event)" formControlName="amount" />
 @Component({ providers: [CurrencyPipe] }) export class MyComponent { form = new FormGroup({ amount: new FormControl('', { validators: Validators.required, updateOn: 'blur' }) }); constructor(private currPipe:CurrencyPipe) {} onChange(value:string) { const ctrl = this.form.get('amount') as FormControl; if(isNaN(<any>value.charAt(0))) { const val = coerceNumberProperty(value.slice(1, value.length)); ctrl.setValue(this.currPipe.transform(val), { emitEvent: false, emitViewToModelChange: false }); } else { ctrl.setValue(this.currPipe.transform(value), { emitEvent: false, emitViewToModelChange: false }); } } onSubmit() { const rawValue = this.form.get('amount').value; // if you need to strip the '$' from your input's value when you save data const value = rawValue.slice(1, rawValue.length); // do whatever you need to with your value } }
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!