jonsamwell/angular-auto-validate

Reset a form

Closed this issue · 12 comments

Hey Jon, it's me again. :P
I made a tiny directive to reset a form :

function reset () {
    return {
      scope: {
        form: '=reset'
      },
      link: function (scope, element) {
        var initialForm = angular.copy(scope.form);
        element.on('click', function () {
          scope.form = angular.copy(initialForm);
          scope.$apply();
        });
      }
    };

You can use it just like that :

<button type="button" reset="vm.form">Cancel</button>

Where vm.form is an object containing all my ng-model in the form. It's working great but when all the inputs are reinitialized, the auto-validate library triggers and put some inputs with an error state. Is it possible to neutralize this behaviour or integrate this reset feature inside the lib ?

EDIT : I didn't mention it but it requires to clean the styling of the good/bad inputs as well.

This is a good request - I've got this working locally. I'll do my best to push a release to bower tomorrow. Basically the solution is really simple. I've create a directive 'form' that listens to the form's reset event then I'm calling the validation manager resetForm (a new method). This is my preferred way of doing it as you don't need to keep an scope state. It's committed to master but I have written any test for it yet . https://github.com/jonsamwell/angular-auto-validate/blob/master/src/directives/formReset.js

@jgoux This has now been pushed up to v1.0.11 - see the docs for usage. http://jonsamwell.github.io/angular-auto-validate/#your_form

Hello @jonsamwell , thanks for this feature.
I have just one problem. When you load a form with custom default values, the <button type="reset"></button> just clears all the values, it doesn't reset the initial values set for the form. This was the point of my custom directive. Could you add a listener for a custom event so we can trigger your reset function by emiting an event inside a directive ?
Then my directive will be something like :

function reset () {
    return {
      scope: {
        form: '=reset'
      },
      link: function (scope, element) {
        var initialForm = angular.copy(scope.form);
        element.on('click', function () {
          scope.form = angular.copy(initialForm);
          scope.$apply();
          scope.$emit('jcs-autoValidate:reset');
        });
      }
    };

Hey @jgoux - Yeah the form reset event clears the values - I only reset the visual state of the element. You already have a hook to do this (which will just reset the elements visual state not the ng-model values) by calling validationManager.resetForm(el); where the 'el' is the form element you wish to reset. See the formReset directive https://github.com/jonsamwell/angular-auto-validate/blob/master/src/directives/formReset.js#L11

I used the correct method in my directive, but some inputs (actually, all the inputs which aren't empty) continue to be in an error state. I can't find what is wrong with it. ^^'

function reset (validationManager) {
    return {
      scope: {
        formData: '=reset'
      },
      link: function (scope, element) {
        var initialFormData = angular.copy(scope.formData);
        var formElement = element;
        for (var i = 0; i <= 5; i += 1) {
          if (formElement !== undefined && formElement[0].tagName.toLowerCase() === 'form') {
            break;
          } else if (formElement !== undefined) {
            formElement = formElement.parent();
          }
        }

        element.on('click', function () {
          validationManager.resetForm(formElement);
          scope.formData = angular.copy(initialFormData);
          scope.$apply();
          // I also tried to put it here : validationManager.resetForm(formElement);
        });
      }
    };

Basically I replace the current object which hold all my form data with its original values, and then I just want to clear all the visual states with your method.

Could you post up a plunkr and I'll have a quick look - you might need to call validationManager.resetForm(formElement); after the scope.$apply() - maybe in a $timeout which is prefered over the use of scope.$apply as the model is being updated again and validation is probably firing.

function reset ($timeout, validationManager) {
    return {
      scope: {
        formData: '=reset'
      },
      link: function (scope, element) {
        var initialFormData = angular.copy(scope.formData);
        var formElement = element;
        for (var i = 0; i <= 5; i += 1) {
          if (formElement !== undefined && formElement[0].tagName.toLowerCase() === 'form') {
            break;
          } else if (formElement !== undefined) {
            formElement = formElement.parent();
          }
        }

        element.on('click', function () {
          scope.formData = angular.copy(initialFormData);
          $timeout(function () { validationManager.resetForm(formElement); });
        });
      }
    };

Here is the plunker : http://plnkr.co/edit/sP8JkB3Y3jMKhyI4DRAO?p=preview

EDIT : I updated the plunker, it reflects my problem.

Thanks, yes you are using an old version 1.0.8 it is now at 1.0.11 https://raw.githubusercontent.com/jonsamwell/angular-auto-validate/master/dist/jcs-auto-validate.min.js

I've had a really quick play and it looks like the form is getting set to the default state but the model is being update which causes the validation to run again. I'll have another play around tonight.

I updated to the lastest version.
The thing I don't understand is even if the validation is applied again, as I'm calling the resetForm method after it, it should clear the form. For now I'll hide this feature. ^^

This is a pure timing issue - the form is obviously getting cleared before the model is actually updating even though it is called before.

This is fixed in the v1.0.13 release. I ended up having to call the $setPristine on the model control for each element (https://github.com/jonsamwell/angular-auto-validate/blob/master/src/services/validationManager.js#L60). Seems to work fine now :-)

I really begin to think that you are a machine Jon. Thanks again. ;)