I'm sure this is an oversimplification, but surely there have to be less implementor-hostile ways to write these features. For example, even after reading the article I still have no idea what setting this on an attribute does:
Bottom line, things could be better.
Bad from an API design point of view and bad that the tutorial felt it didn't need some explination.
FYI some of your examples are returning 404's
This can be done by calling `$scope.$watch(attrs.myBinding)` directly with expression values passed in through element attributes. If necessary `scope: true` can be used create a child scope that inherits from the current scope. This is a good idea if your directive uses it's own controller. However this isn't necessary for most simple directives.
An isolated scope does exactly that, creates a scope for the directive completely isolated from the prototype chain of the containing scope (and thus the application's scope). This is used for complex directives like ng-repeat that need to create and expose their own scopes with the templates that you put inside the repeat blocks.
I know I initially fell into the trap of using isolate scopes to solve this problem. After looking through Angular's own directives for examples I learned other approaches.
I'm not sure exactly what the considered best practices are here (because there is almost no detail on issues like this in the documentation) but at least basing it off how the Angular core team builds their own directives I would suggest avoiding isolate scopes unless scope isolation is specifically necessary.
I'd be interested to hear if someone who knows for sure could chime in as to what the best practice is and why. I can update the article to match.
In that vein, I think you're right that an isolate scope is generally a better default because it makes it clear that the directive expects no dependencies on the inherited scope, and it prevents the directive from overwriting any scope properties set by an ancestor.
I think using an inherited scope makes sense if you're building very app-specific directives that are tightly-coupled to their ancestor.
I used isolate scopes in the article because I thought they were easier to understand, but I'm thinking of updating it.
However, this can really bite you in the butt. If you're doing something like
"The advantage of transclusion is that the linking function receives a transclusion function which is pre-bound to the correct scope. In a typical setup the widget creates an isolate scope, but the transclusion is a sibling (rather than a child) of the isolate scope. This makes it possible for the widget to have private state, and the transclusion to be bound to the parent (pre-isolate) scope."
But I still have a ton to learn, so I'm not sure that's the best approach.
- think very hard about whether you want to use isolated scopes or not, because their presence affects the semantics of scope inheritance, and changing that decision after the fact can cause hard-to-debug issues in completely unrelated parts of your app. This is especially true if you're using transclusions
- exposing events is tricky if you're exposing model values because in those cases you need to call $digest before calling $apply. Another catch is that attaching the event trigger to a DOM event handler will often cause it to fire on programmatic model changes, which may or may not be what you want (it usually isn't desirable to fire a change event when set the initial value of a field from the controller, e.g. to populate an edit page, in an app that does save-on-blur)
1. if you were going to actually do something like the 'scroll' example, make sure to debounce the scroll handler. it's a good practice for any 'scroll' or 'resize' event handler, but especially when you have to dirty check every time, it could get slow: for example, using http://underscorejs.org/#debounce
scope.bulb = controller.getState();
Note: from this example: http://jsfiddle.net/codef0rmer/2ZrX3/