Пакет не работает на 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(); заранее, чтобы обеспечить желаемый результат. К сожалению, у меня недостаточно времени, чтобы привести пример, так что это всего лишь мысленный эксперимент, но я надеюсь, что это поможет!

Другие вопросы по тегам