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

refactor(ngModelController,formController): #8941

Closed
wants to merge 1 commit into from

Conversation

tbosch
Copy link
Contributor

@tbosch tbosch commented Sep 5, 2014

refactor(ngModelController,formController): centralize and simplify l…
…ogic

The previous logic for async validation in
ngModelController and formController was not maintainable:

  • control logic is in multiple parts, e.g. ctrl.$setValidity
    waits for end of promises and continuous the control flow
    for async validation
  • logic for updating the flags ctrl.$error, ctrl.$pending, ctrl.$valid
    is super complicated, especially in formController

This refactoring makes the following changes:

  • simplify async validation: centralize control logic
    into one method in ngModelController:
    • remove counters invalidCount and pendingCount
    • use a flag currentValidationRunId to separate
      async validator runs from each other
    • use $q.all to determine when all async validators are done
  • centralize way how ctrl.$modelValue and ctrl.$invalidModelValue
    is updated
  • simplify ngModelController/formCtrl.$setValidity and merge
    $$setPending/$$clearControlValidity/$$clearValidity/$$clearPending
    into one method, that is used by ngModelController AND
    formController
    • remove diff calculation, always calculate the correct state anew,
      only cache the css classes that have been set to not
      trigger too many css animations.
    • remove fields from ctrl.$error that are valid and add ctrl.$success:
      allows to correctly separate states for valid, invalid, skipped and pending,
      especially transitively across parent forms.
  • fix bug in ngModelController:
    • only read out input.validity.badInput, but not
      input.validity.typeMismatch,
      to determine parser error: We still want our email
      validator to run event when the model is validated.
  • fix bugs in tests that were found as the logic is now consistent between
    ngModelController and formController

ctrl.$valid = true;
ctrl.$invalid = false;
// TODO: Add new values 'pending' and 'skipped' to docs
// TODO: make this an internal method, i.e. rename to $$setValidity
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd be careful with making $setValidity private. There are many custom validation implementations that rely on this. With $validators, many have become obsolete, but there is at least one (that I can can think of now) that's not so easily emulated: when you $http the whole form to the server for validation, and then use $setValidity to apply the results (legacy apps). I don't think you can do that with $validators.

@Narretz
Copy link
Contributor

Narretz commented Sep 5, 2014

Hey @tbosch I think it's a great idea to clean up the code. IIRC @caitp, you were also a big fan of refactoring ngmodel et. al., so maybe you could have a look too?

