angularjs transclusion scope access

A.J.Rouvoet picture A.J.Rouvoet · Jan 19, 2013 · Viewed 9.7k times · Source

I've set up a general dialog directive with a title and apply/cancel buttons. The dialog has an isolated scope.

The content of the dialog directive is transcluded and therefor it's scope is a sibling of the dialog scope:

From the Angular js docs:

However isolated scope creates a new problem: if a transcluded DOM is a child of the widget isolated scope then it will not be able to bind to anything. For this reason the transcluded scope is a child of the original scope, before the widget created an isolated scope for its local variables. This makes the transcluded and widget isolated scope siblings.

This presents a new problem for me though. The transcluded DOM should be able to respond the dialog when it is applied. Therefor I'd like to setup an 'applied' property on the dialog and let the transcluded DOM watch it. This is not possible though, because they are siblings!

Where am I going wrong?

Answer

David Bennett picture David Bennett · Jan 21, 2013

I've run into something similar and there are 2 ways (that I know of) to access the transcluded scope directly.

The first is to create the scope yourself inside a compile function and then pass it to the transclude linking function along with a clone linking function:

function compileFn(tElement, tAttrs, transclude) {
    return linkFn;
    function linkFn(scope, element, attrs) {
        scope = scope.$new();
        scope.name = attrs.works1;
        transclude(scope, function(clone) {
            element.find('div').append(clone);
        });
    };
}

The second is to create a controller and inject the $transclude service which is pre-bound to a new scope. Your clone linking function will receive the new scope as its 2nd parameter:

function Controller($element, $attrs, $transclude) {
    $transclude(function(clone, scope) {
        scope.name = $attrs.works2;
        $element.find('div').append(clone);
    });
}

In both cases you'll have to provide a clone linking function to do the transclusion yourself instead of using ngTransclude.

See http://jsfiddle.net/dbinit/wQC7G/6/ for examples of both.