style form ejemplo angularjs configuration angular-ngmodel

form - ng-model-options angularjs



AngularJS establece ngModelOptions global (5)

El comportamiento predeterminado para actualizar ngModel (y posteriormente la validación) es en cambio ; Me gustaría cambiar eso a borroso . Los docs solo explican cómo hacerlo sobre una base de caso por caso a través de: <ANY ng-model-options="{ updateOn: ''blur'' }"></ANY> . Fui tan lejos como para mirar a través del código fuente, pero de alguna manera no se encuentra ngModelOptions ni ng-model-options (a pesar de que ambos aparecen en la documentación, que se elimina del código fuente).


Como @Angad menciona, puede establecer ng-model-options en cualquier elemento, y se aplicará a todos sus descendientes . Sin embargo, el problema con esto es que si lo configuras así, las radios y las casillas de verificación dejarán de funcionar como se esperaba:

<body ng-app="myApp" ng-model-options="{ updateOn: ''blur'' }">

Esto se puede evitar agregando change y updateOn click en updateOn :

<body ng-app="myApp" ng-model-options="{ updateOn: ''change click blur'' }">

Si también desea actualizar después de un cierto retraso después de escribir, puede utilizar lo siguiente:

<body ng-app="myApp" ng-model-options="{ updateOn: ''keyup change click blur'', debounce: { keyup: 500, click: 0, change: 0, blur: 0 } }">

Probé estas técnicas en Firefox, Chome, Internet Explorer (10, 11) y Safari. Si utiliza otros eventos, estos, asegúrese de probarlo en varios navegadores, por ejemplo, los radios activan el change directamente después de hacer clic, en todos los navegadores excepto en IE.


En lugar de usar

ng-model-options="{ updateOn: ''blur'' }

podrías usar

ng-model-options="{ debounce : { default : 500 } }"

y aplicarlo a un elemento padre en el dom, como un contenedor div. La configuración de debounce anterior le dice a Angular que solo evalúe las reglas de validación después de 500 milisegundos sin actividad.

Usar debounce esta manera es mejor que usar blur porque el desenfoque crea problemas para la radio y las casillas de verificación cuando se aplica a todo el formulario.

La opción de rebote es un valor entero que hace que la actualización del modelo demore un número entero de milisegundos. Reduce la frecuencia de $digest ciclos de $digest producen, lo que hace que la aplicación js consuma menos recursos y le permita al usuario escribir tiempo antes de aplicar las reglas de validación.

YearOfMoo.com recomienda usar desenfoque y rebotar juntos como este

ng-model-options="{ debounce : { default : 500, blur : 0 } }"

Ahora el valor del modelo y las validaciones se aplican inmediatamente después de que el usuario se borre del campo. Esto establece un tiempo de espera de 0 ms para el evento de desenfoque. Desenfoque anula el valor predeterminado.


Esta es una muy buena pregunta, así que he escrito un artículo más detallado sobre este blog . La única forma genérica real que he encontrado para hacer esto es decorar la directiva ngModel, ya que es esta directiva la que realmente usa ngModelOptions.

Si observa la fuente angular de la directiva ngModel , tiene una función de enlace previo para configurar efectivamente las ngModelOptions en el ngModelController mediante el uso de las opciones de $ propiedad. Tenga en cuenta que las opciones $ se crean en el ngModelOptionsDirective que es efectivamente un $ eval en el atributo ng-model-options.

Lo que debemos hacer en nuestro dectorator ngModel es que después de esta función de enlace previo agregue un valor predeterminado para esta propiedad $ options si no está definido. Estoy asumiendo aquí que si el desarrollador ha establecido explícitamente las ngModelOptions en su proyecto, ¡no quiere que se cambie mágicamente! Por lo tanto, solo estableceremos los valores predeterminados si la propiedad $ options no está definida.

Aquí está el código:

(function (angular) { ''use strict''; angular.module(''myAppOverridesModule'').config([''$provide'', function ($provide) { $provide.decorator(''ngModelDirective'', [ ''$delegate'', function ($delegate) { var directive = $delegate[0], link = directive.link, shouldSetBlurUpdateEvent = function (nodeName, inputType) { // The blur event is only really applicable to input controls so // we want to stick with the default events for selects, checkboxes & radio buttons return nodeName.toLowerCase() === ''textarea'' || (nodeName.toLowerCase() === ''input'' && inputType.toLowerCase() !== ''checkbox'' && inputType.toLowerCase() !== ''radio''); }; directive.compile = function () { return function (scope, element, attrs, ctrls) { var ngModelCtrl = ctrls[0]; link.pre.apply(this, arguments); // if ngModelOptions is specified leave it unmodified as developer is explicitly setting it. if (ngModelCtrl.$options === undefined && shouldSetBlurUpdateEvent(element[0].nodeName, element[0].type)) { console.log(''set''); ngModelCtrl.$options = { updateOn: ''blur'', updateOnDefault: false }; } link.post.apply(this, arguments); }; }; return $delegate; } ]); } ]); }(angular));

ACTUALIZACIÓN: He actualizado el código para ignorar las selecciones, casillas de verificación y botones de radio ya que el evento borroso no es el evento de actualización óptimo para ellos.


Modifiqué la respuesta de Jon Samwell porque ya no podía hacer que funcionara.

Esto anula la función de compilación del ngModelDirective almacenando una referencia a la misma y luego devolviendo las funciones de enlace previo / posterior con sus originales más nuestro código de anulación adicional.

¡Disfrutar!

app.config(function($provide) { $provide.decorator(''ngModelDirective'', function($delegate) { var directive = $delegate[0], link = directive.link, shouldSetBlurUpdateEvent = function (nodeName, inputType) { // The blur event is only really applicable to input controls so // we want to stick with the default events for selects, checkboxes & radio buttons return nodeName.toLowerCase() === ''textarea'' || (nodeName.toLowerCase() === ''input'' && inputType.toLowerCase() !== ''checkbox'' && inputType.toLowerCase() !== ''radio''); }; // save a reference to the original compile function var compileFn = directive.compile; directive.compile = function () { var link = compileFn.apply(this, arguments); return { pre: function ngModelPostLink(scope, element, attr, ctrls) { if(!ctrls[2]) { ctrls[2] = {}; } var ngModelOptions = ctrls[2]; if (ngModelOptions.$options === undefined && shouldSetBlurUpdateEvent(element[0].nodeName, element[0].type)) { ngModelOptions.$options = { updateOn: ''blur'', updateOnDefault: false }; } link.pre.apply(this, arguments); }, post: link.post }; }; return $delegate; }); });


Si bien los decoradores ngModel escritos por Jon / John ofrecen una buena solución detrás de escena, también se debe tener en cuenta que declarativamente, las ngModelOptions no tienen que declararse en el nivel del campo de entrada individual, sino que se pueden declarar en el nivel del módulo.

<body ng-app = "myApp" ng-model-options="{ updateOn: ''blur'' }">

Al hacer lo anterior, todos los campos de entrada del módulo myApp heredarán las opciones del modelo ng. Estos se pueden anular en campos de entrada específicos si es necesario (por ejemplo, filtros de búsqueda).

Este plunker demuestra: http://plnkr.co/edit/2L1arGgHJwK82xVucJ4p?p=preview