简体   繁体   中英

Setting click handlers dynamically on generated dom by Angular

Whoever solves this will be the Javascript, Angular Genius...

It's about injecting clickHandlers (function/scope) to the dynamically generated DOM elements

In this basic setup the DOM elements are generated by Angular, Angular is bootstrapped to an element and content is populated by an array. .

Is there a way that we can set click handlers on each anchor dynamically (no need of cross browser implementation, addEventHandler would suffice).

It's best to look at the Fiddle link itself given below to get the full picture.

<div id="navigation" data-ng-cloak>
    <ul data-ng-controller="foliosController" class="nav nav-pills nav-stacked">
        <li data-ng-repeat="folio in folios" class="active"><a href="#">{{folio.title}}</a></li>
    </ul>
</div>

Javascript

var self = this;
var navigation = angular.module("navigation", []);
navigation.controller("foliosController", function($scope){self.foliosController($scope)});
angular.bootstrap(document.getElementById("navigation"), ["navigation"]);

Fiddle: http://jsfiddle.net/casadev/n50ecw5m/

Bonus: If there's a way to set only the first anchor as active.

EDIT: There's a clickHandler defined within the scope, need to link the clickHandler with the generated dom links.

clickHandler: function(event) {
    alert(event.target);
}

Edit 2: Some progress but attached clickHandlers manually to stay inside the scope, wished if angular could do it. http://jsfiddle.net/casadev/n50ecw5m/14/

Mini Question after my own answer: Is there a way to avoid templateUrl in case I don't need to have one?

Who made you use angular and gave you that requirement? All you need to do is ng-click="clickHandler($event)" , or even better ng-click="clickHandler(folio)" to pass the data you're interested in. ng-repeat constantly shuffles and creates/destroys elements when the list changes, manually managing those bindings would be a nightmare. You could use jquery of course and something like $('ul.nav-pills a ).on('click', clickHandler) . Then you would have to put your code in a . Then you would have to put your code in a $scope.$apply()` to get angular to notice any changes.

Instead of adding another dependency on jquery and creating an annoyance for anyone maintaining your code I would spend my time arguing to your boss that you should use ng-click .

Figured it out, use Router instead of clickHandlers on the generated content and assign controllers as per the link, routers can let you specify Controllers that I can have defined and called within the scope and call other functions within the scope. No need for ng-click or any sort of manual clickHandlers. I wish if I could not specify a templateUrl since I don't need but it's not working if I omit it, appreciate any comments.

<div id="navigation" data-ng-cloak>
<ul id="folios" ng-controller="FoliosController" class="nav nav-pills nav-stacked">
    <li data-ng-repeat="folio in folios" class="" active="true">
        <a href="#/folios/{{folio.productId}}" id="{{folio.productId}}">{{folio.title}}</a>
    </li>
</ul>
<ng-view></ng-view>

puremvc.define(
{
name: "modules.search.view.components.Navigation",

constructor: function() {
    var self = this;
    var navigation = angular.module("navigation", ["ngRoute"]);

    navigation.config(function($routeProvider, $locationProvider){self.config($routeProvider, $locationProvider)});
    navigation.controller("FoliosController", function($scope, $location){self.foliosController($scope, $location)});
    navigation.controller("SearchController", function($scope, $location, $routeParams){self.searchController($scope, $location, $routeParams)});

    angular.bootstrap(document.getElementById("navigation"), ["navigation"]);
}
},
{
$scope: null,
$location: null,
folios: [],

foliosController: function($scope, $location) {
    this.$scope = $scope;
    this.$location = $location;
    this.$scope.folios = this.folios;
},

searchController: function($scope, $location, $routeParams) {
    console.log($routeParams);
},

config: function($routeProvider, $locationProvider) {
    $routeProvider.
    when("/", {templateUrl:"js/modules/partials/list.html"}).
    when("/folios/:productId", {templateUrl:"js/modules/partials/search.html", controller:"SearchController"});
},

init: function(folios) {
    for(folio in folios) {
        this.folios.push(folios[folio]);
    }
    this.$scope.$apply();
}
},
{});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM