Pregunta

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?

¿Fue útil?

Solución

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

Otros consejos

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top