如何在 AngularJS 中进行双向过滤?
Posted
技术标签:
【中文标题】如何在 AngularJS 中进行双向过滤?【英文标题】:How to do two-way filtering in AngularJS? 【发布时间】:2012-07-21 22:20:51 【问题描述】:AngularJS 可以做的一件有趣的事情是将过滤器应用于特定的数据绑定表达式,这是一种方便的应用方式,例如,模型属性的文化特定货币或日期格式。在范围上具有计算属性也很好。问题是这些特性都不适用于双向数据绑定方案——从范围到视图只有单向数据绑定。这似乎是一个优秀图书馆的明显遗漏 - 还是我错过了什么?
在KnockoutJS 中,我可以创建一个读/写计算属性,它允许我指定一对函数,一个被调用以获取属性的值,一个在设置属性时被调用.例如,这使我能够实现文化感知输入 - 让用户键入“$1.24”并将其解析为 ViewModel 中的浮点数,并在输入中反映 ViewModel 中的更改。
我能找到与此类似的最接近的事情是使用$scope.$watch(propertyName, functionOrNGExpression);
这允许我在$scope
中的属性更改时调用一个函数。但这并不能解决例如文化感知输入问题。请注意当我尝试在 $watch
方法本身中修改 $watched
属性时出现的问题:
$scope.$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
属性的问题(在第二个输入中键入一些内容,这会更改 @987654331直接@。注意顶部输入不会更新)。这可能发生在控制器操作或从数据服务加载数据时。
有没有更简单的方法来使用 AngularJS 来实现这个场景?我是否缺少文档中的某些功能?
【问题讨论】:
【参考方案1】:事实证明,有一个非常优雅的解决方案,但没有很好的文档记录。
可通过|
运算符和角度formatter
处理显示模型值的格式。原来ngModel不仅有格式化器列表,还有解析器列表。
1。使用ng-model
创建双向数据绑定
<input type="text" ng-model="foo.bar"></input>
2。在您的 Angular 模块中创建一个指令,该指令将应用于相同的元素,并且取决于 ngModel
控制器
module.directive('lowercase', function()
return
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attr, ngModel)
...
;
);
3。在link
方法中,将您的自定义转换器添加到ngModel
控制器
function fromUser(text)
return (text || '').toUpperCase();
function toUser(text)
return (text || '').toLowerCase();
ngModel.$parsers.push(fromUser);
ngModel.$formatters.push(toUser);
4。将您的新指令添加到已具有 ngModel
的同一元素中
<input type="text" lowercase ng-model="foo.bar"></input>
这是一个working example,它将input
中的文本转换为小写,然后在模型中转换回大写
模型控制器的 API 文档也有一个简短的解释和其他可用方法的概述。
【讨论】:
您是否有任何理由使用“ngModel”作为链接函数中第四个参数的名称?这不只是指令的通用控制器,基本上与 ngModel 属性无关吗? (这里还在学习角度,所以我可能完全错了。) 因为“require: 'ngModel'”,链接函数的第四个参数将是ngModel指令的控制器——即foo.bar的控制器,它是ngModelController的一个实例。您可以随意命名第 4 个参数。 (我将其命名为ngModelCtrl
。)
此技术记录在 docs.angularjs.org/guide/forms 的自定义验证部分。
@Mark Rajcok 在提供的小提琴中,同时单击加载数据 - 全部小写,我预计模型值将全部大写,但模型值很小。你能请。解释为什么,以及如何使模型总是大写
@rajkamal,因为 loadData2() 直接修改了$scope
,这就是模型将被设置为......直到用户与文本框交互。那时,任何解析器都可以影响模型值。除了解析器之外,您还可以在控制器中添加一个 $watch 来转换模型值。以上是关于如何在 AngularJS 中进行双向过滤?的主要内容,如果未能解决你的问题,请参考以下文章