Search code examples
angularjsangular-strap

How do have an angular-strap modal / aside trigger an event?


I have a controller:

angular.module('mean').controller('LocationController', [
  '$scope', '$location', '$rootScope', '$aside', '$routeParams', '$filter',
  'ngTableParams', 'LocationService', 'UserService', 'CompanyService',
  function ($scope, $location, $rootScope, $aside, $routeParams, $filter,
    ngTableParams, LocationService,  UserService, CompanyService) {
      $rootScope.menuItem = 'locations';
      $scope.contentTemplate = '/views/location/index.html';
      $scope.locations = [];
      $scope.current_location = null;
      $scope.newLocation = {};
      $scope.location_parent_id = $routeParams.location_parent_id;
      $scope.validation_errors = [];


      $scope.index = function() {
        CompanyService.initialized.then(function() {
          var company_id = CompanyService.getCompany()._id;
          LocationService.list(company_id, $routeParams.location_parent_id).then(function(response) {
            if(response.data.status === 'ok') {
              $scope.locations = response.data.locations;
              $scope.current_location = response.data.location || null;
            } else {
              alert('TBD');
            }
          });
        });

        $scope.tableParams = new ngTableParams({
          page: 1,
          count: 10,
        }, {
          total: $scope.locations.length,
          getData: function($defer, params) {
            var orderedData = params.sorting() ? $filter('orderBy')($scope.locations, params.orderBy()) : $scope.locations;
            orderedData = params.filter() ? $filter('filter')(orderedData, params.filter()) : orderedData;

            $scope.locations = orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count());

            params.total(orderedData.length);
            $defer.resolve($scope.locations);
          }
        });
      }

      $scope.addLocationModal = function() {
        $scope.location_types = ['warehouse', 'section', 'row', 'shelf', 'bin'];
        $aside({
          scope: $scope,
          template: '/views/location/addLocationAside.html',
          show: true
        });
      }

      $scope.createLocation = function() {
        $scope.newLocation.company_id = CompanyService.getCompany()._id;
        LocationService.create($scope.newLocation).then(function(response) {
          if(response.data.status === 'ok') {
            $scope.$hide();
            $scope.index();
          } else {
            $scope.validation_errors = response.data.error;
          }
        });
      }
  }
]);

In the modal, I have a form, that when submitted, calls createLocation function. If the location is created successfully, I want the modal to close and the index to run and re-update the list. But that doesn't seem to happen. I think it's a $scope issue, but I'm not sure what.


Solution

  • Without any more details, it's really hard to tell the problem. So here are some guesses:

    scope apply

    If LocationService doesn't handle $scope.$apply, you might need to call it in the callback inside createLocation for the changes to take effect. Example:

    $scope.createLocation = function() {
        $scope.newLocation.company_id = CompanyService.getCompany()._id;
            LocationService.create($scope.newLocation).then(function(response) {
                $scope.$apply(function () {
                    if (response.data.status === 'ok') {
                        $scope.$hide();
                        $scope.index();
                    } else {
                        $scope.validation_errors = response.data.error;
                    }
                });
            });
    };
    

    You may also need to to do that in your $scope.index method, inside the LocationService.list callback.

    initialized is only resolved once

    It's possible that the CompanyService.initialized promise is only resolved once, at the loading of the app, so you aren't actually updating $scope.locations after closing the modal. I'd change that to:

    var isCountryServiceInitalized = false;
    
    $scope.index = function() {
        function updateLocations() {
            var company_id = CompanyService.getCompany()._id;
            LocationService.list(company_id, $routeParams.location_parent_id).then(function(response) {
                if (response.data.status === 'ok') {
                    $scope.$apply(function () { // you don't need this if LocationService already calls $scope.$apply
                        $scope.locations = response.data.locations;
                        $scope.current_location = response.data.location || null;
                    });
                } else {
                    alert('TBD');
                }
            });
        }
    
        if (!isCountryServiceInitalized) { 
            CompanyService.initialized.then(function () {
                isCountryServiceInitalized = true;
                updateLocations();
            });
        } else {
            updateLocations();
        }
    
        ...
    };
    

    ngTable reload

    It looks like you are using ng-table. You probably need to reload the table after updating $scope.locations. Use:

    $scope.tableParams.reload();