-
Notifications
You must be signed in to change notification settings - Fork 27.6k
directive compile function scope pollution (ngModel) #4889
Comments
Yes, As we can't distinguish markup that was originally in the html file and markup that was added in the compile function the latter also doesn't get the isolate scope. So yes, using the template is the right and intended way now. Tobias |
Closing this as not a bug... |
Thanks for the comment @tbosch but unfortunately it's still unclear to me - are you saying the 'compile' function is now obsolete in v1.2.0 (which it seems is the case for practical purposes if isolate scope can't be used with compile anymore)? If so, that should be clearly documented in the CHANGELOG, docs, etc. Additionally, it still does not solve the problem at hand and that was referenced by @mhevery in his post http://stackoverflow.com/questions/10629238/angularjs-customizing-the-template-within-a-directive - which is - how do you build a directive's HTML/template dynamically, using the directive attrs? The template function is great for simple/static templating/HTML, but (unless I'm mistaken), doesn't allow any access to directive attrs? We need a way to utilize these attributes when building the HTML, i.e. how would you accomplish this in 1.2.0 WITHOUT using "ng-if", etc. on the scope and cluttering the DOM (this is just a simple example - in reality my directive handles selects, textareas and other inputs that require completely different HTML markup)? http://jsfiddle.net/lukem/S9rV2/ Could you please fork that fiddle and show how to build an input that has a dynamic 'type' in 1.2.0? Thanks! |
Also @tbosch could you please not close the issue until it's actually resolved? If you feel it's not a "bug" and want to label it differently and/or feel I'm posting in the wrong forum for this please feel free to provide suggested alternatives, but this is "breaking behavior" that's not well documented so others are likely experiencing this as well. |
Hi @lukemadera, sorry, I didn't mean to annoy you. Regarding your questions: Then, when using a directive that uses an isolate scope (only then): The idea is that the Here is an updated jsfiddle: http://jsfiddle.net/S9rV2/4/ Keeping the issue open this time :-) Tobias |
Ah, and here is the API doc about it: http://docs.angularjs.org/api/ng.$compile True, the changelog (https://github.com/angular/angular.js/blob/master/CHANGELOG.md) does not include your exact case, but it does include a breaking change for how isolate scopes are assigned to DOM elements. Also in the changelog, under new features for 1.1.4 we mention that templates can now be generated dynamically. Thanks for your response as it shows that this change wasn't clearly pointed out by us! |
@tbosch, Moving to 1.2.0 from 1.2.0-rc.3 broke my directive unit tests. I think for the same reason. Before I could do something like that in a test
to get directive's isolated scope. But now it looks like Currently I am doing it by |
@evgenyneu as of 27e9340 you can use To my knowledge this does not walk up the tree, however, so it needs to be used on the root of the directive. |
@caitp, element.isolateScope() is exactly what I needed! Thanks a lot, friend, you saved my day. |
No worries @tbosch and thanks for the fiddle - switching to the template as a function did the trick, I'm all set now! I do remember reading about the 1.1.4 change to a template function but to be honest directives are still by far the most confusing part of Angular (even though they're the most powerful) so once I had something that worked (with the compile function), I wasn't about to change it without good reason! Though after reading through the new/update docs on directives on angularjs.org I think it's much better - especially the "best practices" green boxes are very helpful. There's so many different ways to build a directive and while I know that leads to a lot of power, it also can create lots of confusion. Making progress! Thanks again. |
Related question - @caitp (and/or @tbosch ) - I tried Does it have to do with the Basically I need a way to determine when a user has selected a file from a file input. Any help would be appreciated! |
@lukemadera for starters, the context for event handlers (using the on{{eventname}} attributes) are actually the global context (which in web apps is generally Anyways, ng-change does not wrap the At any rate, if you do want to handle |
Gotcha, thanks @caitp - I got it working with jqLite .on('change'). Thanks for the help and prompt reply! |
For all other people who are reading this issue: |
@evgenyneu Using T |
@tbosch They have stated that 1.2.0 (and the subsequent true isolation of isolate scope) broke unit tests which looked like element = $compile(markup)(scope)
scope = element.scope() because previously they were able to access the isolate scope like this. I believe |
Ah, ok, it's about unit tests, sorry, didn't get that. |
@tbosch Regarding the usage of In older angular versions, this was easy because the extra directive would get the reference to the widget's isolate scope and could directly call methods on it. Now, with the new version of angular, we somehow need to expose the extra api to be accessible from the outer scope. This can be done via value binding or directly by observing the attributes object on the widget's side. This means however that the widget has to be prepared for this to work and needs to do something more complex than actually needed. The other solution is to request the isolate scope in the "marker" directive to imitate the behaviour of older anguar versions. |
@BendingBender in order for directives to communicate, one should expose its API via a controller, and the other should require it. That's the proper way of doing it. In the same way that you can .directive('enhanceWidget', function () {
return {
scope: {...},
controller: function ($scope, $element, $attr) {
this.someHook = ...
}
};
}) and your "marker" directive can communicate with it by requiring it's controller .directive('marker', function () {
return {
require: 'enhanceWidget',
link: function (scope, el, attr, enhanceWidget) {
enhanceWidget.someHook(...)
}
};
}) Also, in the code above, |
@rodyhaddad thanks for the comment, I agree. |
I have a forminput directive (originally adapted from @mhevery example here: http://stackoverflow.com/questions/10629238/angularjs-customizing-the-template-within-a-directive ) that no longer works in the new Angular 1.2.0. It works in Angular 1.2.0-rc.3.
jsFiddles here:
WORKS: 1.2.0-rc.3 http://jsfiddle.net/lukem/9BpSm/
does NOT work: 1.2.0 http://jsfiddle.net/lukem/S9rV2/
I read the changelog and saw there were numerous (breaking) changes to the compile function but it's not clear to me what is causing this new behavior and if it's intended to be this way (in which case how am I correctly supposed to do it?) or if it's a bug.
It DOES seem to work with template instead of compile so perhaps it's related to d0efd5e ? @vojtajina is there a reason isolate scope doesn't also apply to compile functions as well as the template function?
The text was updated successfully, but these errors were encountered: