Search code examples
javascriptjqueryaxiosconfirm

Open multiple jQuery confirm boxes after processing of one is completed


I have an API call where I get the array in response. Now I want to open jQuery Confirm by looping on the response one by one but the problem is, they are opening all at once. Here is the code

axios.post('/orders/ask-for-order-price', {ids: order_ids}).then((response) => {
        if (response.status === 200) {
            let orders = response.data
            $.each(orders, function (index, item) {
                if (item.ask_for_price === true) {
                    showPricePopup(index, item.address, item.order_type, item.client_name)
                }
            })
        }
    }).catch((error) => {
        console.info(error)
    })



showPricePopup = (id, address, type, client_name) => {
    $.confirm({
        title: 'Please enter order price for ',
        content: '' +
            '<form action="" class="formName">' +
            '<div class="form-group">' +
            '<label><strong>' + type + '</strong> at <strong>' + address + '</strong> by <strong>' + client_name + '</strong></label>' +
            '<input type="text" placeholder="Enter the price here" class="price form-control" required />' +
            '</div>' +
            '</form>',
        buttons: {
            formSubmit: {
                text: 'Submit',
                btnClass: 'btn-blue',
                action: function () {
                    var price = this.$content.find('.price').val();
                    if (!price) {
                        $.alert('provide a valid price');
                        return false;
                    }
                    $.alert('Your price is ' + price);
                }
            },
            cancel: function () {
                //close
            },
        },
        onContentReady: function () {
            // bind to events
            var jc = this;
            this.$content.find('form').on('submit', function (e) {
                // if the user submits the form by pressing enter in the field.
                e.preventDefault();
                jc.$$formSubmit.trigger('click'); // reference the button and click it
            });
        }
    });

}

EDIT response.data looks like this

{
  "1": {
    "ask_for_price": true,
    "order_type": "Construction New",
    "address": "3685  Simons Hollow Road, Hanover Township, PA",
    "created_at": "03/16/20",
    "client_name": "Muhammad Ahmad Baig",

  },
  "2": {
    "ask_for_price": true,
    "order_type": "Phase I",
    "address": "4744  Horizon Circle, University Place, WA",
    "created_at": "03/16/20",
    "client_name": "Muhammad Ahmad Baig",

  },
  "3": {
    "ask_for_price": true,
    "order_type": "ETS",
    "address": "1491  Gambler Lane, ALLENDALE, IL",
    "created_at": "03/16/20",
    "client_name": "Muhammad Ahmad Baig",

  },
  "4": {
    "ask_for_price": true,
    "order_type": "Property Condition Assesment",
    "address": "58  Glenview Drive, Corpus Christi, TX",
    "created_at": "03/16/20",
    "client_name": "Muhammad Ahmad Baig",

  },
  "5": {
    "ask_for_price": true,
    "order_type": "Property Condition Assesment (Short Form)",
    "address": "858  Duncan Avenue, Scarsdale, NY",
    "created_at": "03/16/20",
    "client_name": "Muhammad Ahmad Baig",

  },
  "6": {
    "ask_for_price": true,
    "order_type": "Plan and Cost Review",
    "address": "3116  Wolf Pen Road, Pacifica, CA",
    "created_at": "03/16/20",
    "client_name": "Muhammad Ahmad Baig",

  },
}

Solution

  • If you want the popups to show sequentially, you will need to use for loop combined with promises. The reason being that you want to await for one popup to be dismissed (which will resolve the promise), before moving on to the next one:

    for (const key of Object.keys(orders)) {
        const item = orders[key];
    
        // We show popup sequentially, and wait for it to be resolved before moving on to the next
        await showPricePopup(index, item.address, item.order_type, item.client_name);
    }
    

    NOTE: For this to work, make sure that the callback in your .then() is an async function, i.e. .then(async (response) => { ... }).

    This brings us to the next step: showPricePopup should return a promise: you can simply wrap your entire inner content of the function as such:

    showPricePopup = (id, address, type, client_name) => {
        return new Promise(resolve => {
            // Original logic inside the function
        });
    }
    

    Then, make sure that you resolve the promise whenever (1) the form is successfully submitted, or (2) the form is dismissed. Resolving the promise will then cause the await in the for loop to finish, allowing us to move on to opening the modal for the next item in the next iteration.

    Therefore, your updated code should look something like this:

    axios.post('/orders/ask-for-order-price', {
        ids: order_ids
    }).then(async (response) => {
        if (response.status === 200) {
            let orders = response.data;
    
            // Use for loop to iterate through all orders
            // In each iteration, await promise returned by `showPricePopup()`
            for (const key of Object.keys(orders)) {
                const item = orders[key];
                await showPricePopup(index, item.address, item.order_type, item.client_name);
            }
        }
    }).catch((error) => {
        console.info(error)
    })
    
    showPricePopup = (id, address, type, client_name) => {
        return new Promise((resolve) => {
            $.confirm({
                title: 'Please enter order price for ',
                content: '' +
                    '<form action="" class="formName">' +
                    '<div class="form-group">' +
                    '<label><strong>' + type + '</strong> at <strong>' + address + '</strong> by <strong>' + client_name + '</strong></label>' +
                    '<input type="text" placeholder="Enter the price here" class="price form-control" required />' +
                    '</div>' +
                    '</form>',
                buttons: {
                    formSubmit: {
                        text: 'Submit',
                        btnClass: 'btn-blue',
                        action: function () {
                            var price = this.$content.find('.price').val();
                            if (!price) {
                                $.alert('provide a valid price');
                                return false;
                            }
                            $.alert('Your price is ' + price);
    
                            // Resolve your promise here so you can move on to the next one
                            resolve();
                        }
                    },
                    cancel: function () {
                        // If the modal is closed, you also want to resolve the promise
                        resolve();
                    },
                },
                onContentReady: function () {
                    // bind to events
                    var jc = this;
                    this.$content.find('form').on('submit', function (e) {
                        // if the user submits the form by pressing enter in the field.
                        e.preventDefault();
                        jc.$$formSubmit.trigger('click'); // reference the button and click it
                    });
                }
            });
        });
    }