harpax
harpax

Reputation: 6116

unable to open a modal with angular and ui.routes

I am trying to follow this example to show a bootstrap modal on a certain state. It works fine without a modal (so the state config should be ok). All needed dependencies (ie angular bootstrap) should be available.

when I do a console.debug($stateParams) before $modal.open I get the correct data, within the $modal.open-method however the stateParams from the last state are returned (the state I am coming from)

Any hints?


EDIT

the relevant state cfg:

.state('publications.view', {
    parent: 'publications.productSelection',
    url: '/{productSlug:[a-zA-Z0-9-]+}/{docID:[0-9]+}_{slug:[a-zA-Z0-9-]+}',
    onEnter: ['restFactory', '$state', '$stateParams', '$modal',
        function(restFactory, $state, $stateParams, $modal) {
            console.debug($stateParams.docID);
            $modal.open({

                templateUrl: 'partials/publication.html',
                resolve: {
                    publication: ['restFactory', '$stateParams',
                        function(restFactory, $stateParams) {
                            console.debug($state.params);
                            console.debug($stateParams);
                            return restFactory.view($stateParams.language, $stateParams.productSlug, $stateParams.docID);
                        }
                    ]
                },
                controller: ['$scope', '$sce', 'publication', '$rootScope',
                    function($scope, $sce, publication, $rootScope) {
                        $rootScope.pageTitle = publication.data.data.publication.Publication.title;
                        $scope.publication = $sce.trustAsHtml(publication.data.data.publication.Publication.content);
                    }
                ]
            });
        }
    ]
});

Upvotes: 0

Views: 420

Answers (1)

Julian Craske
Julian Craske

Reputation: 21

You can get around this issue by injecting the current $stateParams into the onEnter function, save them as state in some service, and inject that service instead into your modal resolves.

I am adapting the code from here: Using ui-router with Bootstrap-ui modal

.provider('modalState', function($stateProvider) {
    var modalState = {
        stateParams: {},
    };

    this.$get = function() {
        return modalState;
    };

    this.state = function(stateName, options) {
        var modalInstance;
        $stateProvider.state(stateName, {
            url: options.url,
            onEnter: function($modal, $state, $stateParams) {
                modalState.stateParams = $stateParams;
                modalInstance = $modal.open(options);
                modalInstance.result['finally'](function() {
                    modalInstance = null;
                    if ($state.$current.name === stateName) {
                        $state.go('^');
                    }
                });
            },
            onExit: function() {
                if (modalInstance) {
                    modalInstance.close();
                }
            }
        });
    };
})

Then in your app config section

.config(function($stateProvider, $urlRouterProvider, modalStateProvider) {
    modalStateProvider.state('parent.child', {
        url: '/{id:[0-9]+}',
        templateUrl: 'views/child.html',
        controller: 'ChildCtrl',
        resolve: {
            role: function(Resource, modalState) {
                return Resource.get({id: modalState.stateParams.id}).$promise.then(function(data) {
                    return data;
                });
            }
        }
    });
}

Upvotes: 1

Related Questions