Reputation: 2169
I have a directive that calculates the position of the clicked element from a grid and gets positioned in place.
So far the directive appears where is it supposed to, but I'm attempting to trigger a $http call to populate the directive (one call for each element clicked) and so far I had no luck.
You can see the directive code here:
angular.module('myApp')
.directive('theDirective', [function() {
return {
restrict: 'A',
scope: { position: '@', last: '@', release: '='},
link: function(scope, element, attrs) {
element.bind('click', function() {
// Makes http call to get versions
function getVersions(id){
$http.get('http://api.discogs.com/masters/' + release.id + '/versions').
success(function (data5) {
$scope.versions = data5.versions;
});
}
// Highlight clicked element
angular.element(document.querySelector('.clicked')).removeClass('clicked');
element.addClass('clicked');
// Create the collapse element or select existing one
var collapseQuery = document.querySelector('#collapse');
var collapse = collapseQuery === null ?
angular.element('<div id="collapse" class="col-md-12 col-xs-12"> \
<div class="inner"> \
<ul> \
<li class="title">{{release.title}}</li> \
<li class="row top" ng-show="versions"> \
<div class="col-md-1">Year</div> \
<div class="col-md-3">Format</div> \
<div class="col-md-3">Label</div> \
<div class="col-md-2">Country</div> \
<div class="col-md-2">Cat. Nº</div> \
</li> \
<li class="row" ng-show="versions" ng-repeat="version in versions | filter: \'!file\' | orderBy: version.released"> \
<div class="col-md-1">{{(version.released | release:4) || \'-----\'}}</div> \
<div class="col-md-3">{{version.format}}</div> \
<div class="col-md-3">{{version.label}}</div> \
<div class="col-md-2">{{version.country}}</div> \
<div class="col-md-2">{{version.catno}}</div> \
</li> \
<li class="row top" ng-hide="!release.format"> \
<div class="col-md-1">Year</div> \
<div class="col-md-3">Format</div> \
<div class="col-md-3">Label</div> \
</li> \
<li class="row" ng-hide="!release.format"> \
<div class="col-md-1">{{release.year}}</div> \
<div class="col-md-3">{{release.format}}</div> \
<div class="col-md-8">{{release.label}}</div> \
</li> \
</ul> \
</div> \
</div>') :
angular.element(collapseQuery);
// Based on the position of the clicked element calculate the rounded number up to the nearest multiple of four
var calculatedPosition = Math.ceil(scope.position / 4) * 4;
// Get the element at the calculated position or the last one
var calculatedQuery = document.querySelector('[position="' + calculatedPosition + '"]');
if (calculatedQuery === null) calculatedQuery = document.querySelector('[last="true"]');;
var calculatedElement = angular.element(calculatedQuery);
// Insert the collapse element after the element at the calculated position
calculatedElement.after(collapse);
// Highlight the calculated element
angular.element(document.querySelector('.calculated')).removeClass('calculated');
calculatedElement.addClass('calculated');
});
scope.$on('$destroy', function() {
element.unbind('click');
});
}
};
}
]);
I also made a Plunker.
Any pointers on which direction should I take?
Upvotes: 2
Views: 340
Reputation: 9497
You are attempting to use $http
in the directive without injecting it as a dependency. It should be included using inline injection annotation, like this:
angular.module('myApp').directive('theDirective', function($http) {...
Your $http
call makes use of the release
scope property,
$http.get('http://api.discogs.com/masters/' + scope.release.id + '/versions').
but (at least in your plunkr) you didn't include it in the directive element tag. Add it like this:
<div the-directive release="release" ng-repeat="release in releases...
Finally, your directive displays the results of the $http
call in a dynamically created element. To achieve binding in this element, you need to compile it. So add $compile to the list of directive dependencies:
angular.module('myApp').directive('theDirective', function($http, $compile) {...
When you are finished manipulating the DOM, compile the element:
var collapse = angular.element('<div>' ...
...
$compile(collapse)(scope);
I fixed a few other things, but they don't really relate to using $http
in a directive. Here is a working plunker: http://plnkr.co/ttV0ZowaL8Tyz1hAkZak
Upvotes: 2
Reputation: 64853
I think you are trying to do too much in your directive. I would handle all your events on your controller, and ajax calls in a service.
As for your markup I would nest is as follows
artists
releases
release info
You can toggle the visibility status of each layer within your controller and load the necessary data when needed.
Then I would include a very basic directive to handle the positioning and only the positioning of the release details.
Upvotes: 1