Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix (forms): clear selected options when model is not an array #12519

Merged
merged 1 commit into from Dec 14, 2016

Conversation

gary-b
Copy link
Contributor

@gary-b gary-b commented Oct 25, 2016

Please check if the PR fulfills these requirements

What kind of change does this PR introduce? (check one with "x")

[x] Bugfix
[ ] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Other... Please describe:

What is the current behavior? (You can also link to an open issue here)

  1. For a select[multiple] with NgModel, the expected model type is an Array. Currently if you set it to a different type of object (ignoring null/undefined for the moment), you get an error. NgModel does not throw such an error when you use an invalid model value with other input controls, eg input[type=number].
    The repro in Issue SelectMultipleControlValueAccessor is a string and fails with values.map does not exist #11926 includes the use of ngModel on a select element, where ngModel is not explicitly bound. This result in an initial model value for the select of an empty string. (I'm going to raise a separate issue about this ngModel behavior, which I suspect is related to one time string initialization.)
  2. When you set the model value to null or undefined, the currently selected option elements stay selected. NgModel used with other input controls clears the selection when these values are passed in.

What is the new behavior?

  1. If a select[multiple] is bound to an invalid value, the currently selected option elements are cleared and no error is raised.
  2. If you set the model to null or undefined, the currently selected option elements are cleared.

Does this PR introduce a breaking change? (check one with "x")

[ ] Yes
[x] No - (Well, changes what happens when the model is set to null / undefined - but I doubt anyone desires the old behavior.)

@gary-b
Copy link
Contributor Author

gary-b commented Oct 25, 2016

I fixed a lint error in my code. 2 of the travis-ci build steps are still failing though:
Fail 3 looks like infrastructure problems.
Fail 4 relates to a failing test in a completely different area.

this._optionMap.forEach((opt, o) => { opt._setSelected(ids.indexOf(o.toString()) > -1); });
let optionSelectedStateSetter: (opt: NgSelectMultipleOption, o: any) => void;
if (Array.isArray(value)) {
let values: Array<any> = <Array<any>>value;
Copy link
Contributor

Choose a reason for hiding this comment

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

const values: any[] = <any[]>values;

but using value directly should also work because of Array.isArray(value)

@@ -701,6 +701,66 @@ export function main() {
}));
});

describe('select multiple controls', () => {
var fixture: ComponentFixture<NgModelSelectMultipleForm>;
Copy link
Contributor

Choose a reason for hiding this comment

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

var -> let (or const where applicable)

@vicb vicb added the action: review The PR is still awaiting reviews from at least one requested reviewer label Oct 26, 2016
Copy link
Contributor

@kara kara left a comment

Choose a reason for hiding this comment

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

Minor comments, but looks good

`
})
class NgModelSelectMultipleForm {
@Input() selectedCities: any[];
Copy link
Contributor

Choose a reason for hiding this comment

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

The @input decorator here isn't necessary - can you remove?

comp.cities = [{'name': 'SF'}, {'name': 'NYC'}, {'name': 'Buffalo'}];
});

const setSelectedCitiesDetectChangesAndTick = (selectedCities: any): void => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you rename to setSelectedCities? The name is a bit of a handful to read.

const assertOptionElementSelectedState = (selectedStates: boolean[]): void => {
const options = fixture.debugElement.queryAll(By.css('option'));
if (options.length !== selectedStates.length) {
throw `there are ${options.length} option elements but ${selectedStates.length}` +
Copy link
Contributor

@kara kara Nov 10, 2016

Choose a reason for hiding this comment

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

I'd wrap the whole error message in backticks so you don't have to concat the string. Or if you're trying to avoid the line break, I'd just make it shorter.

@kara kara added action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews and removed action: review The PR is still awaiting reviews from at least one requested reviewer labels Nov 10, 2016
When an invalid model value (eg empty string) was preset ngModel on
select[multiple] would throw an error, which is inconsistent with how it
works on other user input elements. Setting the model value to null or
undefined would also have no effect on what was already selected in the
UI. Fix this by clearing selected options when model set to null,
undefined or a type other than Array.

Closes angular#11926
@gary-b
Copy link
Contributor Author

gary-b commented Dec 12, 2016

PR updated.

Copy link
Contributor

@kara kara left a comment

Choose a reason for hiding this comment

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

LGTM

@kara kara added action: merge The PR is ready for merge by the caretaker pr_state: LGTM and removed action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews labels Dec 14, 2016
@vicb vicb merged commit 7b0a867 into angular:master Dec 14, 2016
vicb pushed a commit that referenced this pull request Dec 15, 2016
When an invalid model value (eg empty string) was preset ngModel on
select[multiple] would throw an error, which is inconsistent with how it
works on other user input elements. Setting the model value to null or
undefined would also have no effect on what was already selected in the
UI. Fix this by clearing selected options when model set to null,
undefined or a type other than Array.

Closes #11926
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 10, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker area: forms cla: yes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants