1

I have two directives, and I intent to populate an ng-repeat from the second one with a $http query made in the first one. How could I pass this data from one to the other?

Here's the code:

var app = angular.module('myApp');


app.directive('release', ['musicInfoService',
  function(musicInfoService) {

    return {
      restrict: 'E',
      scope: {
        release: '=',
        artist: '='
      },
      template: '<div class="release">' +
        '<div class="wrapper"><img class="img-responsive" ng-src="{{imageSrc}}"/><div id="text" ng-click="getVersions(release)"></div></div>{{release.title | characters:65}}' +
        '</div>',
      replace: false,
      link: function(scope, elem, attr) {
        var defaultImage = 'img/record-default.png';
        scope.imageSrc = defaultImage;
        musicInfoService.getAlbumInfo(scope.artist.name, scope.release.title)
          .success(function(data) {
            if (data.error) return;

            var image = data.album.image[2],
              imageUrl = defaultImage;

            if (image['#text'] !== '') {
              imageUrl = image['#text'];
            }

            scope.imageSrc = imageUrl;
          });

        scope.getVersions = function(release) {

          if (angular.isUndefined(release)) return;

          musicInfoService.getReleaseVersions(release.id)
            .success(function(data) {
              release.versions = data.versions;
            });
        };
      }
    };
  }
]);

app.directive('theDirective', ['musicInfoService',
  function(musicInfoService) {
  return {
    restrict: 'A',
    scope: { position: '@', last: '@', release: '=',
        artist: '=' },
    link: function(scope, element, attrs) {

      element.bind('click', function() {

        // 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-xs-12"><ul><li>{{release.title}}</li><li ng-repeat="version in release.versions | filter:\'!mp3\' | filter:\'!wav\' ">{{version.format}}</li></ul></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');
      });
    }
  };
}
]);

The first directive makes this call:

      scope.getVersions = function(release) {

          if (angular.isUndefined(release)) return;

          musicInfoService.getReleaseVersions(release.id)
            .success(function(data) {
              release.versions = data.versions;
            });
        };

And I need to use the results here, in the second directive:

var collapseQuery = document.querySelector('#collapse');
    var collapse = collapseQuery === null ?
      angular.element('<div id="collapse" class="col-xs-12"><ul><li>{{release.title}}</li><li ng-repeat="version in release.versions | filter:\'!mp3\' | filter:\'!wav\' ">{{version.format}}</li></ul></div>') :
      angular.element(collapseQuery);

Any thoughts?

EDIT: I've created a Plunker to illustrate the problem.

1
  • You could put release on the parent scope and bind it to both directives or you could store the data in a service and inject it into both directives. Commented Mar 24, 2014 at 15:13

1 Answer 1

1

I would recommend to use factory to create your service which holds the shared data. This service is then injected into both of your directives as a dependency.

app.factory("sharedDataService", function() {
            return {
                yourData: "whatever"
            };
        });

see this :

hope this helps

UPDATE

I created a plunker to illustrate what I mean

Sign up to request clarification or add additional context in comments.

3 Comments

I've created a Plunker (see EDIT). Where would I have to create the factory? I'm a bit confused cause there're multiple services (also dependent one from another) and I wouldn't know how to adapt it. Got lots of help to get here and now there're pieces of code I don't fully understand...
Added a Plunkr plnkr.co/edit/LUNCjOSWSaVf0F6uT6Dd?p=preview and updated my answer.
Peter, I implemented it but I get a "TypeError: Cannot set property 'shared' of undefined" error. The code is in the directives.js of this plunker. Care to take a look? Dunno what might I have missed..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.