我有一个自定义指令,在服务准备就绪时会收到通知,然后应该操作它的DOM。
DOM操作得很好,但每当我来回过滤ng-repeat时这个指令都在(当一个新的$ digest循环触发时),该指令恢复到其初始状态(没有修改的DOM,即它的编译状态) )。
一旦指令被服务和DOM操作通知,范围和DOM就不会改变。那么它的状态就是它的最终形式,而且每当新的$ digest周期触发时,我都希望DOM能够存在。
如何解决这个问题?
如何保存异步DOM操作,以便在下一个$ digest触发时它仍然存在?
我想这样做的原因是,在指令得到通知后数据不会改变,因此,不希望并且需要使用观察者。
感谢。
代码
angular.module('myApp').directive('myItem', function (_, myService) {
var pricesToShow = 3,
textToShow = 'Fetching Data';
return {
restrict: 'A',
transclude: false,
replace: true,
scope: true,
templateUrl: 'tpl/myItem.html',
compile: function($templateElement) {
// THIS IS THE STATE DIRECTIVE REVERTS TO WHENEVER ITS RERENDERED - WHY?
var $pricesElem = $templateElement.children().eq(0).children().eq(-1),
html= '';
if (pricesToShow) {
html = '<span>' + textToShow + '</span>';
_.times(pricesToShow, function() {
html += '<div class="pricetag"><span class="sid">' + i + '</span> <span class="price"></span> <span class="currency"></span></div>';
});
$pricesElem.append(html);
}
return function($scope, $linkElement, $linkAttributes, ctrl) {
var id = Math.random().toString(36).slice(2),
$priceTagElems = $linkElement.children().eq(0).children().eq(-1).children().slice(1);
$scope.$on('$destroy', onDestroy);
if (myService.getServices().isDoneProcessing) {
showPrices();
} else {
myService.registerObserver(id, updatePrices);
}
function onDestroy() {
myService.unregisterObserver(id);
}
function showPrices(isAsyncCall) {
if (!isAsyncCall && !$scope.trip.prices) {
updatePrices();
} else if (!isAsyncCall && $scope.trip.prices) {
// DOM should now be in its final form - but appears to be in its compile form :(
return;
}
// THESE CHANGES TO DOM WON'T BE SAVED FOR THE NEXT $DIGEST - WHY?
_.each($scope.trip.prices, function(price, i) {
$priceTagElems.eq(i).children().eq(0)
.text(price.sid).next()
.text(price.value.toFixed()).next()
.text(price.currency);
});
}
function updatePrices(isNotificationCallback) {
if ($scope.trip.prices) { return; }
$scope.trip.prices = [];
_.each($scope.trip.values, function(item) {
$scope.trip.prices.push({'sid': item.sid, 'value': item.price.value, 'currency': item.price.currency});
});
$scope.trip.prices.sort(function(a, b) {
return a.value - b.value;
});
if (isNotificationCallback) {
$scope.$apply(function() {
$scope.trip.prices = _.first($scope.trip.prices, pricesToShow);
showPrices(true);
});
} else {
$scope.trip.prices = _.first($scope.trip.prices, pricesToShow);
}
}
};
},
controller: function($scope) {
// Some logic ...
}
};
});
myItem.html
<div>
<div>
<div>..some bo-text spans..</div>
<div>..some bo-text spans..</div>
<div class="prices">..this will be replaced by compile function and in async callback function..</div>
</div>
</div>
ng-repeat
<div bindonce="trip" ng-repeat="trip in trips | myFilter:customFilters | limitTo: 20 track by trip.key" my-item="">Replaced by directive</div>
myFilter
return function (trips, filter) {
var filtered = [];
_.each(trips, function(element) {
var match = hasMatch(element, filter);
if (match) {
filtered.push(element);
}
});
return filtered;
};
答案 0 :(得分:0)
作为我们讨论的结论:
limitTo
过滤器结合的顺序意味着范围被销毁,而元素也是所有这些意味着发生的行为绝对正常。
作为解决方案,如果已经链接(如此转换),则不应删除元素,仅隐藏元素。不推荐在实体上克隆和存储某种方式。最好有一个完整的自定义过滤器标记实体已经显示一次,以便它们可以简单地隐藏在有序和有界列表中。