Reputation: 42049
Here's a jsbin illustrating the issue, but I will explain it also below with code. I am making a custom directive in AngularJs that will be inserted once for every entry in the database, which I iterate over using ng-repeat
as you see here.
<div ng-controller="DemoCtrl as demo">
<h1> Hello {{ name }}
<div class="some-list" ng-repeat="customer in customers">
<div id="not-unique" class="not-unique" my-dumb-graphic datajson=customer></div>
I need to make a unique class or id
</div>
</div>
In case you didn't notice, the directive tucked into that code is my-dumb-graph
, with the corresponding myDumbGraphic
name in the code below. In order to insert the graphic, which I will do in the link function of the directive below, I need to be able to select a unique id or class in the html above, and I will need to be able to select it from within the link function in the directive, so somehow need to reference the id from the html in the js. You can see in the jsbin that inside the link function of the directive, the id is not yet unique (i.e. the dynamic part hasn't been computed yet), even though it's eventually unique by the time it's rendered to the dom.
<div id="not-unique" class="not-unique" my-dumb-graphic datajson=customer></div>
Rest of the code var app = angular.module('jsbin', ['ngRoute']) .config(function ($routeProvider) { 'use strict';
var routeConfig = {
controller: 'DemoCtrll'
};
$routeProvider
.when('/', routeConfig)
.otherwise({
redirectTo: '/'
});
});
app.controller('DemoCtrl', function($scope, $routeParams) {
$scope.name = "World";
$scope.customers = [
{
name: 'David',
street: '1234 Anywhere St.'
},
{
name: 'Tina',
street: '1800 Crest St.'
},
{
name: 'Michelle',
street: '890 Main St.'
}
];
});
app.directive('myDumbGraphic', function () {
return {
restrict: 'A',
scope: {
datajson: '='
},
link: function (scope, elem, attrs) {
...code to insert my dumb graphic...need to select unique id or class or both...need to select unique id from here
}
};
});
Update
As several people have suggested, there are multiple ways to create a dynamic id for a div, however, the dynamic part of the div id won't have computed by the time I need it in the link function. For example, If, following suggestion of other answer, I set id in the html to this <div id="id_{{::id}}"
then the dynamic part of it won't have computed by the time I need it to inside the link function, although if I inspect the dom after it's rendered it has computed. In the link function, I can access the div through the elem like this "#"+elem[0].id; and log statements show that at that time it hasn't computed- this is what log statements show for "#"+elem[0].id; ----> #id_{{::id}}
Upvotes: 0
Views: 4116
Reputation: 2569
The directive link function has the corresponding element pass in as a parameter, so you already have the selector:
link: function(scope, element, attrs) {
}
Alternatively, you could take leverage your $scope.customers array keys as unique ids and set view elements, pass the id into the directive, and use that as a selector (this assumes you jQuery loaded):
<h1> Hello {{ name }} </h1>
<!-- use customers array index -->
<div class="some-list" ng-repeat="(customerId, customer) in customers">
<!-- append customer id to this element id so it is unique -->
<div id="directive-element-selector-{{customerId}}" class="not-unique" my-dumb-graphic datajson=customer customer-array-id=customerId></div>
<div id="inner-selector-{{customerId}">
I need to make a unique class or id
</div>
</div>
</div>
directive:
app.directive('myDumbGraphic', function () {
return {
restrict: 'A',
scope: {
datajson: '=',
customerArrayId: '='
},
link: function (scope, elem, attrs) {
$('#directive-element-selector-' + customerArrayId) // jQuery selector, this should equal elem pass in as link function param
$('#inner-selector-' + customerArrayId) // inner selector
}
};
});
Upvotes: 2
Reputation: 5435
You can use the $scope $id property which will be unique for each directive and scope in your system, so you can do something like
<div class="myclass_{{::$id}}"></div>
or something like that
Note: the :: is for one time binding
Upvotes: 1