Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
208 views
in Technique[技术] by (71.8m points)

javascript - Transcluding ng-click in a directive

I am building an AngularJS directive. I want that directive to wrap other contents which have an ng-click inside of it. The resulting button does not do anything when clicked. Here is a simplified version of the code which I tried:

(HTML)

<div ng-app="someapp">
    <div ng-controller="Ctrl1">
        <h2>Example</h2>
        <my-dir data-x="1">
            <button ng-click="refresh()" id="refresh1">Refresh</button>
        </my-dir>
        <my-dir data-x="2">
            <button ng-click="refresh()" id="refresh2">Refresh</button>
        </my-dir>
    </div>
</div>

(JavaScript)

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

app.controller('Ctrl1', function($scope){ });

app.directive('myDir', function(){
    return {
        restrict: 'E',
        scope: {},
        template: '<div><p>Directive contents:</p><div ng-transclude></div></div>',
        transclude: true,
        link: function(scope, element, attrs){
            $scope.y = attrs.x+1;
            scope.refresh = function(){
                console.log("Refresh Called, y = ", $scope.y);
            }
        }
    };
});

How can I change it so that the button actually triggers the $scope.refresh() function?

Extra clarification:

I need local object information for the directive (there can be multiple of this directive in the single controller), so I create a new scope.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As dcodesmith points out, the transcluded ng-click will be bound to the controller's scope rather than the directive's. Depending on what exactly you want to do, you may wish for this to be the behavior (since the transcluded content is not part of the directive, why should it call a method of the directive's scope?). Personally, I would declare the method on the controller's scope instead.

app.controller('Ctrl1', function($scope){ 
    $scope.refresh = function() {
        console.log("Refresh called.");
    };
});

In this case, your directive should declare the isolate scope, even if there is nothing in it.

Update: Based on your comment, why not just include the button in the directive template? In this case, it will already be associated with the correct scope.

If there are some situations that you will not need the refresh button, then expose that as an option through the directive as an attribute:

<my-dir show-button='true'></my-dir>

// directive scope
scope: {
    showButton: '='
} 

The biggest problem that I have with this approach is using the "two-way-binding" operator (=) to cause 'true' and 'false' to be treated as expressions. I just don't like the feel of that very much.

Anyway, hopefully this solves your problem... One more comment, and I'm saying this not even knowing if what you are implementing is actually a refresh button, but if it is, I would take a minute and consider whether you really need a "refresh" button. Angular excels at eliminating refresh button!

Update 2:

I've created a plunkr that shows how I think I would handle your situation, especially if any of the miscellaneous controls are reused:

http://plnkr.co/edit/FhrSwcrSZScvCfhtCSjn

In this example, the two button directives are effectively children of the "videoPlayer" directive. Their logic is contained within that directive, but they are instantiated separately, and not required for the parent directive to operate. The "parent directive" (videplayer) simply exposes the API for the "children" to use. Also not that the methods of the parent are methods of the constructor, not the scope. I think this is very strange, but it is taken exactly from the angular documentation:

http://docs.angularjs.org/guide/directive (last example on the page)

Note that each videoPlayer directive will still have it's own isolate scope.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...