Пакет не работает на AngularJS, если я помещаю дополнительные виджеты в мой массив
Я искал значительное количество времени сейчас, но все еще не могу найти решение своей проблемы. Я ничего не знаю о пакете, но я нашел этот код, который отлично работает и делает то, что хотел.
directive('workspace', ['$rootScope', function($rootScope) {
return {
constrain: 'A',
link: function(scope, element, attrs) {
element.ready(function() {
var packery = new Packery(element[0], {
rowHeight: '.module-sizer',
itemSelector: '.module',
columnWidth: '.module-sizer'
});
angular.forEach(packery.getItemElements(), function(item) {
var draggable = new Draggabilly(item);
packery.bindDraggabillyEvents(draggable);
});
packery.layout();
});
} }; }]).
Так что все работало идеально, когда у меня был массив виджетов, где я не добавлял и не удалял элемент, а просто использовал ng-show, чтобы скрыть / показать их. Теперь я больше не хочу использовать ng-show, вместо этого я добавляю и удаляю свои виджеты из исходного пустого массива.
.controller('WidgetCtrl', ['$scope', function ($scope) {
$scope.counter = 0;
$scope.current = 0;
$scope.widgets = [];
$scope.addWidget = function(name){
var widgets = {
widget1: {name: 'widget1', id: ''},
widget2: {name: 'widget2', data: {dataVariable: 'some data'}, id:''}
};
var widget = widgets[name];
if (widget) {
$scope.widgets.push(widget);
$scope.widgets[$scope.current].id = $scope.widgets.length-1;
console.log('index of the last widget added: ' + $scope.widgets[$scope.current].id);
$scope.current++;}
Таким образом, единственные виджеты, которые можно перетаскивать, это те, которые изначально находятся в массиве. Любые виджеты, которые я добавлю после загрузки страницы, не будут работать. Я новичок в угловых и читал на $ scope.apply и перекомпилировать директиву, но я не уверен, связано ли это с моей проблемой
<div class="module-container" workspace>
<div class="module-sizer"></div>
<div class="gutter-sizer"></div>
<div class="module" ng-repeat='widget in widgets'>
<div dynamic-widget='widget.name' data='widget.data'> </div>
</div>
</div>
1 ответ
Проблема здесь заключается в том, что пакет фактов привязывает события к элементам сетки, чтобы выполнить макет и сделать их "перетаскиваемыми". Вот фрагмент кода, отвечающий за это:
angular.forEach(packery.getItemElements(), function(item) {
var draggable = new Draggabilly(item);
packery.bindDraggabillyEvents(draggable);
});
Итак, что происходит в настоящее время с тем, как настроена ваша директива, так это то, что когда шаблон, содержащий директиву, изначально загружается, он выбирает любые подходящие элементы .module
и инициализировать упаковку и draggabilly с помощью приведенного выше кода и pckry.layout();
с этого момента ваше приложение не будет знать, что количество виджетов вообще увеличилось.
Чтобы удостовериться, что они инициализируются при добавлении, вы можете передать область в директиву следующим образом:
constrain: 'A',
scope: true,
link: // ...
И тогда вы захотите добавить $scope.$watchCollection
в массив widgets
вот так:
$scope.$watchCollection('widgets', function() {
// Call packery and draggabilly on elems here
});
Я предполагаю, что вы захотите переместить логику для инициализации пакета в отдельную функцию для лучшего разделения кода, хотя учтите, что $watchCollection
сработает при первом запуске директивы, так что вся логика может быть внутри.
И последнее, что нужно отметить, это то, что вам может потребоваться позвонить pckry.destroy();
заранее, чтобы обеспечить желаемый результат. К сожалению, у меня недостаточно времени, чтобы привести пример, так что это всего лишь мысленный эксперимент, но я надеюсь, что это поможет!