Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending JSON object with function to another directive's controller

I would like to send JSON object with function template from app.controller to another directive controller. I decided to send this variable as attribute of inner directive's element. The problem is that object which is inside $attr.valueAtt in my directive controller is "[object Object]" and I can't get it:

My code:

var value = (
  [{
     functionLabel:'Fun', 
     functionTemplate: function(param1,param2){
       alert(param1);
     }, 
     functionParams: ['PARAM1','PARAM2']
  }]);

Then I add it in controller as attribute of directive element:

angular.element(document.getElementById('space-for-modals'))
         .append($compile("<modal-dialog visible='true' data-backdrop='static' valueAtt='"+value+"'></<modal-dialog>")($scope));

And try to get "value" in my directive controller:

 $scope.functions=  $attrs.valueAtt;

But in $scope.functions is only "[object Object]". Is there any way to send function template from one to another controller to call it later?

like image 645
klahcim Avatar asked Mar 31 '26 19:03

klahcim


1 Answers

The problem is that when you do valueAtt='"+value+"', JavaScript converts value to a string - which is "[object Object]". You need to store your object in the scope and then reference it by name in the HTML attribute. Something like this:

  var scope2 = scope.$new();
  scope2.foo = [{
     label:'Fun', 
     fn: function(param1, param2){
       alert("Callback function says: " + param1)
     }, 
     params: ['PARAM1', 'PARAM2']
  }];

  angular.element(document.getElementById('space-for-modals'))
     .append($compile("<modal-dialog visible='true' data-backdrop='static' value-att='foo'>Modal dialog</<modal-dialog>")(scope2));

Then in your modal dialog link function you can dereference value-attr to get foo:

link: function(scope, elem, attrs) {
  scope.functions = scope[attrs.valueAtt];
}

And in your dialog controller, you can access the functions member. Note that this won't be ready until after the link function has been called, so you need to use a watch:

  $scope.$watch('functions', function(functions) {
    if (functions == null)
      return;
    var ft = functions[0];
    ft.fn.apply(null, ft.params);
  });

Here's a demo.

I must say, it's a bit odd to be compiling HTML like this - why not just use a template in your directive declaration? If it's because you want to put the content at another level of your DOM, consider using a service to communicate with it (basically, you set a field on a shared singleton object). Also, you could use an isolate scope to avoid binding the attribute yourself.

A service could store a callback function that would be triggered by your controller:

.service('modalService', [function() {
  var proxy = function(message) {
    proxy.callback(message);
  };
  proxy.callback = function() {};
  return proxy;
}])

If you inject that into both your dialog and trigger controllers, you can communicate between them. The modal dialog should replace the callback with its own function. Here's another demo.

like image 156
z0r Avatar answered Apr 03 '26 07:04

z0r