adinas
adinas

Reputation: 4550

Using a function created in parent scope and also local scope varibles in an AngularJS directive with a template

So I am trying to create a directive which will replace an element with HTML which includes an ng-click which calls a function created in $scope.

An example I made can be found at http://jsfiddle.net/adinas/wbfu9ox3/5/ My HTML is

<div ng-app="myapp" ng-controller="mycontroller">
{{greeting}}

<!--This works-->
<div xyz></div>

<!--This works-->
<div ng-click="dosomething('Click me 2')">Click me 2</div>

<!--The click added in the directive here does NOT work-->
<div abc mytext="Click me 3"></div>  

My JS is

var myapp = angular.module('myapp',[]);
myapp.controller('mycontroller', ['$scope', function($scope) {
$scope.greeting = 'Hola!';

$scope.dosomething = function (what) {
    alert(what);
};
}]);
//Works
myapp.directive('xyz', function () {
    return {
        template: '<div ng-click="dosomething(\'Click me 1\')">Click me 1</div>'
    };
});
//Does not work
myapp.directive('abc', function () {
    return {
        template: '<div ng-click="dosomething(\''+attr.mytext+'\')">Click me 3</div>'
    };
});

I made 3 elements. The first two show that A. without the directive the click work. B. a directive without using the 'dosomething' function also works.

The 3rd element which tries to pass a parameter to the 'abc' directive and also call the function fails.

How can I also pass a parameter and also use the function? Thanks.

Upvotes: 0

Views: 57

Answers (2)

JLRishe
JLRishe

Reputation: 101748

Well, if you look in the console, you will see an error that shows why this is not working:

Error: attr is not defined

You're trying to access an attr variable that doesn't exist.

The way to include attribute values in your directive template is to include them in the directive's scope:

scope: {
    mytext: '@'
}

This means that there will now be a mytext variable in the scope of the directive.

This creates a problem, however, since the use of the scope: {} option creates an isolate scope for the directive, and this means that the enclosing controller's scope is not part of the directive's scope.

If feasible, the clean approach here is to also pass in the dosomething function as a parameter of the directive:

<div abc mytext="Click me 3" action='dosomething'></div>  

return {
    template: '<div ng-click="action(mytext)">Click me 3</div>',
    scope: {
        mytext: '@',
        action: '='
    }
};

http://jsfiddle.net/jx1hgjnr/1/

But if that's not what you want to do and you really want to access dosomething from the parent scope, one thing you can do is use $parent.dosomething:

return {
    template: '<div ng-click="$parent.dosomething(mytext)">Click me 3</div>',
    scope: {
        mytext: '@'
    }
};

http://jsfiddle.net/c815sqpn/1/

Upvotes: 1

Petr Averyanov
Petr Averyanov

Reputation: 9486

Such directive should have isolated scope, so it can be used everywhere. That is simple directive that introduce two parameters: func and param.

app.directive('pit', function () {
    return {
        scope : {
          func: '=',
          param: '='
        },
        template: '<button ng-click="func(param)">Click me 3</button>'
    };
});

And this is how u use it in html:

<div pit func="test1" param="test2"></div>

My plunker: http://plnkr.co/edit/YiEWchRPwX6W7bohV3Zo?p=preview

Upvotes: 1

Related Questions