Search code examples
javascriptangularjsangularjs-directiveangularjs-scopeangularjs-ng-transclude

AngularJS : How to pass an object from the directive to transcluded template


I have a directive that creates a UI that allows the user to perform a search. The directive wraps content which will transclude and become the template for each individual search result. Something like this:

<search>
  <div class="someStyle" ng-click="selectResult(result)">{{result.Name}}</div>
</search>

I'd like the ng-click to call the selectResult function on the controller's scope, but have the result object come from the directive. How can I accomplish this with an isolated scope in the directive?


Solution

  • Instead of using ng-transclude, you can build your own search transclude directive that can be used to put result onto the transcluded scope. For example, your search directive might look something like this with ng-repeat and the search-transclude directive where you want the transcluded content:

    .directive("search", function (SearchResults) {
        return {
            restrict: "AE",
            transclude: true,
            scope: {},
            template: '<div ng-repeat="result in results">Search Relevance:' +
            '{{result.relevance}}' +
            //the most important part search-transclude that receives the current
            //result of ng-repeat
            '<div search-transclude result="result"></div></div>',
            link: function (scope, elem, attrs) {
                //get search results
                scope.results = SearchResults.results;
            }
        }
    })
    

    Build search transclude directive as follows:

    .directive("searchTransclude", function () {
        return {
            restrict: "A",
            link: function (scope, elem, attrs, ctrl, $transclude) {
                //create a new scope that inherits from the parent of the
                //search directive ($parent.$parent) so that result can be used with other
                //items within that scope (e.g. selectResult)
                var newScope = scope.$parent.$parent.$new();
                //put result from isolate to be available to transcluded content
                newScope.result = scope.$eval(attrs.result);
                $transclude(newScope, function (clone) {
                    elem.append(clone);
                });
            }
        }
    })
    

    The transcluded content will now be able to see selectResult function if it exists in the scope where the search directive was created. Example here.