Search code examples
scopeangularjstransclusion

angularjs transclusion scope access


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?


Solution

  • Oke, I think I've found a solution. I've wrapped the actual dialog in a directive that defines the scope over the dialog. The content of the dialog is still transcluded in the dialog, but since it will take it's parent scope from the parent of the dialog (!!) and not the dialog itself (transclusion works this way), this will work quite nicely.

    Further, I can have the sg-import directive respond when the dialog is applied by using a &property on the dialog. When the dialog is applied, I have it evaluate the sg-apply function in context of the parent scope (the scoping is done automatically, I just have to call the method from the controller's apply() function).

    <div sg-import>
        <div 
            sg-dialog title="Import Photographs" 
            visible="show_import_dialog" 
            sg-apply="upload()"
        >
            <div class="drop-zone">
                <div sg-photo title="{{ file.name }}">
                </div>
                <input type="file" multiple />
            </div>
        </div>
    </div>