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

fix(select): make ngOptions support selectAs and trackBy together #9419

Closed
wants to merge 3 commits into from

Conversation

jeffbcross
Copy link
Contributor

This commit implements a function, "getSelected()", that takes the
selectAs expression into account when determining if a particular
option is selected or not. Previously, the selectAs part of the
ngOptions comprehension expression was being ignored.

Fixes #6564

@jeffbcross
Copy link
Contributor Author

@IgorMinar mind taking a look?

* <div class="alert alert-info">
* **Note:** The values that are stored on the underlying option elements (i.e. `option.value`) are set
* to either the indeces of the array (for array data sources) or the property names of
* the object (for object data sources).
Copy link
Contributor

Choose a reason for hiding this comment

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

this is an implementation detail and not a public api contract. if we want to have this in the docs then we should just reword it to state the public api contract first and then mention the implementation detail as an explanation of why option.value and select.value contain weird stuff.

@IgorMinar
Copy link
Contributor

otherwise lgtm

@jeffbcross
Copy link
Contributor Author

There are some issues when changing from the view that need some work. See this plnkr

Select "one" and nothing happens. Select "two" and "one" becomes selected (and the model is 1).

If I would decrement both ids, this would work as expected. It seems the logic that assigns the viewValue before rendering needs to also be updated with this change.

@caitp
Copy link
Contributor

caitp commented Oct 7, 2014

#9467 may be related to this in some way, I haven't looked into it much --- in any case both sort of revolve around tracking expressions (the bug it tries to fix is not the same issue, but should be related)

@jeffbcross
Copy link
Contributor Author

Fixed some more issues, and improved viewValue computation. I'm going to do some manual testing and add some more unit tests.

@jeffbcross
Copy link
Contributor Author

I added more tests and fixed some more cases. @tbosch mind taking a look?

});

expect(element.val()).toEqual('2');
expect(element.val()).toEqual('1');
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't val be 2 since values[1] is {id: 2, name: 'second'} and we track by id?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The element value is always either the index (for arrays) or key (for objects), even though the model can be different.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This allows models to be more complex objects. I was confused by this behavior as well, which is why I added a note in the docs about the element value.

});


it('should bind to scope value through selectAs expression while tracking object via track by', function() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

new describe: selectAs with trackBy
Maybe add 2 more tests for object data sources

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@jeffbcross
Copy link
Contributor Author

More todos aside from commit comments:

  • Make sure new tests aren't redundant
  • Add a protractor test or two to simulate E2E experience

This commit implements two functions, "isSelected()" and "getViewValue()"
to properly compute an option's selected state and the model controller's
viewValue respectively. These functions give proper precedence to "track by"
and "select as" parts of the ngOptions comprehension expression, which were
previously inconsistent and incompatible.

Fixes angular#6564
tbosch and others added 2 commits October 8, 2014 11:38
trackBy and selectAs have never worked together, and are fundamentally
incompatible since model changes cannot deterministically be
reflected back to the view. This change throws an error to help
developers better understand this scenario.
* trackBy is always applied to `value`, with purpose to preserve the selection,
(to `item` in this case)
* To calculate whether an item is selected, `ngOptions` does the following:
1. apply `trackBy` to the values in the array, e.g.
Copy link
Contributor

Choose a reason for hiding this comment

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

Replace , e.g. with :

@tbosch
Copy link
Contributor

tbosch commented Oct 8, 2014

Otherwise LGTM.

@tbosch
Copy link
Contributor

tbosch commented Oct 8, 2014

Travis failed because of a jshint error...

   test/ng/directive/selectSpec.js
    779 |        }).toThrowMinErr('ngOptions', 'trkslct', "Comprehension expression cannot contain both selectAs ('item.id') and trackBy ('item.id') expressions.")

@jeffbcross jeffbcross force-pushed the master branch 2 times, most recently from abdaab7 to 30996f8 Compare October 8, 2014 19:47
@jeffbcross
Copy link
Contributor Author

Closed at 30996f8

@jeffbcross jeffbcross closed this Oct 8, 2014
@btford btford removed the In Progress label Oct 8, 2014
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ng-options track by and select as are not compatible
6 participants