0

I have a form where my intent is for required fields to not always be enforced. For example if the user is saving the document as a draft they can enter as little information as they like, if they try and publish the document then they have to enter all the required fields. I'm using a boolean on the controller which changes according to which button has been pressed e.g.

<input type="text" ng-model="field2" ng-required="enforceRequired" />

The problem is that the fields are not re-evaluated when the boolean changes so the form is submitted and then it becomes invalid. Please see this JSFiddle to see what I mean. If you fill in field1 and then click publish it will succeed on the first click and THEN become invalid.

How can I force the validation to run before the form is submitted?

2 Answers2

1

The problem is that you are changing the value of enforceRequired in the middle of the digest loop, so the watchers are not re-rendered before you check the input fields' validity (read about digest here).

If you want to get around it, I suggest one of the following methods:

  1. change the value of enforceRequired before you call saveDraft or publish. see example.

  2. call $scope.$apply() after you change the value of enforceRequired. see another example.

Yaron Schwimmer
  • 5,327
  • 5
  • 36
  • 59
  • $scope.$apply() was the best solution for me. Thanks very much. – user3546309 Jan 14 '15 at 14:56
  • I've actually just noticed that this causes errors in the console (Error: $apply already in progress). Is there any way around this? – user3546309 Jan 14 '15 at 15:21
  • I don't think there is a way around it. you can use [safe apply](http://stackoverflow.com/questions/12729122/prevent-error-digest-already-in-progress-when-calling-scope-apply), but it will cause the whole workaround not to work... That's why I suggested another approach. – Yaron Schwimmer Jan 14 '15 at 15:39
1

Yarons is right, you are changing the value too late, by late I mean after the form validations has been run. What you can do as a workaround is, after changing the required value, let angular do another cycle and then show your alert. This can be done via $timeout service, although I must mention that it is usually not a good practise to change the flow of your digest actions. It gets pretty messy pretty soon.

Change your publish function like this (and don't forget to inject $timeout)

$scope.publish = function () {
    $scope.enforceRequired = true;

    $timeout(function () {
        if ($scope.form.$valid) {
            alert("Published!");
        }
    });
};

Working fiddle: http://jsfiddle.net/bh9q00Le/14/

Umur Kontacı
  • 35,403
  • 8
  • 73
  • 96