如何在angular.js中进行双向过滤? [英] How to do two-way filtering in angular.js?

查看:171
本文介绍了如何在angular.js中进行双向过滤?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Angular.js可以做的一件有趣的事情是将过滤器应用于特定的数据绑定表达式,这是一种方便的方式来应用,例如,文化特定的货币或模型属性的日期格式化。在范围上计算属性也很好。问题是这些功能都不能与双向数据绑定场景配合使用 - 仅从范围到视图的单向数据绑定。这似乎是一个非常优秀的图书馆中的一个明显的遗漏 - 或者我错过了什么?



KnockoutJS ,我可以创建一个读/写计算属性,这允许我指定一对函数,一个被调用来获取该属性的值,一个函数被调用属性设置。这允许我实现例如文化感知输入 - 让用户键入$ 1.24,并将其解析为ViewModel中的浮点数,并在输入中反映的ViewModel中进行更改。



最近我可以找到类似的东西是使用 $ scope。$ watch(propertyName,functionOrNGExpression); 这允许我在 $ scope 中的属性更改时调用一个函数。但是,这并不能解决,例如,文化意识输入问题。注意当我尝试修改 $ watch 方法本身的 $ watched 属性时的问题:

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

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



当用户开始输入时,输入元素很困惑。我通过将属性分为两个属性来改进它,一个用于解析的值,一个用于解析的值:

  $ 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/



这是第一个版本的改进,但有点多详细,并注意到范围的 parsedValue 属性仍然存在问题(在第二个输入中键入一些东西,这会更改 parsedValue 直接注意顶级输入不更新)。这可能发生在控制器操作或从数据服务的加载数据。



有没有更简单的方法来实现这个场景使用Angular.js?我在文档中缺少一些功能?

解决方案

事实证明,有一个非常优雅的解决方案,但不是很好



显示的格式化模型值可以由 | 操作符处理,角度 formatter 。事实证明,ngModel不仅具有格式化器列表,而且还包含解析器列表。



1。使用 ng-model 创建双向数据绑定



  ; input type =textng-model =foo.bar>< / input> 



2。在您的角度模块中创建一个将应用于相同元素的指令,这取决于 ngModel 控制器



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



3。在链接方法中,将您的自定义转换器添加到 ngModel 控制器



$ pre> 函数fromUser(text){
return(text ||'').toUpperCase();
}

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



4。将新的指令添加到已经具有 ngModel的同一元素



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

这是一个工作示例,将输入中的文本转换为小写,并返回模型中的大写字母



模型控制器的API文档也有一个简短的说明和其他可用方法的概述。


One of the interesting things Angular.js can do is apply a filter to a particular databinding expression, which is a convenient way to apply, for example, culture-specific currency or date formatting of a model's properties. It is also nice to have computed properties on the scope. The problem is that neither of these features work with two-way databinding scenarios - only one-way databinding from the scope to the view. This seems to be a glaring omission in an otherwise excellent library - or am I missing something?

In KnockoutJS, I could create a read/write computed property, which allowed me to specify a pair of functions, one which is called to get the value of the property, and one which is called when the property is set. This allowed me to implement, for example, culture-aware input - letting the user type "$1.24" and parsing that into a float in the ViewModel, and have changes in the ViewModel reflected in the input.

The closest thing I could find similar to this is the use of $scope.$watch(propertyName, functionOrNGExpression); This allows me to have a function invoked when a property in the $scope changes. But this doesn't solve, for example, the culture-aware input problem. Notice the problems when I try to modify the $watched property within the $watch method itself:

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

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

The input element gets very confused when the user starts typing. I improved it by splitting the property into two properties, one for the unparsed value and one for the parsed value:

$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/)

This was an improvement over the first version, but is a bit more verbose, and notice that there is still an issue of the parsedValue property of the scope changes (type something in the second input, which changes the parsedValue directly. notice the top input does not update). This might happen from a controller action or from loading data from a data service.

Is there some easier way to implement this scenario using Angular.js? Am I missing some functionality in the documentation?

解决方案

It turns out that there's a very elegant solution to this, but it's not well documented.

Formatting model values for display can be handled by the | operator and an angular formatter. It turns out that the ngModel that has not only a list of formatters but also a list of parsers.

1. Use ng-model to create the two-way data binding

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

2. Create a directive in your angular module that will be applied to the same element and that depends on the ngModel controller

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

3. Within the link method, add your custom converters to the ngModel controller

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

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

4. Add your new directive to the same element that already has the ngModel

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

Here's a working example that transforms text to lowercase in the input and back to uppercase in the model

The API Documentation for the Model Controller also has a brief explanation and an overview of the other available methods.

这篇关于如何在angular.js中进行双向过滤?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