personalizadas funciones ejemplos directivas angularjs angular

angularjs - funciones - Cómo observar los cambios de forma en Angular



ng controller (6)

En Angular, podría tener una forma similar a esta:

<ng-form> <label>First Name</label> <input type="text" ng-model="model.first_name"> <label>Last Name</label> <input type="text" ng-model="model.last_name"> </ng-form>

Dentro del controlador correspondiente, podría observar fácilmente los cambios en el contenido de ese formulario de la siguiente manera:

function($scope) { $scope.model = {}; $scope.$watch(''model'', () => { // Model has updated }, true); }

Aquí hay un ejemplo angular en JSFiddle .

Tengo problemas para descubrir cómo lograr lo mismo en Angular. Obviamente, ya no tenemos $scope , $ rootScope. ¿Seguramente hay un método por el cual se puede lograr lo mismo?

Aquí hay un ejemplo angular en Plunker .


Ampliando las sugerencias de Mark ...

Método 3

Implemente la detección de cambios "profundos" en el modelo. Las ventajas implican principalmente evitar la incorporación de aspectos de la interfaz de usuario en el componente; Esto también capta los cambios programáticos realizados en el modelo. Dicho esto, requeriría un trabajo adicional para implementar cosas tales como eliminar el rebote como lo sugiere Thierry, y esto también detectará sus propios cambios programáticos, así que úselo con precaución.

export class App implements DoCheck { person = { first: "Sally", last: "Jones" }; oldPerson = { ...this.person }; // ES6 shallow clone. Use lodash or something for deep cloning ngDoCheck() { // Simple shallow property comparison - use fancy recursive deep comparison for more complex needs for (let prop in this.person) { if (this.oldPerson[prop] !== this.person[prop]) { console.log(`person.${prop} changed: ${this.person[prop]}`); this.oldPerson[prop] = this.person[prop]; } } }

Probar en Plunker


Para completar un poco más de excelentes respuestas anteriores, debe tener en cuenta que los formularios aprovechan los observables para detectar y manejar los cambios de valor. Es algo realmente importante y poderoso. Tanto Mark como dfsq describieron este aspecto en sus respuestas.

Los observables permiten no solo usar el método de subscribe (algo similar al método de promesas en Angular 1). Puede ir más allá si es necesario para implementar algunas cadenas de procesamiento de datos actualizados en formularios.

Me refiero a que puede especificar a este nivel el tiempo de rebote con el método debounceTime . Esto le permite esperar una cantidad de tiempo antes de manejar el cambio y manejar correctamente varias entradas:

this.form.valueChanges .debounceTime(500) .subscribe(data => console.log(''form changes'', data));

También puede conectar directamente el procesamiento que desea activar (algunos asincrónicos, por ejemplo) cuando se actualizan los valores. Por ejemplo, si desea manejar un valor de texto para filtrar una lista basada en una solicitud AJAX, puede aprovechar el método switchMap :

this.textValue.valueChanges .debounceTime(500) .switchMap(data => this.httpService.getListValues(data)) .subscribe(data => console.log(''new list values'', data));

Incluso va más allá al vincular el observable devuelto directamente a una propiedad de su componente:

this.list = this.textValue.valueChanges .debounceTime(500) .switchMap(data => this.httpService.getListValues(data)) .subscribe(data => console.log(''new list values'', data));

y mostrarlo usando la tubería async :

<ul> <li *ngFor="#elt of (list | async)">{{elt.name}}</li> </ul>

Solo para decir que necesitas pensar la forma de manejar formas de manera diferente en Angular2 (una forma mucho más poderosa ;-)).

Espero que te ayude, Thierry


Para la versión angular 5+ . Poner la versión ayuda ya que angular hace muchos cambios.

ngOnInit() { this.myForm = formBuilder.group({ firstName: ''Thomas'', lastName: ''Mann'' }) this.formControlValueChanged() // Note if you are doing an edit/fetching data from an observer this must be called only after your form is properly initialized otherwise you will get error. } formControlValueChanged(): void { this.myForm.valueChanges.subscribe(value => { console.log(''value changed'', value) }) }


Pensé en usar el método (ngModelChange), luego pensé en el método FormBuilder y finalmente decidí una variación del Método 3. Esto ahorra la decoración de la plantilla con atributos adicionales y recoge automáticamente los cambios en el modelo, reduciendo la posibilidad de olvidar algo. con el Método 1 o 2.

Simplificando el Método 3 un poco ...

oldPerson = JSON.parse(JSON.stringify(this.person)); ngDoCheck(): void { if (JSON.stringify(this.person) !== JSON.stringify(this.oldPerson)) { this.doSomething(); this.oldPerson = JSON.parse(JSON.stringify(this.person)); } }

Puede agregar un tiempo de espera para llamar solo a doSomething () después de x número de milisegundos para simular un rebote.

oldPerson = JSON.parse(JSON.stringify(this.person)); ngDoCheck(): void { if (JSON.stringify(this.person) !== JSON.stringify(this.oldPerson)) { if (timeOut) clearTimeout(timeOut); let timeOut = setTimeout(this.doSomething(), 2000); this.oldPerson = JSON.parse(JSON.stringify(this.person)); } }


Si está utilizando FormBuilder , consulte la respuesta de @ dfsq.

Si no está utilizando FormBuilder , hay dos formas de ser notificado de los cambios.

Método 1

Como se discutió en los comentarios sobre la pregunta, use un enlace de evento en cada elemento de entrada. Añadir a su plantilla:

<input type="text" class="form-control" required [ngModel]="model.first_name" (ngModelChange)="doSomething($event)">

Luego en su componente:

doSomething(newValue) { model.first_name = newValue; console.log(newValue) }

La página de Forms tiene información adicional sobre ngModel que es relevante aquí:

ngModelChange no es un evento de elemento <input> . En realidad, es una propiedad de evento de la directiva NgModel . Cuando Angular ve un objetivo de enlace en la forma [(x)] , espera que la directiva x tenga una propiedad de entrada xChange una propiedad de salida xChange .

La otra rareza es la expresión de la plantilla, model.name = $event . Estamos acostumbrados a ver un objeto $event proveniente de un evento DOM. La propiedad ngModelChange no produce un evento DOM; es una propiedad Angular EventEmitter que devuelve el valor del cuadro de entrada cuando se dispara.

Casi siempre preferimos [(ngModel)] . Podríamos dividir el enlace si tuviéramos que hacer algo especial en el manejo del evento, como eliminar el rebote o acelerar las pulsaciones de teclas.

En su caso, supongo que quiere hacer algo especial.

Método 2

Defina una variable de plantilla local y ngForm en ngForm .
Use ngControl en los elementos de entrada.
Obtenga una referencia a la directiva NgForm del formulario utilizando @ViewChild, luego suscríbase al ControlGroup de NgForm para ver los cambios:

<form #myForm="ngForm" (ngSubmit)="onSubmit()"> .... <input type="text" ngControl="firstName" class="form-control" required [(ngModel)]="model.first_name"> ... <input type="text" ngControl="lastName" class="form-control" required [(ngModel)]="model.last_name"> class MyForm { @ViewChild(''myForm'') form; ... ngAfterViewInit() { console.log(this.form) this.form.control.valueChanges .subscribe(values => this.doSomething(values)); } doSomething(values) { console.log(values); } }

plunker

Para obtener más información sobre el Método 2, vea el video de Savkin .

Consulte también la respuesta de @ Thierry para obtener más información sobre lo que puede hacer con los valueChanges observables (como valueChanges el valueChanges / esperar un poco antes de procesar los cambios).


UPD La respuesta y la demostración se actualizan para alinearse con la última versión angular.

Puede suscribirse a los cambios completos del formulario debido al hecho de que FormGroup que representa un formulario proporciona la propiedad valueChanges , que es una instancia observable:

this.form.valueChanges.subscribe(data => console.log(''Form changes'', data));

En este caso, necesitaría construir el formulario manualmente usando FormBuilder . Algo como esto:

export class App { constructor(private formBuilder: FormBuilder) { this.form = formBuilder.group({ firstName: ''Thomas'', lastName: ''Mann'' }) this.form.valueChanges.subscribe(data => { console.log(''Form changes'', data) this.output = data }) } }

Echa un vistazo a valueChanges en acción en esta demostración : http://plnkr.co/edit/xOz5xaQyMlRzSrgtt7Wn?p=preview