Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

$compile: error while removing tAttr with interpolated expression during directive compile #9236

Closed
g00fy- opened this issue Sep 24, 2014 · 10 comments

Comments

@g00fy-
Copy link

g00fy- commented Sep 24, 2014

According to : these lines calling

tAttr.$set('foo', null);
// or 
tAttr.$set('foo', undefined);

Should remove the Attribute from the element.

This does not work with tAttrs containing interpolated expressions <h1 foo="{{bar}}">Hello</h1>.

How to replicate

See example

code:

  .directive('foo', function(){
    return {
      restrict:'A',
      compile: function(tElement,tAttr){
        tAttr.$set('foo',null); // same result with undefined
      }
    }
  })
<h1 foo="{{ bar }}">Hello World</h1>
TypeError: Cannot read property 'length' of null
    at $interpolate (https://code.angularjs.org/snapshot/angular.js:9330:28)
    at attrInterpolatePreLinkFn (https://code.angularjs.org/snapshot/angular.js:7424:33)
    at invokeLinkFn (https://code.angularjs.org/snapshot/angular.js:7549:9)
    at nodeLinkFn (https://code.angularjs.org/snapshot/angular.js:7048:11)
    at compositeLinkFn (https://code.angularjs.org/snapshot/angular.js:6441:13)
    at compositeLinkFn (https://code.angularjs.org/snapshot/angular.js:6444:13)
    at publicLinkFn (https://code.angularjs.org/snapshot/angular.js:6320:30)
    at https://code.angularjs.org/snapshot/angular.js:1485:27
    at Scope.$get.Scope.$eval (https://code.angularjs.org/snapshot/angular.js:13436:28)
    at Scope.$get.Scope.$apply (https://code.angularjs.org/snapshot/angular.js:13534:23) <h1> 

currently quick fix for apps (imho similar fix can be applied to angular Attributes + check if they contain interpolated expression):

        tAttr.$set('foo',''); // nullify (remove interpolation expression , probably trigger prematurely  registered observers / interpolation?)
        tElement[0].removeAttribute('foo');

This issue questions timing of registering interpolations (before or after compilation ?) - this should be mentioned in the docs.

@caitp
Copy link
Contributor

caitp commented Sep 24, 2014

you'd have to remove the attributes observer (and ideally the watcher associated with it). There is no public API to do this yet really, although it doesn't seem unreasonable

@lgalfaso
Copy link
Contributor

@caitp I think that the issue is talking about removing the interpolation before AttrInterpolateDirective reaches link. I think it should be an easy fix, let me look into this

lgalfaso added a commit to lgalfaso/angular.js that referenced this issue Sep 24, 2014
Handle the removal of an interpolated attribute before the
attrubute interpolating directive is linked

Closes angular#9236
lgalfaso added a commit to lgalfaso/angular.js that referenced this issue Sep 24, 2014
Handle the removal of an interpolated attribute before the
attribute interpolating directive is linked

Closes angular#9236
@lgalfaso lgalfaso removed their assignment Sep 24, 2014
@g00fy-
Copy link
Author

g00fy- commented Sep 24, 2014

@lgalfaso this fix may also resolve issue #9198 in a cleaner way removing need for ngCanary.

@lgalfaso
Copy link
Contributor

@g00fy- not sure how both issues are related, one is about handling the removal of an attribute that is going to be interpolated and the other is about removing an element during compile

@caitp
Copy link
Contributor

caitp commented Sep 24, 2014

dealing with the compile case doesnt really need any special treatment, however after link it does

@lgalfaso
Copy link
Contributor

@caitp there are two cases here

@caitp
Copy link
Contributor

caitp commented Sep 24, 2014

Compile doesn't really need any special treatment lgalfaso, you can just delete attrs.$attrs[name]; delete attrs[name]; --- it's pretty trivial stuff

@caitp
Copy link
Contributor

caitp commented Sep 24, 2014

It would be even more trivial if we added a method like $remove() or something, which would delete the real attribute name, the normalized name, and remove any observers / watchers (if $scope is provided) --- that would solve both cases

@lgalfaso
Copy link
Contributor

@caitp I agree that a richer API for Attribute can solve this. Now, I still think we have two cases. For the former, we already have code and tests that are able to handle the case of the attribute being changed between compile and link, and we do not handle the removal of the attribute. About the later case, I do not know if we want to add support for it

@caitp
Copy link
Contributor

caitp commented Sep 24, 2014

the only reason it's still a problem is because they're still iterating over that key --- but if you delete the key rather than setting it to null, the problem stops

bullgare pushed a commit to bullgare/angular.js that referenced this issue Oct 9, 2014
Handle the removal of an interpolated attribute before the
attribute interpolating directive is linked

Closes angular#9236
Closes angular#9240
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants