Seraph Cheng Seraph Cheng - 4 months ago 34
AngularJS Question

Ionic - when should ionicModal.remove() be called? [Ionic Modal Hide Callback]

In my controller, modal views are initialized with a factory by listening to the

$ionicView.afterEnter
event. As the documentation suggests, modal views should be removed whenever the current active ionic view is about to be destroyed. A function is called in the
$ionicView.beforeLeave
callback in order to remove the modal views.

.controller('UserProfileCtrl', function($scope, $state, user, ModalFactory) {
$scope.user = user;

$scope.checkOrders = function() {
$state.go('app.orders');
};

$scope.$on('$ionicView.afterEnter', function() {
$scope.modals = ModalFactory.getUserProfileModals($scope, user.photos);
});

$scope.$on('$ionicView.beforeLeave', function() {
$scope.modals.remove();
});
});

.factory('ModalFactory', function($ionicModal, $ionicSlideBoxDelegate) {
var modalFactory = {};

modalFactory.getUserProfileModals = function(scope, images) {
var modals = {
'views': [],
'data': []
};

$ionicModal.fromTemplateUrl('templates/modals/common/image-view.html', { 'scope': scope }).then(function(modal) { modals.views.imageView = modal; });

if (images) {
modals.data.images = images;
}

modals.open = function(view, slide) {
Object.keys(this.views).forEach(function(key, index) {
console.log(key);
});

if (view && this.views.hasOwnProperty(view)) {
this.views[view].show();

if (view == 'imageView' && slide) {
$ionicSlideBoxDelegate.$getByHandle('image-view').slide(slide);
}
}
};

modals.close = function(view) {
Object.keys(this.views).forEach(function(key, index) {
console.log(key);
});

if (view && this.views.hasOwnProperty(view)) {
this.views[view].hide();
} else {
Object.keys(this.views).forEach(function(key, index) {
this.views[key].hide();
});
}
};

modals.remove = function() {
console.log('remove');
Object.keys(this.views).forEach(function(key, index) {
console.log(key);
});

this.data.splice(0, this.data.length);

Object.keys(this.views).forEach(function(key, index) {
this.views[key].remove();
});

this.views.splice(0, this.views.length);
};

return modals;
};

return modalFactory;
});


However, I get the following output in the console when I execute these actions in sequence:


  1. call
    $scope.modals.open('imageView', 1)
    ,

  2. call
    $scope.modals.close()
    ,

  3. navigate to another page with
    $state.go('app.orders')
    .



Screenshot showing console output

I tried listening to
$destroy
instead of
$ionicView.beforeLeave
, but then
$scope.modals.remove()
is not called at all. It seems
$destroy
is not fired when I am testing my application with Chrome.

Can anyone tell me when should I remove the modal views, and why is there such an error message in my scenario?




Update



After I modified the code in
ModalFactory
as follows, the error is gone.

function open(view, slide) {
if (view && modals.views.hasOwnProperty(view)) {
modals.views[view].show();

if (view == 'imageView' && slide) {
$ionicSlideBoxDelegate.$getByHandle('image-view').slide(slide);
}
}
};

function close(view) {
if (view && modals.views.hasOwnProperty(view)) {
modals.views[view].hide();
} else {
Object.keys(modals.views).forEach(function(key, index) {
modals.views[key].hide();
});
}
};

function remove() {
console.log('remove');

modals.data.splice(0, modals.data.length);

Object.keys(modals.views).forEach(function(key, index) {
modals.views[key].remove();
});

modals.views.splice(0, modals.views.length);
};

modals.open = open;
modals.close = close;
modals.remove = remove;

return modals;

Answer

By using $scope.$on('$destroy', ..) method Angular will broadcast a $destroy event just before tearing down a scope and removing the scope from its parent.

Here is the example of how i resolved modal.remove() issue,

.factory('ModalFactory', function($ionicModal, $rootScope) {
    var init = function(tpl, $scope) {
        var promise;
        $scope = $scope || $rootScope.$new();

        promise = $ionicModal.fromTemplateUrl(tpl, {
            scope: $scope,
            animation: 'slide-in-right'
        }).then(function(modal) {
            $scope.modal = modal;
            return modal;
        });

        $scope.openModal = function() {
            $scope.modal.show();
        };
        $scope.closeModal = function() {
            $scope.modal.hide();
        };
        $scope.$on('$destroy', function() {
            $scope.modal.remove();
        });

        return promise;
    };

    return {
        init: init
    }

})

And from the controller, pass the current scope of controller and modal template

.controller('UserProfileCtrl', function($scope, $state, user, ModalFactory) {    
    ModalFactory.init('image-view.html', $scope)
            .then(function(modal) {
                confirmationModal = modal;
                confirmationModal.show();
            });
})

Hope this is helpful for you.

Comments