2

I'm looping through some items in AngularJS and asking user input on each item using an AngularUI modal. My problem is that the loop finishes and all the modals render at once, without waiting for the user.

How can I make execution wait until the modal is closed?

An example of my code:

var listofitems = somelist; // loop through each item for (var i in listofitems){ if (listofitems[i].id == presetId){ // ask user confirmation in a modal $scope.selections = {'doThis': doThis, 'doThat': doThat} var openModal = function () { var modalInstance = $modal.open({ templateUrl: 'confirmationModal.html', controller: confirmationController, resolve: { selections: function () { return $scope.selections; } } }); modalInstance.result.then(function (selections) { doThis = selections.doThis; if (selections.doThat){ doThis = selections.doThis; } }); } // open the modal openModal(); } } } var confirmationController = function ($scope, $modalInstance, selections) { $scope.selections = selections; $scope.doThis = function () { $scope.selections.doThis = true; $modalInstance.close($scope.selections); }; $scope.doThat = function () { $scope.selections.doThat = true; $modalInstance.close($scope.selections); }; }; 

Incorporating @dsfg answer here's a Plunkr example. The ui modals don't work that well, but you can see execution has finished before the user has submitted any input.

1 Answer 1

2

You can't just pause the loop (well you can with ES6 generators). But you can change the way you iterate over array/object keys. What you can do is to check items one by one using function and execute next "iteration" only when previous is completed. This is easy with promises.

At first, make openModal return promise, then create helper function checkItems that will be invoked for every item in array of keys.

var openModal = function() { var modalInstance = $modal.open({ templateUrl: 'confirmationModal.html', controller: confirmationController, resolve: { selections: function() { return $scope.selections; } } }); return modalInstance.result.then(function(selections) { doThis = selections.doThis; if (selections.doThat) { doThis = selections.doThis; } }); }; var listofitems = somelist; var keys = Object.keys(listofitems); (function checkItems() { // get the first key and remove it from array var key = keys.shift(); if (listofitems[key].id == presetId) { // ask user confirmation in a modal $scope.selections = { 'doThis': doThis, 'doThat': doThat } // open the modal openModal().then(function() { if (keys.length) { checkItems(); } }); } })(); 

In above example, items will be checked until the first promise is rejected. If you want to check all items regardless of the promise state then use

openModal().finally(function() { if (keys.length) { checkItems(); } }); 
Sign up to request clarification or add additional context in comments.

3 Comments

This is really confusing me. I'm sure I followed your example correctly, and it does seem like the modals open consecutively and not all at once. But execution still continues like always. Logging shows the then() does not get executed, but somehow checkItems() is called until there are no more keys. I'm going to see if I can get a fiddle up.
And I edited the code on my side so if( keys.length ){ checkItems();} gets called even if the id's don't match.
Well, you put your code in the loop which is not going to pause. Instead try to refactor your code into array of promises and set done flag when all promises are resolved. plnkr.co/edit/1Eq5kNLOun9kn6PXsXhT?p=preview

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.