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

Ahmed Mostafa
  • 666
  • 1
  • 4
  • 16
branko
  • 43
  • 6
  • You have misquoted 'main' in the angular.module() (only one quote) – rrd Dec 15 '16 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 – branko Dec 15 '16 at 13:09

3 Answers3

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.

georgeawg
  • 48,608
  • 13
  • 72
  • 95
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.

Dinesh Sundaraneedi
  • 402
  • 1
  • 5
  • 18
-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');
            };
        }])
Ahmed Mostafa
  • 666
  • 1
  • 4
  • 16
  • Answer has no explaination of the fix. The resolve is a [$q defer anti-pattern](http://stackoverflow.com/questions/30750207/is-this-a-deferred-antipattern) that hangs on error conditions. – georgeawg Dec 15 '16 at 18:21
  • I maked here $q to return specific attribute from the result , I think now it is not anti-pattern !! – Ahmed Mostafa Dec 15 '16 at 19:30
  • 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 ?? – Ahmed Mostafa Dec 15 '16 at 19:36
  • In that case create a derived promise by chaining. See my answer for an example of that. – georgeawg Dec 15 '16 at 22:04
  • Yes , you right I'm sorry man I have not seen your answer – Ahmed Mostafa Dec 15 '16 at 23:54