0

I would like to highlight a field in red if the user tries to submit the form while the field is empty. So I set a showErrors boolean to true on submit, and conditionally require my field based on this value ng-required='showErrors'.

I define a isValid function which triggers a digest cycle to allow the showErrors value to propagate, but the function is not behaving as I would like. With the field empty, the first time the submit button is clicked isValid returns true and then false on subsequent clicks, but I would like it to always return false if the field is empty.

How can I force my isValid function to wait for the digest cycle to propagate prior to returning validity?

https://plnkr.co/edit/wH6HfawquHJwR69AUPRI

9
  • Not sure if you really need to have a custom function which will call the digest cycle. Angular takes care of running the digest cycle whever a change in model is detected. From the Docs "docs.angularjs.org/api/ng/directive/ngRequired" Commented Jul 10, 2017 at 19:42
  • after setting showErrors=true, my first call to $scope.myform.$valid gives true when my input field is blank (possibly because there is no change to the model?) Commented Jul 10, 2017 at 19:45
  • In that case, you can just initialize the "showErrors" value with true on controller load (you have set to false now) and it will work as expected. Commented Jul 10, 2017 at 20:03
  • but I don't want to show errors on page load, I don't want the empty field to show as red until the submit button is clicked. Commented Jul 10, 2017 at 20:19
  • @ab11 you can change class name in ng-click method then you will be able to control input value after submit to set input red or white Commented Jul 10, 2017 at 20:54

2 Answers 2

0

From personal experience it would be easier to control the hightlight by using css on the form level.

ng-required is reserved for use when we need to set required dynamically, for example user can choose to input phone or email, then required for email input field is only needed when user select email.

<form ng-class='{showErrors: showErrors}'>
  <input required />
</form>

.showErrors .ng-invalid {
  border-color: red;
}
Sign up to request clarification or add additional context in comments.

Comments

0

TlDr; use $timeout(function(){...});

The answer provided by @Icycool does do the trick in this use case. But the reason i came to this post was the reason of the title of the post: "How to wait till the $digest cycle is done?"

I did some searching and found this post on coding-geek explaining the different elements that come to hand in the $digest cycle.

It explains that $timeout can be used to wait a cycle, (or more, if you add the timeout parameter) It also says that you can use $evalAsync but this does not always do the trick for me.

So here is an example where a scope variable is watched and a input element is triggered. It's kind of abstract and psuedo because I do not have a good use case right now.

$scope.$watch('vm.foo', function(newFoo) {
    if (newFoo) {
        $timeout(function() {
            $window.alert('new Foo set!' + newFoo);
        });
    } else {
        $timeout(function() {
            $window.alert('Foo was removed!');
            angular.element('input').focus(); 
        }, 2000); // waits for 2 secs before alert and focus
    }
});

I've found this plunker that uses plain timeout's and $apply, but you can fiddle around with it to make it work for your use case, i found it helping to understand cycles: https://plnkr.co/edit/1nzydOS7AVONmXh9?preview

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.