1

I have been trying to solve this issue since more than 6 hours without any further progress. I'm trying modify the Bootstraps validate script. And I wanted to enclose it inside a function to return a boolean.

Simply I want 1st console.log to function before 2nd console.log so that bsvalidate will return correct value, but its always other way. I cant let the function execution hold until forEach function concludes.

I've tried to create a promise inside the main function without any success. Thanks in advance for all the help.

function bsvalidate() {
    'use strict'
    // Fetch all the forms we want to apply custom Bootstrap validation styles to
    var forms = document.querySelectorAll('.needs-validation')
    // Loop over them and prevent submission
    window.check = true
    Array.prototype.slice.call(forms)
        .forEach(function (form) {
            form.addEventListener('submit', function (event) {
                if (!form.checkValidity()) {
                    event.preventDefault()
                    event.stopPropagation()
                    window.check = false
                    console.log('inside forEach') // 1st console.log
                }
                console.log('check>>', window.check)
                form.classList.add('was-validated')
            }, false)
        })
    console.log('outside forEach') // 2nd console.log
    return window.check
}```
damdafayton
  • 1,600
  • 2
  • 10
  • 19
  • Seems like you only want `outside forEach` to be logged once you submit (after the 1st log occurrs), so why not move that inside your callback to `.addEventListener()`? – Nick Parsons Aug 26 '21 at 09:51
  • Ive updated the post now. I want to return correct window.check value thats why I want function to wait for forEach to conclude. – damdafayton Aug 26 '21 at 09:58
  • can you please show your example using the Promise? You can't return from an async call / change the value within your callback and then return it, you'll need to either use a callback or a Promise, seeing the example of your Promise implementation would be helpful, otherwise, this question is a duplicate of [Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference](https://stackoverflow.com/q/23667086) / [How to return the response from an asynchronous call](https://stackoverflow.com/q/14220321) – Nick Parsons Aug 26 '21 at 10:04
  • I suggest that you go for a callback approach here instead of using a Promise since forms can be submitted multiple times (and promises can only be resolved/rejected once), so you can make `bsvalidate` accepts a function `bsvalidate(cb)`, then call that function inside of your event listener, passing through anything you want to access `cb(window.check)`. To use bsvalidate, you would need to pass through your callback when calling it: `bsvalidate(function(windowCheck) {console.log("complete: ", windowCheck)})` – Nick Parsons Aug 26 '21 at 10:09
  • I've added reject() near 1st console.log and resolve() near 2nd console.log so my Promise trial hasn't changed anything. Do you mean .call function is an async function? If so I start to understand the reason of the problem. – damdafayton Aug 26 '21 at 10:23
  • Thanks for this link: Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference / How to return the response from an asynchronous call. But I'm not trying to put in order different commands. I'm trying to return a boolean from bsvalidate function. And for that to happen I guess I have to make bsvalidate hold until .forEach to conclude. I have tried to make bsvalidate to accept a function like bsvalidate(cb) but it still runs the code after .forEach before .forEach concludes. – damdafayton Aug 26 '21 at 11:11
  • You can't make `bsvalidate` return the boolean you're after. You need to use a callback / promise - the linked questions aren't just about ordering, they highlight the exact issue you're having where you're trying to return a value before its actually been update (this can't be done, and making your function blocking / wait for the value before you return isn't the right approach). The callback that you pass to bsvalidate would act as code you want to run once your event listener fires (eg: the code you currently have after your `.forEach()`). – Nick Parsons Aug 26 '21 at 11:15
  • As far as I understand Im not trying to return a value before its actually been updated. I want to check if there is any 'false' argument / 1st console.log triggered within .forEach function to stop the 'form submit'. To check if window.check was false or 1st console.log triggered I need to have access to whole information after .forEach ended. I can pass bsvalidate(cb) but sometimes first item in the loop can be true but another one can be false which corrupts my control logic. :S – damdafayton Aug 26 '21 at 12:16
  • Simply I want to make sure window.check==true after .forEach ended and I have to know .forEach method has run for each element to trigger next logic. Is it still the same problem you addressed before? – damdafayton Aug 26 '21 at 12:20
  • Is your issue that you have a few forms, say 3 for example, and you want to make sure all 3 of them are valid, and if so, then return `true`, otherwise return `false`? – Nick Parsons Aug 26 '21 at 12:34
  • If there are few forms yes, if not, it's not few forms but few inputs inside the existing form. Its an html form element which has plenty inputs inside. '.forEach' is checking each input inside each form. "form" in forEach(function (form)) corresponds to inputs in the form. – damdafayton Aug 26 '21 at 12:44
  • Hey thanks a lot for all the ideas. Ive fixed the script already. Problem was caused mainly by me forgetting to remove old script from the page. So I was applying two scripts: one modified other original at the same time since hours. After removing the original one simple error counter variable fixed the problem without any further need for callbacks and promises. – damdafayton Aug 26 '21 at 15:42

0 Answers0