sar
sar

Reputation: 1287

How to pass array or object to directive as string and then use it as variable inside directive

I have directive 'copyPaste' which copies element value to the element specified in 'destination' attribute.

// html code
<div ng-app='app'>
 <div ng-controller="mainController">
 <input type='text' ng-model='firstInput' copy-paste destination='secondInput'>
 <input type='text' ng-model='secondInput'>

 <!-- following does not work -->

   <input type='text' ng-model='param.firstInput' copy-paste destination='param.secondInput'>
 <input type='text' ng-model='param.secondInput'>

 </div>
</div>


//directive code

module.directive('copyPaste',['$rootScope',function($rootScope){
 return {
 restrict:'A',
 link:function(scope,element,attrs,ctrl){
 var destination=attrs.destination;
 scope.$watch(attrs.ngModel, function (v) {
            scope[destination]=v 
            });
 }
 }
}])

//controller

    module.controller('mainController',['$scope',function($scope){
     $scope.firstInput='hello'
    }]);

Above code works if I pass simple variable. If I pass object , array it does not work . How can I pass array and objects to directive as string then use as variables. I dont want to run directive in isolate scope, in isolate scope I need to call $scope.$apply to update binding so trying to avoid isolate scope.

JsFiddle

Upvotes: 0

Views: 234

Answers (3)

Arno_Geismar
Arno_Geismar

Reputation: 2330

Ok so I got this to work. This should do it see -> plunk:

basically im traversing your scope tree to find the object for which you want to set the value. Not the prettiest but it gets the job done

var module = angular.module('app', []);
module.directive('copyPaste', ['$rootScope', function($rootScope) {
  return {
    restrict: 'A',
    link: function(scope, element, attrs, ctrl) {
      var destination = attrs.destination;


scope.$watch(attrs.ngModel, function(v) {
        var splitted = destination.split('.');
        if (splitted.length > 1) {
          var value = null;
          var lastKey = "";
          for (var i = 0; i < splitted.length; i++) {
          if(value == null) {
          value = scope[splitted[i]];
          } else {
          if(value[typeof splitted[i] == 'Object']) {
          value = value[splitted[i]];
          } else {
            lastKey = splitted[i];
          }

                    }
          }
          value[lastKey] = v;

                } else {
        scope[destination] = v;
        }
            });
    }
  }
}])

module.controller('mainController', ['$scope', function($scope) {
  $scope.firstInput = 'hello';
  $scope.secondInput = "";
  $scope.param = {};
  $scope.param.secondInput = "";
  $scope.param.firstInput = "Again";
}]);

Upvotes: 1

remborg
remborg

Reputation: 548

I think you should use an event instead of $watch, it would be more performant. Have a look at ngChange (https://docs.angularjs.org/api/ng/directive/ngChange)


I think the problem could be due to $watch that is not checking your variable properly.

You could try to set the objectEquality boolean to true (doc here https://docs.angularjs.org/api/ng/type/$rootScope.Scope )

 scope.$watch(attrs.ngModel, function (v) {
                scope[destination]=v 
            }, true); // <-- deep object check

Upvotes: 0

frank91
frank91

Reputation: 131

You can use JSON.stringify for convert value to a JSON string, and then later use JSON.parse which turns a string of JSON text into a Javascript object

Upvotes: 0

Related Questions