Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use the same controller for modal and non-modal form in Angular UI Bootstrap?

I've got a modal with a registration form. The same form should be displayed at the bottom of the landing page not in a modal.

Currently my controller that handles registration modal takes $modalInstance as one of its parameters along $scope etc. If I add ng-controller="SignUpCtrl" to an element in the landing page, it doesn't work, because the controller wasn't created via $modal.open method and so Angular complains about Unknown provider: $modalInstanceProvider <- $modalInstance.

I've got a service for registering users (authService.signUp(data).then/catch...), but the controller itself does a bit more - handles input, emits events (e.g. with translated error messages), sets cookies etc.

What's the best way to handle such case without duplicating almost whole controller code? Should I move the code from controller into yet another, higher-level service?

like image 514
szimek Avatar asked May 21 '14 10:05

szimek


2 Answers

After struggling for a long while I found a easier trick to reuse our Controller for both modal and normal case.

I found that we can pass caller's scope to modal controller, so I pushed modalInstance into $scope and passed it to the modal controller. Now you don't have unknown provider problem because $scope is a well known one.

Below is an example:

CallerController = function($rootScope, ...) {
   var modalScope = $rootScope.$new();
   modalScope.modalInstance = $modal.open({
        templateUrl: tempUrl,
        controller: ReusableModalController,
        scope: modalScope // <- This is it!
    });

    modalScope.modalInstance.result.then(function (result) {
        // Closed
    }, function () {
        // Dismissed
    });
};

ReusableModalController = function($scope, ...){
    var dataToSendBack = 'Hello World';
    $scope.modalInstance.close(dataToSendBack);
};

Cheers!

like image 132
KinoP Avatar answered Nov 18 '22 03:11

KinoP


If you are using ui-router you can easily use the resolve from ui-router to provide a $uibModalInstance (was $modalInstance before):

$stateProvider
.state('conductReview', {
    url: '/review',
    templateUrl: '/js/templates/review.html',
    controller: 'yourController',
    resolve: {
        $uibModalInstance: function () { return null; } // <- workaround if you want to use $uibModalInstance in your controller.
    }
})

That way you can use your modal controller like a normal controller. If you inject $uibModalInstance in your controller it will be null.

like image 39
Thomas Avatar answered Nov 18 '22 02:11

Thomas