1

I am trying to create a directive that uses angular ui bootstrap modal. I would like to open this directive from my controller when a $http request is made, and close it when the request resolves. I'm new to angular and a bit stuck. Here's what I've got so far.

expedition.html controller:

.controller('ExpeditionCtrl', ['$http', 'UserFactory', '$scope',
    function ($http, UserFactory, $scope) {
        var vm = this;
        vm.totalItems;
        vm.itemsPerPage = 100;
        vm.currentPage = 1;
        vm.pageChanged = pageChanged;
        vm.content = [];
        vm.loadingInstance;
        vm.open;
        fetchPage();

        function pageChanged() {
            fetchPage();
        }

        function fetchPage() {

            $http.get('myapi?page=' + vm.currentPage + "&limit=" + vm.itemsPerPage)
                .then(function(response) {
                    angular.extend(vm.content, response.data.content);
                    vm.content = response.data.content;
                    vm.totalItems = response.data.totalElements;
                })
        }

    }

expedition.html:

<div class="section">
    <div class="sectioncontent">
        // some html

            <uib-pagination total-items="vm.totalItems" ng-model="vm.currentPage" ng-change="vm.pageChanged()" items-per-page="vm.itemsPerPage"></uib-pagination>

        </div>
        <loading-modal loadingInstance="vm.loadingInstance" open="vm.open"></loading-modal>
    </div>
</div>

loadingModal.directive.js:

.directive('loadingModal', ['$uibModal',
    function($modal) {
        return {
            transclude: true,
            restrict: 'EA',
            template: '<div ng-init="open()"> Test Loading </div>',
            scope: {
                loadingInstance: "=",
                open: "="
            },
            link: function(scope, element, attrs) {

                scope.open = function(){

                    scope.loadingInstance = $modal.open({
                        templateUrl: 'app/templates/loadingModal.tpl.html',
                        controller:  scope.useCtrl,
                        size: 'sm',
                        windowClass: 'app-modal-window',
                        backdrop: true,

                    });
                    scope.loadingInstance.result.then(function(){
                        scope.initialized = true;
                        console.log('Finished');
                    }, function(){
                        scope.initialized = true;
                        console.log('Modal dismissed at : ' + new Date());
                    });
                };
            }
        };
    }]);

loadingModal.tpl.html:

<div class="modal-body">
    Loading ....
</div>
5
  • Please include the content of the module template in the question Commented Apr 26, 2016 at 22:03
  • You haven't included the part in which you call the $uibModalInstance.close() (Or $uibModalInstance.dismiss()), but you need to call one of those function after the request has been resolved. Commented Apr 26, 2016 at 22:14
  • right, I hadn't done that as I haven't been able to get the modal to open. I haven't been able to open the dialog. I tried using ng-init in the directive template. "template: '<div ng-init="open()"> Test Loading </div>'," Also, when I tried to manually open the modal, I got an error: docs.angularjs.org/error/$compile/… Commented Apr 26, 2016 at 22:35
  • I think ng-init is messing this up. try to remove ng-init and move all of the scope.open function outside. Commented Apr 26, 2016 at 22:52
  • @MuliYulzary: If I remove ng-init, the modal will open on page load, however I still get an error about not being able to assign the modal instance to an undefined variable, so I can't close it from my controller Commented Apr 27, 2016 at 13:19

2 Answers 2

2

Ok, so I was able to do this by using a factory. Then in the controller, I call LoadingModalFactory.open() when I initiate a $http request, and LoadingModalFactory.modalInstance.close() when the request resolves. Maybe there's a better way to do this, but for now this is working.

.factory('LoadingModalFactory', ['$uibModal', function($uibModal) {
    var modalInstance;
    var loadingModalFactory = {
        open: open,
        modalInstance: modalInstance,
    };

    return loadingModalFactory;

    function open() {
        loadingModalFactory.modalInstance = $uibModal.open({
            templateUrl: 'app/components/modals/templates/loadingModal.tpl.html',
            size: 'sm',
            windowClass: 'app-modal-window',
            backdrop: true,

        });
    }

}]);
Sign up to request clarification or add additional context in comments.

Comments

1

In your fetchPage() function:

  1. Open the modal and return its object to a variable
  2. Run the $http call and in the resolution, close the modal with its stored variable reference

var modal = $uibModal.open({ //your modal config }); $http.get(...).then(function(response) { modal.close(); });

I may be going outside of the question, but you don't have to do this in a directive. You can still modularize this by using a template for the modal and a controller for the modal defined elsewhere.

If you need to do this in a directive, you could pass the http get function into the directive with the '&' scope property.

1 Comment

If I didn't use a directive, then I would need to type the modal config in every controller I want to use. Is passing the http get function the only way to make this a directive?

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.