Cómo hacer el filtrado bidireccional en AngularJS?


Una de las cosas interesantes que AngularJS puede hacer es aplicar un filtro a una expresión de databinding en particular, que es una forma conveniente de aplicar, por ejemplo, formato de moneda o fecha específico de la cultura de las propiedades de un modelo. También es bueno tener propiedades calculadas en el ámbito. El problema es que ninguna de estas características funciona con escenarios de databinding bidireccional - solo databinding unidireccional desde el ámbito a la vista. Esto parece ser una omisión flagrante en un excelente biblioteca-o me estoy perdiendo algo?

En KnockoutJS, pude crear una propiedad computada de lectura/escritura, que me permitió especificar un par de funciones, una que se llama para obtener el valor de la propiedad, y otra que se llama cuando se establece la propiedad. Esto me permitió implementar, por ejemplo, la entrada consciente de la cultura, permitiendo que el usuario escriba "$1.24" y analizarlo en un flotador en el ViewModel, y tener cambios en el ViewModel reflejados en la entrada.

El lo más cercano que podría encontrar similar a esto es el uso de $scope.$watch(propertyName, functionOrNGExpression); Esto me permite tener una función invocada cuando una propiedad en el $scope cambia. Pero esto no resuelve, por ejemplo, el problema de entrada consciente de la cultura. Observe los problemas cuando intento modificar la propiedad $watched dentro del propio método $watch:

$scope.$watch("property", function (newValue, oldValue) {
    $scope.outputMessage = "oldValue: " + oldValue + " newValue: " + newValue;
    $scope.property = Globalize.parseFloat(newValue);
});

(http://jsfiddle.net/gyZH8/2/)

El elemento de entrada se confunde mucho cuando el usuario comienza a escribir. Lo mejoré dividiendo la propiedad en dos propiedades, una para el valor sin analizar y otra para el valor analizado:

$scope.visibleProperty= 0.0;
$scope.hiddenProperty = 0.0;
$scope.$watch("visibleProperty", function (newValue, oldValue) {
    $scope.outputMessage = "oldValue: " + oldValue + " newValue: " + newValue;
    $scope.hiddenProperty = Globalize.parseFloat(newValue);
});

(http://jsfiddle.net/XkPNv/1/)

Esto fue una mejora con respecto a la primera versión, pero es un poco más detallado, y observe que todavía hay un problema con la propiedad parsedValue de los cambios de ámbito (escriba algo en la segunda entrada, que cambia el parsedValue directamente. observe que la entrada superior no se actualiza). Esto puede ocurrir a partir de una acción del controlador o de la carga de datos de un Servicio.

¿Hay alguna forma más fácil de implementar este escenario usando AngularJS? ¿Me falta alguna funcionalidad en la documentación?

Author: Graham, 2012-07-23

1 answers

Resulta que hay una solución muy elegante para esto, pero no está bien documentada.

Los valores del modelo de formato para la visualización pueden ser manejados por el operador | y un angular formatter. Resulta que el ngModel que tiene no solo una lista de formateadores, sino también una lista de analizadores.

1. Use ng-model para crear el enlace de datos bidireccional

<input type="text" ng-model="foo.bar"></input>

2. Cree una directiva en su módulo angular que se aplicará al mismo elemento y que depende de la ngModel controlador

module.directive('lowercase', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attr, ngModel) {
            ...
        }
    };
});

3. Dentro del método link, agregue sus convertidores personalizados al controlador ngModel

function fromUser(text) {
    return (text || '').toUpperCase();
}

function toUser(text) {
    return (text || '').toLowerCase();
}
ngModel.$parsers.push(fromUser);
ngModel.$formatters.push(toUser);

4. Agregue su nueva directiva al mismo elemento que ya tiene el ngModel

<input type="text" lowercase ng-model="foo.bar"></input>

Aquí hay un ejemplo de trabajo que transforma el texto a minúsculas en el input y de nuevo a mayúsculas en el modelo

La Documentación de la API para el Controlador del Modelo también tiene una breve explicación y una descripción general de los otros disponibles método.

 228
Author: phaas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-18 14:47:20