Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing an object as attribute to compiled directive on the fly

I have a angular element on the page which needs to communicate with the rest of the non angular page elements.

I am creating directive elements on the fly, and appending it to its target div. I am trying to pass that created directive an object (ajax object), which contains just attributes.

The issue is that I can't figure out how to pass just this ajax object to the directive, as $compile requires a scope. When the http finishes, and because i have to use = in the directive, the directives are being over-ridden.

Please see my plunk: https://plnkr.co/edit/brTWgUWTotI44tECZXlQ ( sorry about the images ). Click the <button> to trigger the directive.

(function() {
'use strict';
var CHANNEL = 'podOverlay';
angular.module('CavernUI', [])
  .controller('CavernCtrl', function($scope,getItemService) {

    $scope.model = {};
    var _pods = $scope.model.pods = {};

    function getData(selector) {
      $(selector).each(function(i, pod) {
        _pods[+pod.dataset.item] = {
          $: $(pod)
        };
      });

      Object.keys($scope.model.pods).map(function(key) {
        getItemService.getItem(key).success(function(response) {
          _pods[key] = angular.extend(_pods[key], response);
          $scope.$broadcast(CHANNEL, _pods[key], $scope);
        });
      })
    }

    $scope.runPodCheck = function(selector) {
      getData(selector);
    }
  })
  .directive('podchecker', function($compile) {
     
     var createOverlay = function(e,data,scope){
         scope.data = data;
         // can i just pass data rather than scope.data?
         // If I pass the scope, then when another $broadcast happens
         // the scope updates, wiping out the last scope change.
         // Scope here really needs to be a static object that's
         // created purely for the hand off. But I don't know if 
         // that can be done.
         angular.element(data.$[0]).empty().append($compile('<overlay data="data"></overlay>')(scope));
     }

    return {
      restrict: 'E',
      scope: {
        check: '&',
      },
      templateUrl: 'tpl.html',
      link: function(scope,elm,attr){
         scope.$on(CHANNEL,createOverlay);
      }
    };
  })
  .directive('overlay', function() {
    return {
      restrict: 'E',
      scope: {
        o: '=data' // here is the problem. 
      },
      template: '<div class="overlay"><a href="{{o.url}}"><img ng-src="{{o.images.IT[0]}}"/></a></div>',
      link: function(scope, elm, attr) {
        
      }
    }
  })
  .service('getItemService', ['$http', function($http) {
    this.getItem = function(itemId) {
      return $http({
        method: 'GET',
        url: 'https://www.aussiebum.com/ajaxproc/item',
        params: {
          id: itemId,
          ajxop: 1
        },
      });
    };
  }]);
}());

Edits: Expected ouput: enter image description here

like image 966
Simon Avatar asked Feb 24 '16 19:02

Simon


People also ask

How do I pass data from one directive to another directive in AngularJS?

The best way to pass an object to an angular directive is by using the &. When you use &, angular compiles the string as an expression and sets the scope variable in your directive to a function that, when called, will evaluate the expression in the context of the directive's parent's scope.

What is a directive in HTML?

What are Directives? At a high level, directives are markers on a DOM element (such as an attribute, element name, comment or CSS class) that tell AngularJS's HTML compiler ( $compile ) to attach a specified behavior to that DOM element (e.g. via event listeners), or even to transform the DOM element and its children.

What is attrs in AngularJS?

Using attrs you are able to access the attributes defined in your html tag like <fm-rating ng-model="$parent.restaurant.price" symbol="$" readonly="true"> So in this case you will have access to the symbol and readonly attributes.


1 Answers

I'm not sure this is the best approach, but one way might be to manually create a new scope for each of the overlays.

So changed this:

var createOverlay = function(e,data,scope){
           scope.data = data;
           angular.element(data.$[0]).empty().append($compile('<overlay data="data"></overlay>')(scope));
       }

to this:

var createOverlay = function(e,data,scope){
           var overlayScope = scope.$new(false); // use true here for isolate scope, false to inherit from parent
           overlayScope.data = data;
           angular.element(data.$[0]).empty().append($compile('<overlay data="data"></overlay>')(overlayScope));
       }

Updated Plnkr: https://plnkr.co/edit/wBQ1cqVKfSqwqf04SnPP

More info about $new()

Cheers!

like image 68
Brent McFerrin Avatar answered Nov 08 '22 19:11

Brent McFerrin