0

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>

2
  • 1
    Do you see any console.log? Or error? What if you add the ng-click to the <div class="link-preview-delete pull-right"> part ; any difference? Do you have the possibility to create a JsFiddle / Plunkr / ... ? Commented Jun 14, 2017 at 8:53
  • No error, no console log. Will try for Plunkr. Commented Jun 14, 2017 at 9:15

3 Answers 3

1

You need to add empty dependency to your module, Like:

 angular.module('commons.ui', [])

and, have to use controller as syntax(if not used) in HTML, Like:

ng-controller="LinkPreviewController as $ctrl"

Working Demo :

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

function linkPreview() {
  return {
    restrict: 'E',
    replace: true,
    templateUrl: 'app/commons/ui/components/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: 'Go COYO',
    description: 'COYO is an integrated platform for your official company news, social collaboration and team messaging.',
    url: 'http://www.coyoapp.com/en/tour',
    tld: 'coyoapp.com'
  }, {
    image: '',
    title: 'Hacker News',
    description: 'News for the technically interested',
    url: 'https://news.ycombinator.com/',
    tld: 'news.ycombinator.com'
  }];

  function deletePreview() {
    console.log('clicked');
    $log.info('should be deleted');
    vm.linkPreviews.splice(0, 1);
  }
}
<script src="https://code.angularjs.org/1.5.2/angular.js"></script>
<div ng-app="commons.ui" ng-controller="LinkPreviewController as $ctrl">
  <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">spanToClick</i>
                </span>
        </div>
      </div>
    </div>
  </div>
</div>

Update:

In your directive you are using scope:{}, which creates isolated scope, So your code doesn't work.

Now further ng-repeat create new child scope, So your div gets repeated but internal logic of ng-repeat like delete click is under new child scope , So it doesn't work.

If you'll do $parent.$ctrl then it will point to parent and will work.

See this plunker

Overall easiest fix is to remove isolated scope from directive. scope: {}

Sign up to request clarification or add additional context in comments.

3 Comments

Defining the controller like ng-controller="LinkPreviewController as $ctrl" actually does make my code work. However now I'm curious how the binding in the function does fail. controller: 'LinkPreviewController', controllerAs: '$ctrl' I mean the ng-repeat gets rendered so why does not the ng-click work?
@Daniel : In your directive you are using scope:{}, which creates isolated scope, So your code doesn't work. because ng-repeat created new child scope. See my updated answer
@Daniel : did the updated answer solved your problem, you can accept answer if solved, could help others as well. Just going through very old answers.. :-D
0

You wrong the function declaration in controller.

To use function from controller you need to set it like

this.deletePreview

or

$scope.deletePreview

(in this last case you haven't to write $ctrl in the ng-click view. Remember to inject $scope!).

1 Comment

I would expect that the lines var vm = this; vm.deletePreview = deletePreview; equal this.deletePreview
0

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.