1

I am using controllerAs syntax and opening angular-ui modal dialog from it with variable passed to modal controller using "resolve". After opening, I am executing ajax "request", and "updating" variable passed to modal controller. However in modal controller this change is not reflected. Code snippet:

angular.module('main')
.controller('mainCtrl', ['$modal', function($modal){
    vm = this;
    vm.paymentMessage = 'We are processing you request. Wait a moment.';
    vm.showModal();
    testService.TestAjax().then(function(response){
            vm.paymentMessage = response.data.message;
   });
   vm.showModal = function() {
        var modalConfig = {
            controller: 'ModalProcessingCtrl as modalProcessingCtrl',
            templateUrl: 'template/processingModal.html',
            size: 'lg',
            resolve: {
                paymentMessage: function () {
                    return vm.paymentMessage;
                }
            }
        };
        $modal.open(modalConfig).result;
    };
 }])
.controller('ModalProcessingCtrl', ['$modalInstance','paymentMessage', function($modalInstance, paymentMessage){
    self = this;
    self.paymentMessage = paymentMessage;
    self.cancel = function () {
        $modalInstance.dismiss('cancel');
    };
}])

and the tamplate is like this:

    <script type="text/ng-template" id="template/processingModal.html">
      <div class="modal-header">
        <button type="button" class="close" ng-click="modalProcessingCtrl.cancel()"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title" id="id_card_processing_label">Processing</h4>
      </div>
      <div class="modal-body">
            <div>
              <p>{{ modalProcessingCtrl.paymentMessage }}</p>
            </div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" ng-click="modalProcessingCtrl.cancel()">Close</button>
      </div>
    </script>    

I can see message initially set, but not updated message after ajax request call finished. Is there any way to reflect changes for paymentMessage from mainCtrl in modalProcessingCtrl and show it in modal dialog? Thanks

2
  • You have misquoted 'main' in the angular.module() (only one quote) Commented Dec 15, 2016 at 13:03
  • Sorry, this is not a working example, I just cleaned my code and removed all unnecessary parts. That's where syntax error came from. This is definitely not a solution for my question Commented Dec 15, 2016 at 13:09

3 Answers 3

1

Change the resolve function to return a promise instead of a value that has not yet been defined:

        resolve: {
            paymentMessage: function() {
                //return vm.paymentMessage;
                var promise = testService.TestAjax();
                var messagePromise = promise.then(function(response) {
                    //return data for chaining
                    return response.data.message;
                });
                return messagePromise;
             }
         }

By returning a promise to the resolve function, the modal will get the value of the message after it has been returned from the server. If a server error occurs, it will be propagated as a rejected promise.

Because calling the .then method of a promise returns a new derived promise, it is easily possible to create a chain of promises. It is possible to create chains of any length and since a promise can be resolved with another promise (which will defer its resolution further), it is possible to pause/defer resolution of the promises at any point in the chain.

-- AngularJS $q Service API Reference -- Chaining Promises.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. That was exactly what I needed.
0

Try this way:

    angular.module('main)
            .controller('mainCtrl', ['$modal', function($modal) {
                vm = this;
                vm.paymentMessage = 'We are processing you request. Wait a moment.';
                vm.showModal();
                vm.showModal = function() {
                    var modalConfig = {
                        controller: 'ModalProcessingCtrl as modalProcessingCtrl',
                        templateUrl: 'template/processingModal.html',
                        size: 'lg',
                        resolve: {
                            paymentMessage: function() {
                                return vm.paymentMessage;
                            }
                        }
                    };
                    $modal.open(modalConfig).result;
                };
            }])
            .controller('ModalProcessingCtrl', ['$modalInstance', 'paymentMessage', function($modalInstance, paymentMessage) {
                self.paymentMessage = paymentMessage;
                testService.TestAjax().then(function(response) {
                    self.paymentMessage = response.data.message;
                });
                self.cancel = function() {
                    $modalInstance.dismiss('cancel');
                };
            }])

Using resolve fires up before controller loads and templates rendered. It is one-time thing.

Comments

-2

try this solution , and accept answer if right :)

angular.module('main')
        .controller('mainCtrl', ['$modal', function($modal) {
            vm = this;
            vm.paymentMessage = 'We are processing you request. Wait a moment.';
            vm.showModal();
            /*testService.TestAjax().then(function(response) {
                vm.paymentMessage = response.data.message;
            });*/
            vm.showModal = function() {
                var modalConfig = {
                    controller: 'ModalProcessingCtrl as modalProcessingCtrl',
                    templateUrl: 'template/processingModal.html',
                    size: 'lg',
                    resolve: {
                        /*paymentMessage: function() {
                            return vm.paymentMessage;
                        } , */
                        paymentMessage: ['$q', 'testService', function($q, testService) {
                            var defer = $q.defer();
                            testService.TestAjax().then(function(response) {
                                defer.resolve(response.data.message);
                            });
                            return defer.promise;
                        }]

                    }
                };
                $modal.open(modalConfig).result;
            };
        }])
        .controller('ModalProcessingCtrl', ['$modalInstance', 'paymentMessage', function($modalInstance, paymentMessage) {
            self.paymentMessage = paymentMessage;
            self.cancel = function() {
                $modalInstance.dismiss('cancel');
            };
        }])

5 Comments

Answer has no explaination of the fix. The resolve is a $q defer anti-pattern that hangs on error conditions.
I maked here $q to return specific attribute from the result , I think now it is not anti-pattern !!
What if the rssult.data has more than attribute like result.data = {name:"value",age:"agevalue",message:"messagevalue"} and here I just need result.data.message ?? Is the $q in this case anti-pattern ??
In that case create a derived promise by chaining. See my answer for an example of that.
Yes , you right 👍👍 I'm sorry man I have not seen your answer

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.