Michael P.
Michael P.

Reputation: 1413

Can't seem to bind event handlers to directive-generated markup in Angular.js

I'm attempting to bind an event handler to elements that don't yet exist within the DOM but am running into issues. I think where the problem begins is at line #51, where I attempt to find an element that doesn't exist (because ng-repeat hasn't yet generated it). Is there a way around this without creating a binding that is too general (e.g., $("a").on("click", function () {});)?

cover-photo-carousel.js

  1 var MyApp = angular.module("MyApp");
  2
  3 MyApp.directive("coverPhotoCarousel", ["$compile", function ($compile) {
  4   return {
  5     restrict: "EA",
  6     replace: true,
  7     templateUrl: "cover-photo-carousel.html",
  8     scope: true,
  9     controller: function ($scope) {
 10       $scope.images = [
 11         {
 12           title: "",
 13           url: "http://blah.com/abc.jpg",
 14           description: "",
 15           cover: true
 16         },
 17         {
 18           title: "",
 19           url: "http://blah.com/abc.jpg",
 20           description: ""
 21         },
 22         {
 23           title: "",
 24           url: "http://blah.com/abc.jpg",
 25           description: ""
 26         },
 27         {
 28           title: "",
 29           url: "http://blah.com/abc.jpg",
 30           description: ""
 31         }
 32       ];
 33       $scope.bark = function () {
 34         console.log("Something.");
 35       };
 36     },
 37     link: function (scope, element, attributes) {
 38
 39       if (scope.images.length > 1) {
 40         element.find(".cover-photo-control .glyphicon").show();
 41       }
 42
 43       scope.images.forEach(function (value, index) {
 44         if (value.cover) {
 45           element.css({
 46             "background-image": "url(" + value.url + ")"
 47           });
 48         }
 49       });
 50
 51       element.find(".thumbnails-container .thumbnails ul li a").on("click", function (e) {
 52         e.preventDefault();
 53         element.css({
 54           "background-image": "url(" + scope.images[1].url + ")"
 55         });
 56       });
 57     }
 58   }
 59 }]);

cover-photo-carousel.html

<div class="cover-photo-carousel">
  <div class="cover-photo-control back text-center">
    <span class="glyphicon glyphicon-chevron-left"></span>
  </div>
  <div class="cover-photo-control forward text-center">
    <span class="glyphicon glyphicon-chevron-right"></span>
  </div>
  <div class="thumbnails-container">
    <div class="thumbnails">
      <ul class="clearfix">
        <li ng-repeat="image in images"> 
          <a href="#"><img src="{{image.url}}" alt="" width="90"  /></a>
        </li>
      </ul> 
    </div>
  </div>
</div>

Upvotes: 0

Views: 831

Answers (2)

Arun P Johny
Arun P Johny

Reputation: 388316

The angular way could be something like

var app = angular.module('my-app', [], function() {

})

app.controller('AppController', function($scope) {

  $scope.message = "Welcome";
})
app.directive("coverPhotoCarousel", ["$compile",
  function($compile) {
    return {
      restrict: "EA",
      replace: true,
      templateUrl: "cover-photo-carousel.html",
      scope: true,
      controller: function($scope) {
        $scope.images = [{
          title: "",
          url: "http://placehold.it/90&text=abc",
          description: "",
          cover: true
        }, {
          title: "",
          url: "http://placehold.it/90&text=def",
          description: ""
        }, {
          title: "",
          url: "http://placehold.it/90&text=ghi",
          description: ""
        }, {
          title: "",
          url: "http://placehold.it/90&text=jkl",
          description: ""
        }];
        $scope.bark = function() {
          console.log("Something.");
        };
        $scope.myStyle = {};
        $scope.clicked = function(image) {
          $scope.myStyle['background-image'] = 'url(' + image.url + ')'
        }
      },
      link: function(scope, element, attributes) {

        if (scope.images.length > 1) {
          element.find(".cover-photo-control .glyphicon").show();
        }

        scope.images.forEach(function(value, index) {
          if (value.cover) {
            element.css({
              "background-image": "url(" + value.url + ")"
            });
          }
        });

        element.find(".thumbnails-container .thumbnails ul li a").on("click", function(e) {
          e.preventDefault();
          element.css({
            "background-image": "url(" + scope.images[1].url + ")"
          });
        });
      }
    }
  }
]);
.cover-photo-carousel {
  background-repeat: no-repeat;
  background-position: center center;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="my-app" ng-controller="AppController">

  <cover-photo-carousel></cover-photo-carousel>
  <script type="text/ng-template" id="cover-photo-carousel.html">
    <div class="cover-photo-carousel" ng-style="myStyle">
      <div class="cover-photo-control back text-center">
        <span class="glyphicon glyphicon-chevron-left"></span>
      </div>
      <div class="cover-photo-control forward text-center">
        <span class="glyphicon glyphicon-chevron-right"></span>
      </div>
      <div class="thumbnails-container">
        <div class="thumbnails">
          <ul class="clearfix">
            <li ng-repeat="image in images">
              <a href="#" ng-click="clicked(image)">
                <img src="{{image.url}}" alt="" width="90" />
              </a>
            </li>
          </ul>
        </div>
      </div>
    </div>
  </script>
</div>

Upvotes: 1

hon2a
hon2a

Reputation: 7214

Use ng-click to execute click handlers in AngularJS.

Upvotes: 0

Related Questions