In my Angular app, i have a directive "editable". It written on Angular version 1.2.0-rc.2 and worked well, but when I upgraded framework to version 1.2.13 - directive broke. I checked capability with other versions, and was confused, because directive works only with three versions: 1.2.0rc1, 1.2.0-rc.2 and 1.2.0-rc.3
In new versions this directive works only with two ugly edits:
1. directive's property "terminal" set to "true"
2. compile element in "link" function
Directive have simple logic:
- show previously savedValue
- click on button "EDIT" -> show input for new value
- click on button "OK" to save value - > show new savedValue
Here is the code:
- this version works: http://plnkr.co/edit/VHZVzk?p=preview
- this version broken: http://plnkr.co/edit/NffdDj?p=preview
- this version works with new insertions: http://plnkr.co/edit/7msiY0?p=preview
So, i have a questions:
- Why it's all happens?
- What differences between 1.2.0-rc* versions and other, that brake down directive.
- Is there a way, better than compile directive and adding TERMINAL property to repair directive, because many other directives broken too?
First understanding
They actually changed something in the way the contents are compiled against a determined scope in case of an isolated scope.
Breaking Changes from version 1.2.0
Please see their breaking changes brought with version 1.2.0 :
- $compile:
- due to d0efd5ee, Child elements that are defined either in the application template or in some other directives template do not get the isolate scope. In theory, nobody should rely on this behavior, as it is very rare - in most cases the isolate directive has a template.
- due to 909cabd3, Directives without isolate scope do not get the isolate scope from an isolate directive on the same element. If your code depends on this behavior (non-isolate directive needs to access state from within the isolate scope), change the isolate directive to use scope locals to pass these explicitly.
In your specific case, your edit button cannot access the properties and methods you implemented on the isolated scope. You were able to do that temporarily in those "rc" versions.
Fast solution
Don't use isolated scope for your directive.
Deeper solution
You are actually doing something quite weird. You create an isolated scope to get ngModel
binded to the scope used by your directive.
But, working with the ngModel
directive doesn't work that way. You have to require the ngModelController
instance added by the ngModel
directive, using a directive property called require
, that you will fill with the name of the directive your are requiring the controller of, that is to say "ngModel".
Then the forth argument of your link
function will refer to the ngModelController
instance which is quite well documented on the Angular documentation.
So ! :
- don't use isolated scope when you don't need it
- remember isolated scope is not directly accessible on the element itself anymore, except using the
$$childHead
property of course ... but you should not do that !