我正在构建一个装饰表头项目的指令,并在click事件中对数据进行排序。我无法使用指令范围将数据模型上的更改应用于父作用域。
vm.data是父作用域上的一个数组,它包含我要在指令中排序的数据。 单击后,指令中的数据对象已更改,但父级仍处于相同的顺序。
我不想使用$ parent访问父作用域,我错过了什么?
<th sortable="browser" data="vm.data">Browser</th>
指令代码:
angular
.module("app")
.directive("sortable", ['lodash', sortableDirective]);
function sortableDirective(lodash) {
return {
restrict: "A",
scope:{
data:"="
},
controller:function($scope){
},
link: function (scope, element, attributes) {
var sorted = undefined;
var col = attributes['sortable'];
var oldClass = 'sorting'
attributes.$$element.addClass(oldClass);
$(element).on("click", sort);
function changeClass(){
if(sorted=='asc'){
attributes.$$element.removeClass(oldClass);
attributes.$$element.addClass('sorting_asc');
oldClass = 'sorting_asc';
}
else if(sorted=='desc'){
attributes.$$element.removeClass(oldClass);
attributes.$$element.addClass('sorting_desc');
oldClass='sorting_desc';
}
}
function sort() {
if (sorted == 'asc') {
sorted = 'desc';
}
else {
sorted = 'asc';
}
scope.data = lodash.sortBy(scope.data, function (o) {
return o[col];
});
if (sorted == 'desc') {
lodash.reverse(scope.data);
}
changeClass();
}
}
};
}
答案 0 :(得分:0)
这是因为你正在使用jQuery来监听元素的变化。所以只需改变这一行:
$(element).on("click", sort);
到
element.on("click", sort);
如果jQuery不可用,第二个属性即element
已经是jQlite的一个实例,如果jQuery可用,它将是jQuery的一个实例。
在任何情况下,都有一个可用的方法.on
,它将在值更改时执行。由于您再次将其包装到$()
,因此Angular未收到有关数据更改的通知。
在第二次浏览代码时,我看到了实际问题。您正在重新分配scope.data
方法中的完整sort()
,该方法违反了Javascript(或任何OOPS编程)的引用行为。
通过引用传递仅在您继续修改 SAME 引用变量时才有效。注意到这个词,相同?通过编写scope.data = lodash.sortBy(scope.data, function (o) {})
,您删除了传递给指令的实际数据的引用。因此,值不会更新。
所以要解决这个问题,你有几个选择:
scope.data
变量推荐(使用内置sort
方法)data
scope.$emit()
传递给父作用域
$parent
媒体资源答案 1 :(得分:0)
双向绑定将更新每个摘要周期的父级,但点击处理程序需要使用$apply
调用该摘要周期:
link: function (scope, element, attributes) {
var sorted = undefined;
var col = attributes['sortable'];
var oldClass = 'sorting'
element.addClass(oldClass);
//REPLACE this
//$(element).on("click", sort);
//
//WITH this
element.on("click", function (e) {
sort();
scope.$apply();
});
function changeClass(){
if(sorted=='asc'){
element.removeClass(oldClass);
element.addClass('sorting_asc');
oldClass = 'sorting_asc';
}
else if(sorted=='desc'){
element.removeClass(oldClass);
element.addClass('sorting_desc');
oldClass='sorting_desc';
}
}
ng-click
指令自动调用$apply
但是当AngularJS jqLite处理click事件时,代码需要通知AngularJS框架。
来自文档:
$apply([exp]);
$apply()
用于从角度框架外部以角度执行表达式。 (例如,来自浏览器DOM事件,setTimeout,XHR或第三方库)。因为我们正在调用角度框架,所以我们需要执行exception handling,executing watches的适当范围生命周期。