Vinoth Kumar
Vinoth Kumar

Reputation: 499

Angular js scope between directive and controllers

I have to show user login page in pop up and have to validate user name and password with the server by using angular js. I create one app model file, and one controller, service and one directive. My code looks like bellow,

app.js

angular.module('mint', ['ngAnimate', 'toastr']);

mycontroller.js

angular.module('mint').controller(
        'headercontroller',
        [
                '$scope',
                'headerservice',
                'toastr',
                function($scope, headerservice, toastr) {
$scope.showModal = false;

                    $scope.toggleModal = function() { 
                        $scope.showModal = !$scope.showModal;
                    };
$scope.userSignin = function(){
                        $scope.userloginbtn = false;
                        if($scope.signin_form.$valid){  //Error on this line signin_form is undefine. using $valid for undefine
                            var record = {};
                            angular.extend(record, $scope.signinForm);
                            console.log(record);
                        }else {
                            $scope.signin_form.submitted = false;
                            $scope.userloginbtn = true;
                        }
                    };
} ]);

my directive.js file is

angular
        .module('mint')
        .directive(
                'modal',
                function() {
                    return {
                        template : '<div class="modal fade">'
                                + '<div class="modal-dialog">'
                                + '<div class="modal-content">'
                                + '<div class="modal-header">'
                                + '<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>'
                                + '<h4 class="modal-title"><span><i class="fa fa-user"></i> {{ title }}</span></h4>'
                                + '</div>'
                                + '<div class="modal-body" ng-transclude></div>'
                                + '</div>' + '</div>' + '</div>',
                        restrict : 'E',
                        transclude : true,
                        replace : true,
                        scope : true,
                        link : function postLink(scope, element, attrs) {
                            scope.title = attrs.title;

                            scope.$watch(attrs.visible, function(value) { 
                                if (value == true)
                                    $(element).modal('show');
                                else
                                    $(element).modal('hide');
                            });

                            $(element).on('shown.bs.modal', function() {
                                scope.$apply(function() {
                                    scope.$parent[attrs.visible] = true;
                                });
                            });

                            $(element).on('hidden.bs.modal', function() {
                                scope.$apply(function() {
                                    scope.$parent[attrs.visible] = false;
                                });
                            });
                        }
                    };
                });

My html file looks like

<!DOCTYPE html>
<html lang="en" ng-app="mintmygold">
<body>
    <div class="container-fluid ban_bg"
        ng-controller="headercontroller">
        <div class="but_bg">
                    <button type="button" class="btn btn-default btn_sin" ng-click="toggleModal()">
                        <span><i class="fa fa-key"></i> Sign In</span>
                    </button>
        </div>

        <modal title="Login" visible="showModal">
                <form role="form" name="signin_form" class="signup_form" novalidate
                    ng-model="signin_form">
                    <div class="form-group">
                        <p class="infoMsg" ng-model="signinform_info">Please fill in your login credentials:</p>
                    </div>
                  <div class="form-group">
                    <label for="email">Email address</label>
                    <input ng-model="signinForm.userEmail" name="userEmail" type="email" class="form-control" id="email" placeholder="Enter email" required />
                    <div
                                ng-show="signin_form.$submitted || signin_form.userEmail.$touched">
                                <span ng-show="signin_form.userEmail.$error.required">Enter your
                                    email.</span> <span ng-show="signin_form.userEmail.$error.email">This
                                    is not a valid email.</span>
                            </div>
                  </div>
                  <div class="form-group">
                    <label for="password">Password</label>
                    <input ng-model="signinForm.userPassword" name="userPassword" type="password" class="form-control" id="password" placeholder="Password" required />
                    <div
                                ng-show="signin_form.$submitted || signin_form.userPassword.$touched">
                                <span ng-show="signin_form.userPassword.$error.required">Enter your
                                    password.</span>
                            </div>
                  </div>
                  <button ng-disabled="signin_form.$invalid || !userloginbtn" ng-model="signin" ng-click="userSignin()" type="submit" class="btn btn-primary">Submit</button>
                </form>
              </modal>
        </div></body></html>

Now i can show the popup when click on sign in button. When i submit the form i couldn't get the values of email and password values from the pop up form in controller. what is my mistake of using the scope. Please any one help me.

Upvotes: 0

Views: 405

Answers (2)

Vishwajeet Sawant
Vishwajeet Sawant

Reputation: 44

With a quick overlook, it seems a silly mistake. Change your lines

From

angular.module('mint', ['ngAnimate', 'toastr']);

To

angular.module('mintmygold', ['ngAnimate', 'toastr']);

Upvotes: 1

goreorto
goreorto

Reputation: 302

You are using scope: true which means your directive is creating a child scope and inheriting the properties from its parent. Therefore any property you define in the directive scope does not exists on you controller scope.

Changing form name=signin_form for form name=$parent.signin_form or scope: false should fix the problem

I didn't test this though. And it's not a good solution. I would probably create a service that launches the pop-up and returns a promise that gets resolved/rejected accordingly.

app.js

var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, modal) {
  $scope.launch = function(){
    modal.show().then(function(user){
      console.log(user)
    }, function(err){
      console.log(err)
    });  
  }


});

app.factory('modal', ["$document", "$compile", "$rootScope", "$templateCache", "$timeout", "$q",
  function ($document, $compile, $rootScope, $templateCache, $timeout, $q) {
    var $body = $document.find('body');

    return {
      show: function(){
        var defer = $q.defer(),
            child = $rootScope.$new();

        child.user = {};

        child.close = function(){
          defer.reject('canceled');
          tpl.remove();
        }

        child.submit = function(){
          defer.resolve(child.user);
          tpl.remove();
        }

        var tpl = angular.element($templateCache.get('modal.html'));
        $compile(tpl)(child);
        $body.append(tpl);

        return defer.promise;
      }
    };

}]);

index.html

<script type="text/ng-template" id="modal.html">
    <div class="modal in" style="position: static; display: block">
      <div class="modal-dialog">
        <form ng-submit="submit()" class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" ng-click="close()" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <h4 class="modal-title">Modal title</h4>
          </div>

          <div class="modal-body">
              Email: <input ng-model="user.email"></input><br>
              Password: <input ng-model="user.password"></input>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-default" ng-click="close()">Close</button>
            <button type="submit" class="btn btn-primary">Sign in</button>
          </div>
        </form>
      </div>
    </div>
</script>
<button type="button" ng-click="launch()" class="btn btn-primary">Show modal</button>

Plunker

This is just a proof of concept. I think is enough to get you started. I'd strongly recommend to checkout UI Bootstrap and the way the implement their modal

Upvotes: 0

Related Questions