Angularjs UI Modal Forms

All we need is an easy explanation of the problem, so here it is.

I used to have a login dialog using bootstrap modal:

  $scope.loginDialog = {
    backdrop: true,
    keyboard: true,
    windowClass: "modal loginDialog",
    backdropClick: true,
    templateUrl: '/tmpl/user/loginForm',
    controller: function dialogController($scope, $modalInstance) {
      $scope.submit = function () {
        $http.post('/api/login', $scope.user).success(...);
      }
    }
  };

Login form looks like this:

form#loginBox(ng-submit="submit()")
  .modal-body.login-box
    .formItem
      label(for='user[usernameOrEmail]') Name or Email:
      input(type='text', name='user[usernameOrEmail]', required="required", value='', ng-model="user.user")
    .formItem
      label(for='user[password]') Password:
      input(name='user[password]', type='password', value='', required="required", ng-model="user.password")
  .modal-footer
    input.btn.btn-primary( type="submit", value="Login")

In angular ui 0.4 and angularjs 1.1.3 this worked fine.

I’ve updated to the latest angular ui 0.6 and 1.2rc2 and now this no longer works. Specifically $scope.user is no longer the same as the one in the form. How do I get the $scope of the form element? I see it in the batarang but not from the loginDialog controller.

Thanks

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

You are missing the resolve property on your open model object. This is the new way to pass in locals to your modal’s controller.

From the ui-bootstrap documentation:

resolve – members that will be resolved and passed to the controller
as locals; it is equivalent of the resolve property for AngularJS
routes

Updated code and working plunker

angular.module('plunker', ['ui.bootstrap']);
var ModalDemoCtrl = function ($scope, $modal, $log) {

    $scope.user = {
        user: 'name',
        password: null
    };

    $scope.open = function () {

        $modal.open({
            templateUrl: 'myModalContent.html',
            backdrop: true,
            windowClass: 'modal',
            controller: function ($scope, $modalInstance, $log, user) {
                $scope.user = user;
                $scope.submit = function () {
                    $log.log('Submiting user info.');
                    $log.log(user);
                    $modalInstance.dismiss('cancel');
                }
                $scope.cancel = function () {
                    $modalInstance.dismiss('cancel');
                };
            },
            resolve: {
                user: function () {
                    return $scope.user;
                }
            }
        });
    };
};

Method 2

In continuance to the above reply, I forked the plunker and made a few minor changes:

Versions used:

  • angularjs : 1.2.11
  • angular-ui-bootstrap : 0.10.0
  • bootstrap : 3.1.0

Another important difference is that the user object is now passed from the HTML template, which could be a case when you might have a list of items displayed and you would want to open a modal dialog, by passing the object representing the list item clicked.

Plunker is at: http://plnkr.co/edit/bfpma2?p=preview

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply