Tito
Tito

Reputation: 852

Passing into a directive without adding it to scope

I have a directive where a list(array) of items is passed in through the scope of the controller into the scope of the directive whereby the template of the directive then has access to the items.

I would like to have it so that the list of items is passed to the directive (where it is then used within the link function) and then not directly accessible through the directive's template.

i.e. if we had the following directive:

directive('itemList', function(){
return {
    scope: {
        items: '='
    }
    link: function(scope, elem, attrs){
        var item-list = scope.items;
        // ... want to manipulate first ...
    }
}
})

the variable scope.items is now available to any template that the directive uses. Whereas I don't want that to be the case and would like to pass in something to the directive without making it known to the scope. Is this possible?

Upvotes: 0

Views: 45

Answers (2)

user2943490
user2943490

Reputation: 6940

You can use the $parse service to retrieve the value without using scope: {}, but you will lose the 2 way data binding that you inherently get from using scope: { items: '=' }. As mentioned by Dana Cartwright, if you need 2 way binding, you have to set this up manually with watches.

directive('itemList', function($parse){
    return {
        link: function(scope, elem, attrs){
            var itemList = $parse(attrs['items'])(scope);

            // do stuff with itemList
            // ...
            // then expose it
            scope.itemList = itemList;
        }
    };
});

Upvotes: 1

Dana Cartwright
Dana Cartwright

Reputation: 1576

Since the directive scope pretty much by definition is the scope used by the directive's template, I don't see any obvious way of doing this in a strict information hiding way. But, why not just use a different name for the passed scope variable and what the template binds to? For example, if you said scope: { myPrivatePassedItems: '=items' }, you can now work with scope.myPrivatePassedItems as much as needed before setting it as scope.items. With this approach, the HTML in both the usage of the directive and the directive's template just sees "items", but internally your directive has its own "private" variable.

I should add that the above is the simple change needed for the one-way data flow from the consumer to the directive template. If you also need to update the original items array, you will also want to add a scope.$watch on the scope.items array after you have done your initial setup. You would then need to carry those changes (possibly with modifications) back to scope.myPrivatePassedItems in order to update the consumer's array.

Upvotes: 1

Related Questions