angular - соединить массив внутри директивы, если src error

0

Мне нужно удалить элемент и нажать дальше внутри ng-repeat, если изображение не существует.

В настоящее время я использую следующую директиву

myApp.directive("noImage", function() {
  return {
    link: function(scope, element, attrs) {
      return element.bind("error", function() {
        element.attr("src", attrs.noImage);
        return element.addClass('no-img');
        //return element.parent().remove();
        //return element.parent().splice();
      });
    }
  };
});

Очевидно, что если использовать element.parent().remove() или splice() он не перетаскивает следующий элемент в массив.

Вот скрипка

Еще одна идея - это функция записи в контроллере, а затем запустить ее из директивы:

$scope.splicePost = (post) =>
  $scope.posts.splice( $scope.posts.indexOf(post), 1 )

Проблема в том, что я не могу понять, как это сделать. Может быть, нужно использовать изоляцию?

Теги:

3 ответа

2
Лучший ответ

ng-repeat создает дочернюю область для каждого элемента репитера.

Это означает, что внутри директивы вы наследуете массив родительских областей, а также имеете доступ к scope.post для каждого элемента сообщения.

myApp.directive("noImage", function () {
    return {
        link: function (scope, element, attrs) {
            element.bind("error", function () {
                // get index of post in the posts array
                var idx = scope.posts.indexOf(scope.post);
                scope.$apply(function () {
                    // splice posts array
                    scope.posts.splice(idx, 1);
                });
            });
        }
    };
});

Поскольку событие находится за пределами углового ядра, вам нужно указать угловое значение, чтобы запустить дайджест, когда область изменена, и это делается с использованием $apply или $timeout

Чтобы сделать это более пригодным для повторного использования, было бы лучше создать изолированную область и передать в столбце post и post array в изолированную область

DEMO

  • 0
    Спасибо за это. Не могли бы вы взглянуть на этот вопрос (связанный с ним) stackoverflow.com/questions/33472524/…
0

Да, вы правы, вам нужно передать массив в директиву, и если изображение не может загрузить, вы можете сращиться с массивом. передайте его в изолированном объеме с помощью "=", поэтому у вас есть двусторонняя привязка.

Если произошла ошибка, сращивание, в противном случае, ничего не делать.

ОБНОВЛЕНИЕ: Код:

var myApp = angular.module('myApp',[]);

myApp.directive("noImage", function() {
  return {
    scope: {
      posts: "="
    },
    link: function(scope, element, attrs) {
      return element.bind("error", function() {
        scope.posts.splice(scope.$parent.$index, 1);
        scope.$apply();
      });
    }
  };
});

Html станет:

<div ng-controller="MyCtrl">
  <ul>
     <li ng-repeat = 'post in posts | limitTo: 5'>
         <img posts="posts" ng-src = "{{post.image_url}}" no-image = "" />

     </li>
  </ul> 
</div>
  • 0
    Можете ли вы отредактировать мою скрипку и показать ее?
0

Я бы предпочел подумать о компонентах, значит, вы могли бы создать компонент, называемый image-block который ранее использовал шаблон, используемый в вашей разметке. Теперь ваша разметка может выглядеть так:

<div ng-controller="MyCtrl as vm">
  <image-block images="vm.posts" url-property="image_url"></image-block>
</div>

Вы передаете images и urlProperty под которыми компонент может найти URL для каждого изображения. Директива image-block изображения реализуется следующим образом:

myApp.directive("imageBlock", function() {
  return {
    restrict: 'E',
    scope: {
      images: '=',
      urlProperty: '@',
      limit: '@'
    },
    template:
      '<ul>' +
        '<li ng-repeat="image in images | limitTo: limit || 3">' + 
          '<img ng-src="{{ image[urlProperty] }}" is-image="image" />' +
        '</li>' +
      '</ul>',
    controller: ['$scope', function(scope) {
        this.removeImage = function(image) {
            var index = scope.images.indexOf(image);
            if(index > 0) {
                scope.images.splice(index, 1);
            }
        };
    }]
  };
});

Компонент имеет свой собственный логический контроллер, который также требуется директивой isImage. Эта директива поймает событие error и removeImage функцию removeImage родительского контроллера.

Директива isImage выглядит так:

myApp.directive("isImage", function() {
  return {
    scope: {
        image: '=isImage'    
    },
    require: '^imageBlock',
    link: function(scope, element, attrs, ctrl) {
      return element.bind("error", function() {
         scope.$apply(ctrl.removeImage(scope.image));
      });
    }
  };
});

Единственным свойством scope является изображение, которое будет передано вместе с родительским контроллером для удаления изображения из списка.

Вот обновленная версия вашего JSFiddle. Лично я считаю, что способ мышления в компонентах очень полезен, и помогает разбить вашу логику и интерфейс на более мелкие части.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню