Ciel
Ciel

Reputation: 4440

angularjs - isolate scope between multiple different directives

I am trying to create three different directives that need to communicate together, and this isn't really a problem but I would like to explore the possibility of using an isolate scope, or at least as small a scope as possible between them.

Because sharing directly on the controller scope is so discouraged, I enacted this to try and get around that. The only solution I've seen immediately is to make all three behaviors in the same single directive, so that they all use the same scope - but this is very messy.

This is an extremely slim example of how it works. The full code is very long and it's not useful without a lot of extra context. I'm trying to trim it down to just what I need help with.

1. Is there a better way to share these scope properties between the directives?

2. Can I do it using an isolate scope, to reduce the clutter and load on the controller?

3. The reason for sharing information is a bit hard to explain briefly.

directives

angular.module('app', [])
.directive('dataSourceUrl', ['$parse', function($parse) {
   return {
        restrict: 'A',
        priority: 10,
        link: function(scope, element, attributes) {
            var path = attributes.dataSourceUrl;
                
            angular.extend(scope.options, {
                /* more code */
            });
        }
   }
}])
.directive('dataSourceOptions', 
    ['$parse', function($parse) {
    return {
        restrict: 'A',
        priority: 9,
        link: function(scope, element, attributes) {
            var options = scope.$eval(attributes['dataSourceOptions']);
            
            angular.extend(scope.options, {
                /* more code */
            });
        }
    }
}])
.directive('dataSourceColumns', 
    ['$parse', function($parse) {
    return {
        restrict: 'A',
        priority: 9,
        link: function(scope, element, attributes) {
            var columns = scope.$eval(attributes.dataSourceColumns);
            
            angular.forEach(columns, function(value, key) {
                switch(value) {
                    case "Id":
                        scope.options.columns.push({ field: "Id" /* more code */ });
                        break;
                    case "Name":
                        scope.options.columns.push({ field: "Name" /* more code */ });
                        break;
                    /* more code */
                }
            });
        }
    }
}]);

notes

My experience with angular is minimal, I am very new. I have researched isolate scope extensively, but it is proving to be more difficult than I thought. My goal is to use these directives kind of like this ...

<div kendo-grid data-source-url="'path/to/data'" 
     data-source-options="options" 
     data-source-columns="['Id','Name','Abbreviation','Group']">
</div>

Upvotes: 1

Views: 624

Answers (2)

harishr
harishr

Reputation: 18055

you can have multiple isolate scoped directive on same element. though as far as i remember, read it somewhere, that multiple isolate scoped directive do share the scopes.

you can read more about scopes here

regarding sharing the data between directives, are the directives independent or are they in parent-child relationship?

if parent child then use require property of directives. and pass data only to parent directive and access it in child directive.

if they are sibling or independent, pass data to each directive separately.

lets assume that dataSourceUrl display changes on basis of parameters in dataSourceOptions. then you can use require property.

.directive('dataSourceUrl', 
    ['$parse', function($parse) {
    return {
        restrict: 'A',
        require: 'dataSourceOptions'
        link: function(scope, iElement, iAttrs, ctrlOptions)
               {
                         //ctrlOption.showHeadeers or something
                }

Upvotes: 2

Shohel
Shohel

Reputation: 3934

Here is the fiddle where two directive are integrated

http://jsfiddle.net/Wijmo/MTKp7/

and code is

angular.module("btst", []).
directive("btstAccordion", function () {
    return {
        restrict: "E",
        transclude: true,
        replace: true,
        scope: {},
        template:
            "<div class='accordion' ng-transclude></div>",
        link: function (scope, element, attrs) {

            // give this element a unique id
            var id = element.attr("id");
            if (!id) {
                id = "btst-acc" + scope.$id;
                element.attr("id", id);
            }

            // set data-parent on accordion-toggle elements
            var arr = element.find(".accordion-toggle");
            for (var i = 0; i < arr.length; i++) {
                $(arr[i]).attr("data-parent", "#" + id);
                $(arr[i]).attr("href", "#" + id + "collapse" + i);
            }
            arr = element.find(".accordion-body");
            $(arr[0]).addClass("in"); // expand first pane
            for (var i = 0; i < arr.length; i++) {
                $(arr[i]).attr("id", id + "collapse" + i);
            }
        },
        controller: function () {}
    };
}).
directive('btstPane', function () {
    return {
        require: "^btstAccordion",
        restrict: "E",
        transclude: true,
        replace: true,
        scope: {
            title: "@",
            category: "=",
            order: "="
        },
        template:
            "<div class='accordion-group' >" +
            "  <div class='accordion-heading'>" +
            "    <a class='accordion-toggle' data-toggle='collapse'> {{category.name}} - </a>" +

            "  </div>" +
            "<div class='accordion-body collapse'>" +
            "  <div class='accordion-inner' ng-transclude></div>" +
            "  </div>" +
            "</div>",
        link: function (scope, element, attrs) {
            scope.$watch("title", function () {
                // NOTE: this requires jQuery (jQLite won't do html)
                var hdr = element.find(".accordion-toggle");
                hdr.html(scope.title);
            });
        }
    };
})

and also you can see the accordion example from this js

https://github.com/angular-ui/bootstrap/blob/master/src/accordion/accordion.js

Upvotes: 1

Related Questions