AngularJs | ng-click not firing

I can see no apparent reason why the ng-click shouldn’t work, however it does not fire when clicking the element it is bound to.

There are two elements that will be rendered. Each one has an icon X on on the top right of its div which should fire deletePreview. This will lead currently to the deletion of the first item of linkPreviews. When invoking this method by $timeout e.g., it works as expected. Trying to click on the icon however is not working.

I’m glad for any ideas.

(function (angular) {
  'use strict';

  angular
    .module('commons.ui')
    .directive('linkPreview', linkPreview)
    .controller('LinkPreviewController', LinkPreviewController);

  function linkPreview() {
    return {
      restrict: 'E',
      replace: true,
      templateUrl: 'link-preview/link-preview.html',
      scope: {},
      require: 'ngModel',
      bindToController: {
        focusVar: '=?',
        placement: '@'
      },
      controller: 'LinkPreviewController',
      controllerAs: '$ctrl'
    };
  }

  function LinkPreviewController($log, $timeout) {
    var vm = this;
    vm.deletePreview = deletePreview;

    vm.linkPreviews = [
      {
        image: {
          fileId: 'f616157b-223d-46ff-ba87-c16d10e83ed6',
          senderId: '1ae6f889-f27e-4466-a0a9-021923704097'
        },
        title: 'Title',
        description: 'This is an integrated platform for your official company news, social collaboration and team messaging.',
        url: 'http://www.sample.com/en/tour',
        tld: 'sample.com'
      },
      {
        image: '',
        title: 'Hacker News',
        description: 'News for the technically interested',
        url: 'https://news.ycombinator.com/',
        tld: 'news.ycombinator.com'
      }
    ];

    function deletePreview() {
      $log.info('should be deleted');
      vm.linkPreviews.splice(0, 1);
    }
  }
})(angular);
<div ng-repeat="linkPreview in $ctrl.linkPreviews">
    <div class="link-preview">
        <div class="link-preview-delete pull-right">
            <div class="link-preview-delete pull-right">
                <span class="link-preview-delete-button" ng-click="$ctrl.deletePreview()">
                    <i class="zmdi zmdi-close img-close"></i>
                </span>
            </div>
        </div>
        ..
     </div>
</div>

Answer

I guess it is a bug in AngularJS? Or I indeed misused it.

In my example, the top html element of the directive is <div ng-repeat="linkPreview in $ctrl.linkPreviews">, meaning that multiple divs will be added on the same hierarchy level.

When wrapping this in another div, as the example of @anoop showed, it’ll all of a sudden work. What I don’t understand yet is, why is the array of vm.linkPreviews is always attached to the controller, however the function vm.deletePreviews will only work when it is wrapped in one top div.

Working HTML code:

<div>
    <div ng-repeat="linkPreview in $ctrl.linkPreviews">
        <div class="link-preview">
            <div class="link-preview-delete pull-right">
            <span class="link-preview-delete-button" ng-click="$ctrl.deletePreview()">
              <i class="zmdi zmdi-close img-close"></i>
            </span>
            </div>
            <div class="link-preview-image-wrapper">
                <div class="link-preview-image">
                    <coyo-image-reference ng-if="linkPreview.image"
                                          file-id="::linkPreview.image.fileId"
                                          sender-id="::linkPreview.image.senderId"
                                          size-definitions="{'default': 'S', 'screen-lg': 'S'}"></coyo-image-reference>
                    <div class="link-preview-icon" ng-if="!linkPreview.image">
                        <i class="zmdi zmdi-globe"></i>
                    </div>
                </div>
            </div>
            <div class="link-preview-text-wrapper">
                <div class="link-preview-line">
                    <span class="link-preview-title" ng-bind="::linkPreview.title"></span>
                </div>
                <div class="link-preview-line">
                    <span class="link-preview-description" ng-bind="::linkPreview.description"></span>
                </div>
                <div class="link-preview-line">
                <span class="link-preview-url">
                    <a href="{{ ::linkPreview.url }}" target="_blank">{{ ::linkPreview.tld }}</a>
                </span>
                </div>
            </div>
        </div>
    </div>
</div>