0

I've searched and tried many things for this, and I think maybe Im just doing it wrong.

I have a single page app that has very similar DOM pieces, differentiated only by the data that is fed in to them from a service. Each DOM piece has a different web service.

My HTML looks something like this

<div section="foo">
    <ul>
        <li ng-repeat="item in collection">{{item.name}}</li>
    </ul>
</div>
<div section="bar">
    <ul>
        <li ng-repeat="item in collection">{{item.cost}}</li>
    </ul>
</div>

The differences are more dramatic in my real example so no I cant just change 'cost' to 'name' and have them be identical.

I have a directive that looks like this:

angular.module("App").directive("section", ["BaseProvider", function(provider) {
    return {
        restrict: "A",
        scope: {},
        link: function($scope, element, attrs) {
            provider.query(attrs.section).success(function(response) {
                $scope.collection = response; // ** pay attention to this line **
            });
        }
    };
}]);

so, it calls the query method of BaseProvider, passing in the section attribute of the DOM element. so, "foo" or "bar" in my examples.

BaseProvider looks something like this:

angular.module("App").factory("BaseProvider", ["$http", function($http) {
    var urls = {
        foo: "/something/foo.v1.json",
        bar: "/something/bar.v2.json"
    };

    return {
        query: function(base) {
            return $http.get(urls[base]);
        }
    };
}]);

this all works. what i'm running in to is the typical directive problem - it does not make it in time for the $apply/$digest cycle and so when i do $scope.collection = response inside of the directive, the collection IS set, but the DOM does not update.

so, I try to run $scope.$apply(), but then I run in to the $digest in progress error.

http://docs.angularjs.org/error/$rootScope:inprog?p0=$digest

i've tried the suggestions, but am still having a problem. i'm out of ideas at this point and maybe my hope to have a reusable directive and a single provider driving the whole thing isn't the way to go.

i had this all working using a FooCtrl and a BarCtrl but I was repeating myself so many times it just felt wrong.

oooyaya
  • 1,773
  • 1
  • 15
  • 39
  • Can you clarify what you're really trying to accomplish here? You want to share the dom but bind to different data and different properties of the data? Are there two sections or more than two? – paulmelnikow Jan 03 '14 at 06:36
  • Also, I could be wrong but I don't think a directive is the best way to accomplish this. Nested controllers probably would be a better choice. – paulmelnikow Jan 03 '14 at 06:36
  • Nested controllers may be better. I'm looking for a way to avoid the inprogress problem related to having multiple directives each performing a $http GET and $scope.$apply to update the DOM. – oooyaya Jan 03 '14 at 13:38
  • more than two sections. – oooyaya Jan 03 '14 at 13:41

1 Answers1

6

If you are using angular 1.2.x or above your directive will not work because it is using an isolate scope. Isolate scope means that any variable you assign to the scope can only be used from within the scope's internal template (meaning the template defined in the directive using the template: attribute.

Since your directive does not have a template, you should not use isolate scope. Instead of doing:

scope: {}

You should do:

scope: true

This will make the directive create a scope but not isolate it. This will make your directive's scope available to the outer template (i.e. your ng-repeat).

Keep this in mind, if you don't have a template defined in your directive you should hardly ever use an isolate scope.

Daniel Tabuenca
  • 13,147
  • 3
  • 35
  • 38
  • that's good to know. will this address the inprogress problem related to multiple directives performing an $http GET and trying to update the dom with $scope.$apply? if i understand you right, doing scope: true will push it to a sandbox kind of scope like a controller uses, which will address digest running in to itselfecause i won't need to do scope.apply manually - it'll update the scope teh way it's intended to and everything just falls back in to place. – oooyaya Jan 03 '14 at 13:40
  • this absolutely fixed it. i hate being so close and just not seeing it. thanks a ton. – oooyaya Jan 03 '14 at 13:49
  • You should not use $scope.$apply() on an $htpp.GET. $http service is an angular service and as such is already aware that it should execute a digest cycle. It is rare to need to use $apply() unless you are binding to browser dom events, in which case you need to wrap your code in an $apply(). – Daniel Tabuenca Jan 03 '14 at 16:23