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

fix(select): revert commit to fix skipping over blank disabled options #8221

Closed
wants to merge 6 commits into from

Conversation

ealtenho
Copy link
Contributor

An earlier commit caused an error where the first option of a select would be skipped
over if it had a blank value. This fix adds a test case to identify this case and shows
that reverting the earlier commit causes the behavior to change.

Relates to #7715

@mary-poppins
Copy link

Thanks for the PR! Please check the items below to help us merge this faster. See the contributing docs for more information.

  • Uses the issue template (#8221)

If you need to make changes to your pull request, you can update the commit with git commit --amend.
Then, update the pull request with git push -f.

Thanks again for your help!

@caitp
Copy link
Contributor

caitp commented Jul 16, 2014

Please use git revert <SHA> and update the commit message to the form revert: fix(select): avoid checking option element selected properties in render (just to be consistent with the style we're using!) You can also change the commit message to include notes about the reason for reverting, that would be helpful.

I'm all for reverting it, so LGTM

@Narretz
Copy link
Contributor

Narretz commented Jul 16, 2014

Using git revert is not only for consistency, it also makes it easy to find the actual reverted commit. However, you need a separate commit for the tests in this case.

@caitp
Copy link
Contributor

caitp commented Jul 16, 2014

yes, I think we want to reverts here (or maybe I'm wrong, it's been months!)

@ealtenho
Copy link
Contributor Author

Thanks @caitp @Narretz, I will move the revert and the test cases into two different commits.

@Narretz
Copy link
Contributor

Narretz commented Jul 16, 2014

The commit in question is dc149de, because it caused a lot of different bugs. The consensus was that the original bug should be fixed in FF, is that right @ealtenho ?

@caitp
Copy link
Contributor

caitp commented Jul 16, 2014

different shas in master and v1.2.x

@ealtenho
Copy link
Contributor Author

Yes @Narretz, I filed a bug with Firefox. @IgorMinar is also looking at how to fix the original issue.

@caitp
Copy link
Contributor

caitp commented Jul 16, 2014

PS @ealtenho do you have a link to the bugzilla bug? I'd like to be CC'd on that

@IgorMinar
Copy link
Contributor

@ealtenho ealtenho added cla: yes and removed cla: no labels Jul 16, 2014
@ealtenho
Copy link
Contributor Author

@caitp @IgorMinar how do these look?

Actually, I hadn't updated the comment for the second commit. I think it now has the right message.

@IgorMinar IgorMinar added this to the 1.3.0-beta.16 milestone Jul 16, 2014
@IgorMinar
Copy link
Contributor

@ealtenho

we don't want to revert this:

-    it('should not update selected property of an option element on digest with no change event',
 -        function() {
 -      createSingleSelect();
 -
 -      scope.$apply(function() {
 -        scope.values = [{name: 'A'}, {name: 'B'}, {name: 'C'}];
 -        scope.selected = scope.values[0];
 -      });
 -
 -      var options = element.find('option');
 -      var optionToSelect = options.eq(1);
 -
 -      expect(optionToSelect.text()).toBe('B');
 -
 -      optionToSelect.prop('selected', true);
 -      scope.$digest();
 -
 -      expect(optionToSelect.prop('selected')).toBe(true);
 -      expect(scope.selected).toBe(scope.values[0]);
 -    });
 -

@IgorMinar
Copy link
Contributor

otherwise it looks good

@caitp
Copy link
Contributor

caitp commented Jul 16, 2014

So I was looking at the spec, and it looks like FF is actually totally compliant with the requirements laid out for it (re: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-button-element.html). This is implementation-defined behaviour, so to get it fixed in gecko we really need to make a case for it --- I think we have a case here, but it could very well be WONTFIX'd.

Some mozillians spoken to seem to agree that it's a bug, while some consider it a feature, and the spec just doesn't care one way or the other.

I guess we'll see how it goes

@ealtenho
Copy link
Contributor Author

@IgorMinar, so it's okay to have a failing test in the PR at this point? I know that the test is still necessary, but I wasn't sure if it should be left if this PR does not contain a fix?

@caitp is there any action I should take then on the bug report? Like elaborating how this behavior affects us?

@caitp
Copy link
Contributor

caitp commented Jul 16, 2014

So, @sideshowbarker seems to agree that it's a weird user experience, and Olli Pettay seems to be at least satisfied that browser interop is an issue which should be addressed.

I've chosen to describe the behaviour as reading a menu in a restaurant and having your credit card charged as soon as you gaze at an item, before actually committing to a decision about your order. Analogies like that might be helpful in explaining why it's a problem, and an explanation as to why we sometimes consider values before the user actually chooses one (eg during digest) would be helpful too.

But frankly, the reproduction is pretty solid and clearly shows the problems with this behaviour, so that should be more than enough.

One thing though, mobile devices (with touch screens) are really a huge priority for pretty much all of the different vendors right now, so it can be hard to explain problems which affect actual pointing devices (this problem won't occur on mobile, since there's no real "hover" scenario on mobile).

@ealtenho
Copy link
Contributor Author

@IgorMinar I changed the revert to preserve the failing test.
I also added tests for regression #7855

@caitp
Copy link
Contributor

caitp commented Jul 17, 2014

so I guess that bug is a duplicate of a bug opened in 2007 (the search terms I went for didn't include "dropdown menu", so I did't see it before)... that somewhat shrinks my hopes that it will be fixed quickly :( That's a shame.

@sideshowbarker
Copy link

so I guess that bug is a duplicate of a bug opened in 2007 (the search terms I went for didn't include "dropdown menu", so I did't see it before)... that somewhat shrinks my hopes that it will be fixed quickly :( That's a shame.

Well that bug is marked as blocking a couple other more recent bugs, so I’d think that increases the chances of a change being made sooner than the 2007 date would suggest. https://bugzilla.mozilla.org/showdependencytree.cgi?id=987143&hide_resolved=1

@jeffbcross
Copy link
Contributor

@ealtenho we should make a separate commit to add the select ngOptions should not update selected property of an option element on digest with no change event test back so that the revert commit is a pure revert. Even so, @IgorMinar must have had something else in mind other than committing a failing test.

@ealtenho
Copy link
Contributor Author

@jeffbcross I had a discussion with @btford and @IgorMinar about this yesterday and my understanding was that I was submitting this PR partially so @IgorMinar could work on addressing the failing test case.

@IgorMinar

we should make a separate commit to add the select ngOptions should not update selected property of an option element on digest with no change event test

should I implement this?

@btford btford modified the milestones: 1.3.0-beta.17, 1.3.0-beta.16 Jul 18, 2014
@IgorMinar IgorMinar self-assigned this Jul 23, 2014
@petebacondarwin
Copy link
Contributor

we should make a separate commit to add the select ngOptions should not update selected property of an option element on digest with no change event test

@ealtenho - I would definitely do this. It is much easier to understand the failing test if it is not hidden inside some partially reverted commit.

@petebacondarwin
Copy link
Contributor

@IgorMinar - I have assigned this to me for tomorrow. If you want it back just say; if I don't make any progress tomorrow then I'll assign it back to you myself :-)

@petebacondarwin
Copy link
Contributor

Please take a look at my fix for this: #8367

Erin Altenhof-Long and others added 6 commits July 28, 2014 09:27
…render

This reverts commit dc149de. That commit fixes a bug caused by
Firefox updating `select.value` on hover. However, it
causes other bugs with select including the issue described in angular#7715. This issue details how
selects with a blank disabled option skip to the second option. We filed a bug
with Firefox for the problematic behavior the reverted commit addresses
https://bugzilla.mozilla.org/show_bug.cgi?id=1039047, and alternate Angular fixes are being
investigated.

Closes angular#7715 angular#7855
…ith no change event

Commit dc149de was reverted to fix regressions angular#7715 and angular#7855.
This commit introduced this test case and a corresponding fix for preventing the update of the
selected property of an option element on a digest with no change event. Although the previous fix
introduced regressions, the test covers a valid issue and should be included.
An earlier commit dc149de caused an error where the first option of
a select would be skipped over if it had a blank disabled value. These tests demonstrate that with
that commit in place, blank disabled options are skipped in a select. When the commit is reverted,
the correct behavior is seen that the blank disabled option is still selected in both selects
marked with required and those that have optional choices.

Relates to angular#7715
A regression angular#7855 was introduced by
angular@dc149de
This test ensures that reverting that commit fixes this regression.
In the regression, changes to a bound model in ng-change were not propagated back to the view.

Test for angular#7855
…digest with no change event

The `render()` method was being invoked on every turn of the digest cycle,
which was inadvertently updating the DOM even when a `change` event had
not been triggered.

This change only calls the `render()` method when `ctrl.$render()` is called,
as part of the NgModelController` lifecycle and when the `modelValue` has
significantly changed.
@petebacondarwin
Copy link
Contributor

@ealtenho - LGTM. Let's get a check from one of the core team.

// TODO(vojta): can't we optimize this ?
scope.$watch(render);
scope.$watch(valuesFn, render, true);
scope.$watch(getSelectedSet, render, true);
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this mean that you can conceivably render() multiple times per digest (not including retrying dirtychecking)?

Copy link
Contributor

Choose a reason for hiding this comment

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

Well previously render() was being called a minimum of 2 times for every digest, whether or not there was a change to any of the model values.
I initially put these into a watchGroup() call but that doesn't have a parameter to watch deeply.

Copy link
Contributor

Choose a reason for hiding this comment

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

but we shouldn't really need deep watching afaik? since we only test if values are the same with identity equality anyhow

Copy link
Contributor

Choose a reason for hiding this comment

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

or is something different now that we do need to do that

Copy link
Contributor

Choose a reason for hiding this comment

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

The deep watches are needed because we need to re-render if the list of options changes (valuesFn).
Also, the selectedSet is recreated every time and so we need to check whether its properties have changed.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not really sold on that approach.

Previously, we were doing this work in the watch expression, and knew specifically which options changed and how.

Now, we're deep-watching with the same watch action twice, without knowing what's changed and what hasn't. For small collections of options it won' t matter, so if we're shipping this, really emphasize that it's not intended for large collections or complex collections of options

@jeffbcross jeffbcross assigned caitp and unassigned petebacondarwin Jul 28, 2014
petebacondarwin added a commit that referenced this pull request Jul 30, 2014
…digest with no change event

The `render()` method was being invoked on every turn of the digest cycle,
which was inadvertently updating the DOM even when a `change` event had
not been triggered.

This change only calls the `render()` method when `ctrl.$render()` is called,
as part of the NgModelController` lifecycle and when the `modelValue` has
significantly changed.

Closes #8221
Closes #7715
@ealtenho ealtenho deleted the blank-select-fix branch August 13, 2014 00:41
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.

9 participants