3

I have mainly to open an angular popup window based on a template. But I need to obtain the data from an ajax call.

The Module sample explains how to use a template, but I am confused where to place an ajax call to obtain the items, like follows (the snippet is not working, but is the same as the sample):

angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl',
    function($scope, $uibModal, $log) {

      //
      // need to obtain these items from an AJAX/GET call
      //
      $scope.items = ['item1', 'item2', 'item3'];

      $scope.open = function(size) {
          var modalInstance = $uibModal.open({
            templateUrl: 'myModalContent.html',
            controller: 'ModalInstanceCtrl',
            size: size,
            resolve: {
              items: function() {
                return $scope.items;
              }
            }
          });
<div ng-controller="ModalDemoCtrl">
  <script type="text/ng-template" id="myModalContent.html">
    <div class="modal-header">...</div>
    <div class="modal-body">
      <ul>
        <li ng-repeat="item in items">...</li>
      </ul>
    </div>
    <div class="modal-footer">...</div>
  </script>

  <button type="button" ng-click="open()">Open me!</button>

</div>

I have a link that return JSON data, I'd modify the function like this:

      $scope.open = function(size, jsonLink) {
          var modalInstance = $uibModal.open({

            // ?????
            templateJsonUrl: jsonLink,
            // ?????

            templateUrl: 'myModalContent.html',
            controller: 'ModalInstanceCtrl',
            size: size,
            resolve: {
              items: function() {
                return $scope.items;
              }
            }
          });
serge
  • 13,940
  • 35
  • 121
  • 205
  • The sample has a 'ModalInstanceCtrl' defined that I don't see in your code. That's where you could make your ajax call to get data that you'd bind to the model. – jbrown Dec 04 '15 at 13:38
  • To make ajax requests Angular provides you with the $http service. I dont think that the $uibModal service support this. I would add it to the $scope.open method and then populate it to the scope for the view to pick up from there. – Frank Adrian Dec 04 '15 at 13:39
  • @jbrown: I did't include the whole controller, just the `open` function from it, cause is there where I should call the ajax page(perhaps via $http), but the question is where? directly in open or in resolve part, or include `open` in http promise ... – serge Dec 04 '15 at 13:45
  • You can make the $http call in the open, assign the result to a var that you inject into the instance controller via the resolve(). Alternatively, you could make the $http call in the instance controller directly. – jbrown Dec 04 '15 at 13:53

2 Answers2

3

Just make a request with a http service, and assign result to $scope.items when it will be resolved. A digest cycle will make bindings. Don't forget to inject http service itself.

angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl',
    function($scope, $http, $uibModal, $log) {

      $http
          .post('/your_pass_to_json.json', data)
          .then(function(data) {
              $scope.items = data.items;
          });

      $scope.open = function(size) {
          var modalInstance = $uibModal.open({
            templateUrl: 'myModalContent.html',
            controller: 'ModalInstanceCtrl',
            size: size,
            resolve: {
              items: function() {
                return $scope.items;
              }
            }
          });

Here is plunker, but I've assigned $scope.items in the promise rejection because could not mock the XHR request.

UPDATE

Or you can put modal opening in the xhr callback:

$scope.open = function(size) {
    $http
    .post('/your_pass_to_json.json', data)
    .then(function(data) {
        var modalInstance = $uibModal.open({
            templateUrl: 'myModalContent.html',
            controller: 'ModalInstanceCtrl',
            size: size,
            resolve: {
              items: function() {
                return data.tiems;
              }
            }
       });
   });
}

In this case, the modal will always be opened with a delay. I would suggest you to make an xhr request once the controller was initialized, and make a verification on the opening event: if xhr was already fired before, take items from $scope, if it wasn't, cancel previous request and make a new one.

Alexandr Lazarev
  • 12,554
  • 4
  • 38
  • 47
1

@Lazarev's answer is correct, but additionally in Angular, you have to make ajax calls from angular services and directly inject to controllers.

like this; AngularJS Ajax Call in Service

Community
  • 1
  • 1
İsmail Şener
  • 413
  • 2
  • 6
  • 14
  • Ajax calls do not need to be made from a service. You are referring to a specific pattern that uses services. The calls can be made directly from the controller. – jbrown Dec 04 '15 at 16:03