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

fix($compile): be more careful about shadowing $attrs values #12151

Closed
wants to merge 1 commit into from

Conversation

caitp
Copy link
Contributor

@caitp caitp commented Jun 17, 2015

Shadows only when attributes are non-optional and not own properties,
only stores the observed '@' values when they are indeed strings.

Partial revert of a6339d3

Closes #12144

@petebacondarwin
Copy link
Contributor

It is also true that this affects the isolated scope as well as the bindToController:

  it('should only observe attributes that are defined', function() {
      module(function($provide) {
        directive('missingInterpolatedAttrDirective', function() {
          return {
            restrict: 'E',
            scope: { prop: '@' },
            bindToController: { prop: '@' },
            controllerAs: 'vm',
            controller: function($scope) {
              this.prop = this.prop || 'init';
              $scope.prop = $scope.prop || 'init';
            },
            template: '<div>{{ prop }} | {{ vm.prop }}</div>'
          };
        });
      })
      inject(function($rootScope, $compile) {
        element = $compile('<missing-interpolated-attr-directive></missing-interpolated-attr-directive>')($rootScope);
        $rootScope.$digest();
        expect(element.text()).toEqual('init | init');
      });
    });

@petebacondarwin
Copy link
Contributor

Apart from adding a check for the isolated scope, this LGTM

@caitp
Copy link
Contributor Author

caitp commented Jun 17, 2015

added

}

attrs.$observe(attrName, function(value) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Slightly unrelated to this fix, but should we be bothering to call $observe at all if the attribute doesn't exist?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might exist later, I think that's the reasoning behind this

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that if you have a one-time binding and the value is sometimes expected to be not defined then in many cases you basically have to write attribute="::null". This is very unintuitive and it's very easy to create lots of excessive bindings.

Changing that might be a breaking change, though. But it might be worth doing in 1.5?

Shadows only when attributes are non-optional and not own properties,
only stores the observed '@' values when they are indeed strings.

Partial revert of 6339d30d1379689da5eec9647a953f64821f8b0
@gkalpak
Copy link
Member

gkalpak commented Jun 17, 2015

Note that it also happens with new scope and bindToController (e.g. scope: true, bindToController: {prop: '@'}), so it might be a good idea to add a test for that too.

Also note that the case where something is returned from the controller behaves differently, so (if one wanted to be thorough) both cases should be tested. In any case, if I had to choose, I would prefer to have the version where something is returned from the controller, as it is the most fragile one:

controller: function () {
  ...
  return <something>;

@caitp
Copy link
Contributor Author

caitp commented Jun 17, 2015

Honestly trying every permutation of it is going to add like 300 lines, it's the same paths being taken for each one. Let's keep it for now and add more in a follow-up

@petebacondarwin
Copy link
Contributor

I'm going to merge this. Thanks @caitp.
@gkalpak - if you get a moment could you knock up some more tests that would match the cases you mention above? Thanks

@gkalpak
Copy link
Member

gkalpak commented Jun 17, 2015

I don't feel strongly about it, so it lgtm.
(But I think the paths are different; i.e. thete are extra paths that call the function again in some cases.)

@caitp
Copy link
Contributor Author

caitp commented Jun 17, 2015

Yeah lets do it in a followup. in a meeting atm, if someone else wants to land this

@caitp caitp closed this in 8a1eb16 Jun 17, 2015
gkalpak added a commit to gkalpak/angular.js that referenced this pull request Jun 23, 2015
netman92 pushed a commit to netman92/angular.js that referenced this pull request Aug 8, 2015
…esent

Shadows only when attributes are non-optional and not own properties,
only stores the observed '@' values when they are indeed strings.

Partial revert of 6339d30d1379689da5eec9647a953f64821f8b0

Closes angular#12151
Closes angular#12144
netman92 pushed a commit to netman92/angular.js that referenced this pull request Aug 8, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants