Javascript 如何在 AngularJS 中进行双向过滤?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11616636/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 06:32:52  来源:igfitidea点击:

How to do two-way filtering in AngularJS?

javascriptangularjsdata-bindingangularjs-scope

提问by Jeremy Bell

One of the interesting things AngularJS 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?

AngularJS 可以做的一件有趣的事情是将过滤器应用于特定的数据绑定表达式,这是一种方便的应用方式,例如,特定于文化的货币或模型属性的日期格式。在作用域上有计算属性也很好。问题是这些特性都不适用于双向数据绑定场景——只有从作用域到视图的单向数据绑定。在其他优秀的图书馆中,这似乎是一个明显的遗漏 - 或者我错过了什么?

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.

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

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 $scopechanges. But this doesn't solve, for example, the culture-aware input problem. Notice the problems when I try to modify the $watchedproperty within the $watchmethod itself:

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

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

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

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

( 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 parsedValueproperty of the scope changes (type something in the second input, which changes the parsedValuedirectly. notice the top input does not update). This might happen from a controller action or from loading data from a data service.

这是对第一个版本的改进,但有点冗长,请注意parsedValue范围更改的属性仍然存在问题(在第二个输入中键入一些内容,parsedValue直接更改。注意顶部输入没有更新)。这可能发生在控制器操作或从数据服务加载数据时。

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

是否有一些更简单的方法可以使用 AngularJS 来实现这个场景?我是否缺少文档中的某些功能?

回答by phaas

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.

格式化显示的模型值可以由|操作员和 angular 处理formatter。事实证明,ngModel 不仅有一个格式化程序列表,还有一个解析器列表。

1. Use ng-modelto create the two-way data binding

1.ng-model用于创建双向数据绑定

<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 ngModelcontroller

2. 在您的 angular 模块中创建一个指令,该指令将应用于相同的元素并且取决于ngModel控制器

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

3. Within the linkmethod, add your custom converters to the ngModelcontroller

3. 在该link方法中,将您的自定义转换器添加到ngModel控制器

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

4. 将您的新指令添加到已经具有 ngModel

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

Here's a working examplethat transforms text to lowercase in the inputand back to uppercase in the model

这是一个工作示例,它input在模型中将文本转换为小写,然后再转换为大写

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

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