Automatically open Modal


#1

I think I have a quite common use case for the modal component. Basically what I like to achive is this:

Simple (tab) application. If the user is not logged in, a login modal is shown directly on top of everything.

But I get this error:

TypeError: Cannot call method 'show' of undefined
at Scope.$scope.openModal (...)

Code: http://plnkr.co/edit/yBcd6eM5orL5QblRmEJ0?p=preview

Any help would be really appreciated!


Show modal based on localStorage variable
#2

I’ve hacked away at it a bit. Here is a working example:

I THINK the problem with your original code is simply a timing issue. I don’t think the Modal service is instantiated by the time the user.notAuthorized is broadcasted. So, it’s not able to call the method that does not yet exist.

I’ve put in a very hackish timeout to allow the modal to get instantiated.

UPDATE : Ignore the stuff below about using resolve. It’s actually a good way to deal with async account validation, but it doesn’t help in your example. I tried another example getting rid of broadcast and just manually checking the Account status with UserService.isAuthorized(). Again, get the modal does not exist issue. So, it’s back to simply being a timing issue. I think the calls to $scope.openModal are occurring in the digest cycle before the Modal has been created. So, the delay seems the only fix I can think of.


However, I don't think using broadcast is the best way to do this. If you are using ng-route, you would be best to do a resolve on the route. The resolve should check the logged in status. Then, in your controller, the logged in status will have already been determined. Then, you check it, and launch the modal.

I THINK that would solve the problem.

Here is an example of what using the resolve looks like :

angular.module('myApp', ['ionic', 'ngRoute', 'ngAnimate','AccountService'])

    .config(['$sceDelegateProvider', '$compileProvider', function ($sceDelegateProvider, $compileProvider){
        $compileProvider.aHrefSanitizationWhitelist(/^\s*(https):/);
        $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https):/);
        $sceDelegateProvider.resourceUrlWhitelist(['self']);
    }])

    .config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {

        // All routes for the app
        $routeProvider.when('/home', {
            templateUrl: 'templates/intro.html',
            controller: 'IntroController',
            resolve : {
                loadData: function(AccountService) {
                    return AccountService.initialize();
                }
            }
        });

        // if none of the above routes are met, use this fallback
        // which executes the 'AppCtrl' controller (controllers.js)
        $routeProvider.otherwise({
            redirectTo: '/home'
        });

    }]);

#3

Thanks @Calendee!

I’ve also played arround with it and was hoping for a directive solving the issue but that wasn’t the case. Putting it in angular.run() didn’t do the trick either (which makes sense after reading the docs).

Setting the timeout works but really seems to be hackish.

Maybe someone @ionic could elaborate on this? Chaining a promise to the Modal or some other kind of event broadcast might be handy.


#4

I’ve just come across this issue and found your question. My solution was to do what you’ve done with timeout but using AngularJS $timeout service.

$timeout($scope.showModal, 0);

This opens the modal immediately and doesn’t leave the “Angular world”.

It would nice if there were a couple of options that would open the modal on load and/or have the modal opened on load so you don’t see the initial transition. Just a thought!