AngularJS: run after digest loop with $timeout (Safari vs chrome)

AngularJS: run after digest loop with $timeout (Safari vs chrome)



I've written some custom validation code when filling out a form, but need to set the $timeout to > 100 ms in order to get it to work, and I'm curious to find out why.


$timeout



The required form elements follow this format. I add the "novalidate" class if the input is wrong: (Observe, there's a ton of these elements in the form)


<div class="dottedWrapper" ng-class="novalidate:(newController.jobDescription.length == 0) && newController.formSubmitted">



When submitting the form, I check if any elements has the "novalidate" class and return.


self.formSubmitted = true;

$timeout(function ()

// Validate!
if (document.getElementsByClassName("novalidate").length > 0)
return;


...

, 100); // MUST SET AT LEAST 100ms for it to work in safari



However, this only works if I set the time to about over 100ms in Safari. In chrome, It's only necessary to set it to 1ms.



Correct me if I'm wrong, but here's my thinking, and bare in mind that I'm a newbie in angular:



I set the "self.formSubmitted = true;" in the beginning. This causes, through the two-way data binding an update on all the divs, since the "formSubmitted" is contained inside the ng-class.


self.formSubmitted = true;



This is done through a digest loop, which means I cannot run the "document.getElementsByClassName("novalidate")" directly after since the digest loop most run through once and update everything.


document.getElementsByClassName("novalidate")



So... I use the $timeout, thinking it will let the current digest loop run, and then jump on the next digest loop. At this point, all elements should be updated.


$timeout





do you need to use the dom to store such info? if you could use JS vars, you would not need to delay, which seems a little janky...
– dandavis
Nov 6 '15 at 7:28





I could do this, but there's a ton of elements... With the code I have now, it's just one line to validate.
– BlackMouse
Nov 6 '15 at 7:36





but why you need timeout if you can directly check newController.jobDescription.length == 0 in js?
– Grundy
Nov 6 '15 at 7:39


newController.jobDescription.length == 0





if other programmers see setTimeouts not connected to animation, message timeouts, or game actions, they will make fun of you. figure out something else out, there are many many ways to do this better... as soon as you decide that 100ms is enough, it will start taking 101ms on your bosses computer during a demo, guaranteed.
– dandavis
Nov 6 '15 at 7:41






i don't know the whole story, but it seems to me that one active submit spoils the others. if that's the case, a single busy boolean var/prop that's get and set by all should suffice.
– dandavis
Nov 6 '15 at 7:55





2 Answers
2



Aside from Pixelbits answer (which I totally agree with), you could try replacing $timeout with one of the following;


$evalAsync


$$postDigest



Where the former will trigger a new $digest loop (just like $timeout), and the latter will not.



Even so, I think your best bet would be to harness the built-in input validation directives. And instead of checking for the existence of a novalidate class in the DOM, just check the <form>.$valid property (<form> gets exposed on your $scope, when given a name attribute).


input


novalidate


<form>.$valid


<form>


name



Your view would look something like so;


<form name="myForm">
<input ng-model="formData.jobDescription" ng-minlength="1">
</form>



And then in your controller;


// var form = $scope.myForm;
console.log(form.$valid); // true|false



Now, the above suggestion may not work for your use case - We need to see more of your implementation to be able to assist you to a greater extent.





Great! Thanks a lot
– BlackMouse
Nov 6 '15 at 13:28



You're breaking the MVC pattern. Don't - it's bad practice.



Why don't you just do:


if (self.jobDescription.length == 0 && self.formSubmitted)
return;





I could do this, but there's a ton of elements... With the code I have now, it's just one line to validate.
– BlackMouse
Nov 6 '15 at 7:36





@BlackMouse, so why you just not use built-in validation in angular? And anyway you write this code for tons element, why not just move it all to one place?
– Grundy
Nov 6 '15 at 7:49







By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)