@@ -75,12 +74,38 @@ function FormController(element, attrs, $scope, $animate) {
toggleValidCss(true);

// convenience method for easy toggling of classes
function toggleClass(className, setUnset) {
Copy link
Contributor

Choose a reason for hiding this comment

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

what's the meaning of setUnset variable? it's a weird name

Copy link
Contributor

Choose a reason for hiding this comment

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

I actually don't follow the logic of the conditions in the following code. if it's supposed to really toggle the classes then I'd expect the conditions to 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.

Renamed the method to cachedToggleClass. It sets/removes the css class based on the given argument. The name is the same as the one in jQuery, although this method does not support to be called with no argument, see http://api.jquery.com/toggleclass/#toggleClass-className-switch
I don't know a better name for this :-(

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Renamed to parameter to switchValue, just like in the jQuery method...

Copy link
Contributor

Choose a reason for hiding this comment

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

ah. ok. now it makes sense. thanks

@IgorMinar
Copy link
Contributor

overall I like this change. it needs a bit more cleanup though.

@tbosch tbosch force-pushed the asyncvalidation branch 2 times, most recently from 3dc38b7 to cdbab90 Compare September 5, 2014 22:48
@tbosch
Copy link
Contributor Author

tbosch commented Sep 5, 2014

Ok, just did. All tests are passing again, and I updated the commit message.
From my standpoint this is merge able!
Could you do a final pass and LGTM this?

@Narretz
Copy link
Contributor

Narretz commented Sep 5, 2014

Wait a minute ... I assume this also addresses #8861 and #8892?

@tbosch tbosch changed the title WIP: refactor(ngModelController,formController): refactor(ngModelController,formController): Sep 5, 2014
@tbosch tbosch added this to the 1.3.0-rc.1 milestone Sep 5, 2014
@tbosch
Copy link
Contributor Author

tbosch commented Sep 5, 2014

Ok, also rebased on top of master...

@tbosch
Copy link
Contributor Author

tbosch commented Sep 5, 2014

@Narretz it could, although I have not explicitly checked. When I work on those other PRs, I will add their tests and see what happens.

@shahata
Copy link
Contributor

shahata commented Sep 5, 2014

As far as I can see this PR fixes the issue addressed by those PR's

@IgorMinar
Copy link
Contributor

👍

@tbosch tbosch force-pushed the asyncvalidation branch 2 times, most recently from 4a8e051 to 24e8115 Compare September 8, 2014 18:45
…ogic

The previous logic for async validation in
`ngModelController` and `formController` was not maintainable:
- control logic is in multiple parts, e.g. `ctrl.$setValidity`
  waits for end of promises and continuous the control flow
  for async validation
- logic for updating the flags `ctrl.$error`, `ctrl.$pending`, `ctrl.$valid`
  is super complicated, especially in `formController`

This refactoring makes the following changes:
- simplify async validation: centralize control logic
  into one method in `ngModelController`:
  * remove counters `invalidCount` and `pendingCount`
  * use a flag `currentValidationRunId` to separate
    async validator runs from each other
  * use `$q.all` to determine when all async validators are done
- centralize way how `ctrl.$modelValue` and `ctrl.$invalidModelValue`
  is updated
- simplify `ngModelController/formCtrl.$setValidity` and merge
  `$$setPending/$$clearControlValidity/$$clearValidity/$$clearPending`
  into one method, that is used by `ngModelController` AND
  `formController`
  * remove diff calculation, always calculate the correct state anew,
    only cache the css classes that have been set to not
    trigger too many css animations.
  * remove fields from `ctrl.$error` that are valid and add private `ctrl.$$success`:
    allows to correctly separate states for valid, invalid, skipped and pending,
    especially transitively across parent forms.
- fix bug in `ngModelController`:
  * only read out `input.validity.badInput`, but not
    `input.validity.typeMismatch`,
    to determine parser error: We still want our `email`
    validator to run event when the model is validated.
- fix bugs in tests that were found as the logic is now consistent between
  `ngModelController` and `formController`

BREAKING CHANGE:
- `ctrl.$error` does no more contain entries for validators that were
  successful. 
- `ctrl.$setValidity` now differentiates between `true`, `false`,
  `undefined` and `null`, instead of previously only truthy vs falsy.
@tbosch tbosch closed this Sep 8, 2014
@tbosch tbosch deleted the asyncvalidation branch September 8, 2014 22:10
tbosch added a commit that referenced this pull request Sep 8, 2014
…ogic

The previous logic for async validation in
`ngModelController` and `formController` was not maintainable:
- control logic is in multiple parts, e.g. `ctrl.$setValidity`
  waits for end of promises and continuous the control flow
  for async validation
- logic for updating the flags `ctrl.$error`, `ctrl.$pending`, `ctrl.$valid`
  is super complicated, especially in `formController`

This refactoring makes the following changes:
- simplify async validation: centralize control logic
  into one method in `ngModelController`:
  * remove counters `invalidCount` and `pendingCount`
  * use a flag `currentValidationRunId` to separate
    async validator runs from each other
  * use `$q.all` to determine when all async validators are done
- centralize way how `ctrl.$modelValue` and `ctrl.$invalidModelValue`
  is updated
- simplify `ngModelController/formCtrl.$setValidity` and merge
  `$$setPending/$$clearControlValidity/$$clearValidity/$$clearPending`
  into one method, that is used by `ngModelController` AND
  `formController`
  * remove diff calculation, always calculate the correct state anew,
    only cache the css classes that have been set to not
    trigger too many css animations.
  * remove fields from `ctrl.$error` that are valid and add private `ctrl.$$success`:
    allows to correctly separate states for valid, invalid, skipped and pending,
    especially transitively across parent forms.
- fix bug in `ngModelController`:
  * only read out `input.validity.badInput`, but not
    `input.validity.typeMismatch`,
    to determine parser error: We still want our `email`
    validator to run event when the model is validated.
- fix bugs in tests that were found as the logic is now consistent between
  `ngModelController` and `formController`

BREAKING CHANGE:
- `ctrl.$error` does no more contain entries for validators that were
  successful.
- `ctrl.$setValidity` now differentiates between `true`, `false`,
  `undefined` and `null`, instead of previously only truthy vs falsy.

Closes #8941
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.

6 participants