Nishchit
Nishchit

Reputation: 19074

Angular directive assign same scope with multi behaviour

I have a directive with refresh scope. In my case refresh should be an object or a function, so how can i assign this to my directive.

1. First case

<!--HTML-->
<directive 
  refresh="vm.refresh">
</directive>

//JS
scope:{refresh:"="}

2. Second case

<directive 
  refresh="vm.refresh(search)">
</directive>

//JS
scope:{refresh:"&"}

3. My case

<directive 
  refresh="vm.refresh or vm.refresh(search)">
</directive>

//JS - What to do ? need help
scope:{refresh:"=&needHelp"}

But i need this both features in my directive, So how can i isolate this both. I need to know applied refresh scope is object OR function in link function of directive.

Upvotes: 1

Views: 77

Answers (3)

sahbeewah
sahbeewah

Reputation: 2690

You can use expression binding to evaluate the scope variable, and use the $attrs object to determine the type. Refer to example below...

JSFiddle: http://jsfiddle.net/g4bft6rL/

JS

var myApp = angular.module('myApp',[]);

myApp.directive('myDirective', function() {
    return {
        restrict: 'E',
        scope: {
            refresh: '&'
        },
        controller: function ($scope, $attrs) {
            $scope.$watch('refresh', function (prev, curr) {
                $scope.text = 'refresh is a ' + getExpressionType($attrs.refresh);
                $scope.value = $scope.refresh();
            });
        },
        template: "result: {{ text }} = {{ value }}"
    };

    function getExpressionType (expression) {
        // naive, but you get the idea
        return expression.slice(-1)[0] === ')' ? 'function' : 'object';
    }
});

function MyCtrl($scope) {
    $scope.refresh = { a: 1 };
    $scope.refreshFn = function what (arg) {
        return {
            value: arg
        };
    };
    $scope.param = 123;
}

HTML

<div ng-controller="MyCtrl">
  <my-directive refresh="refreshFn(param)"></my-directive>
  <my-directive refresh="refresh"></my-directive>
</div>

Upvotes: 1

Ganesh Nemade
Ganesh Nemade

Reputation: 1599

You can try something like below, I havent tested this code but just consider the hint/idea.

<directive refresh="refreshFromOuter" search="outerSearchString">" </directive>

refreshFromOuter can be a string or function. in directive controller

 return {
        restrict: 'EA',
        scope: {
            name: '=',
          refresh:'=',
          search:'@'
        }, 
        controller:function($scope){
            console.log($scope);
          if(angular.isFunction($scope.show)){
            alert('is Function');
            $scope.refresh($scope.search || '');
          }
          else{
            alert($scope.refresh + 'as string');
          }
        },
        template: '<div>Some template</div>'
    };

Upvotes: 0

dfsq
dfsq

Reputation: 193261

This is tricky situation. In such case you could check for what type of expression refresh attribute holds. However, you need to parse attribute value manually with the help of $parse service.

.directive('directive', function($parse) {
  return {
    scope: {
      // some other bindings, scope is isolated
    },
    template: '<button ng-click="test()">Test</button>',
    link: function(scope, element, attrs) {

      // parse attribute expression (not evaluated yet)
      var callback = $parse(attrs.refresh);

      scope.search = 'Search query';

      scope.test = function() {

        // when needed to refresh: evaluate refresh callback
        var evalled = callback(scope.$parent, {search: scope.search});
        if (typeof evalled == 'function') {
          evaled(scope.search);
        }
      };
    }
  };
})

In case of refresh="vm.refresh(search)" situation callback(scope.$parent, {search: scope.search}) will do the trick. However, if this evaluation returns a function, it means that this is refresh="vm.refresh" case - then it enters the if block and executes this function with necessary parameter.

Demo: http://plnkr.co/edit/4W0SKOzpL5LUP0OAofp5?p=info

Upvotes: 2

Related Questions