18

I was reading this article on Angular validation and thought it would be good to use in my own project. It's working really well and I'd like to extend it accessing methods in other controllers upon successful validation of the form. I've tried various ways of doing this but I can't seem to see the methods in the $scope object.

<!DOCTYPE html>
<html>
  <head>
    <link data-require="bootstrap-css@3.0.0" 
      data-semver="3.0.0" 
      rel="stylesheet" 
      href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" />
    <script data-require="angular.js@1.0.8" 
      data-semver="1.0.8" 
      src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
    <script src="rcSubmit.js"></script>
    <script src="loginController.js"></script>
    <script src="loginApp.js"></script>
  </head>

  <body>
    <div class="container">
      <div class="row">
        <div class="col-xs-12 col-sm-6 col-sm-offset-3">
          <h1>Simple Login Form</h1>
          <form name="loginForm" novalidate 
            ng-app="LoginApp" ng-controller="LoginController" 
            rc-submit="login()">
            <div class="form-group"
              ng-class="{'has-error': rc.loginForm.needsAttention(loginForm.username)}">
             <input class="form-control" name="username" type="text" 
              placeholder="Username" required ng-model="session.username" />
             <span class="help-block" 
              ng-show="loginForm.username.$error.required">Required</span>
            </div>
            <div class="form-group"
              ng-class="{'has-error': rc.loginForm.needsAttention(loginForm.password)}">
              <input class="form-control" name="password" type="password" 
                placeholder="Password" required ng-model="session.password" />
              <span class="help-block" 
                ng-show="loginForm.password.$error.required">Required</span>
            </div>
            <div class="form-group">
              <button type="submit" class="btn btn-primary pull-right" 
                value="Login" title="Login">
                <span>Login</span>
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>
  </body>
</html>

I was hoping that someone can tell me what I'm missing in order to make this work. I've forked a plunkr.

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
user686483
  • 1,584
  • 6
  • 18
  • 29
  • Could you be a little bit more precise about what you're trying to achieve? I don't understand how sharing methods between controllers is related to validation. Usually the way to go with validation is building a directive and accessing the model-controller. – hugo der hungrige Jan 30 '14 at 11:55
  • Hi Hugo, I'm wanting to access some methods I have in a shared service. The service is working fine for other controllers but when I try to use it with this validation code I can access the methods. For instance in the code below how would I be able to access the methods in my service? I've tried everything you can think off but I still get undefined. // define controller for login var LoginController = ['$scope', function ($scope) { $scope.session = {}; $scope.login = function () { // process $scope.session alert('logged in!'); }; }]; – user686483 Feb 01 '14 at 00:30

2 Answers2

47

The proper way to do this would be with an angular service. For example:

app.factory('svc', function () {
    var msg="original...";
    return {
        setMessage: function(x) {
            msg=x;
        },
        getMessage: function() {
            return msg;
        }
    };
});

This way you can access the fucntions inside svc in any controller that you inject svc into:

app.controller("ctrl1",function($scope,svc,$timeout){
  $scope.someText=svc.getMessage();
  $scope.$watch("someText",function(v){
    svc.setMessage(v);
  });
});

app.controller("ctrl2",function($scope,svc){
  $scope.msg=svc.getMessage();
  $scope.$watch(svc.getMessage,function(v){
    $scope.msg=v;
  });
});

See this demo plunk (I ignored that plunk you provided because it had a lot of noise).

EDIT

Executing the service method and form validation are not really related to each other, see plunk.

EDIT

If you want to use the services or controllers of one app inside another, just reference the dependencies in your main app and call the services defined in your main app inside your second app. If your main app is called demoApp1, then you could create another app called dempApp2 and reference demoApp1 in demoApp2 and use any services defined in demoApp1 inside demoApp2. See the plunk I've updated it to demonstrate what you're asking.

fernandopasik
  • 9,565
  • 7
  • 48
  • 55
Mohammad Sepahvand
  • 17,364
  • 22
  • 81
  • 122
  • Hi Mohammad, thanks for answering the question so quickly. I'l give the service a try and let you know how I get on. – user686483 Jan 30 '14 at 10:15
  • Hi Mohammad, The service works fine and I'm able to share methods across the application but U still can't see those methods in the validation controller. Any ideas? – user686483 Feb 01 '14 at 01:09
  • 1
    I don't understand what you mean by seeing the methods in the validation controller? – Mohammad Sepahvand Feb 01 '14 at 05:05
  • I would like to call a service method once the form has been validated , from here: // define controller for login var LoginController = ['$scope', function ($scope) { $scope.session = {}; $scope.login = function () { // process $scope.session alert('logged in!'); }; }]; – user686483 Feb 01 '14 at 22:24
  • @user686483 I still don't fully understand what you mean, but I've changed the plunk to call the service method only when the form is valid. See the updated the plunk. – Mohammad Sepahvand Feb 02 '14 at 11:17
  • Hi Mohammad, I think that the solution that you posted works for an app that has controllers and services in the same app. In my question there are different apps and controllers throughout the application. This means that if I include the service reference in the app and pass it to the controller I get undefined. – user686483 Feb 05 '14 at 00:30
  • I tried exactly that and nothing worked for me. I ended up just having a regular js function that's called onsubmit. The function picks up the service methods and allows me to execute them. Thank you very much for all you help. – user686483 Feb 06 '14 at 20:29
3

The best approach for you to communicate between the two controllers is to use events.

Scope Documentation

In this check out $on, $broadcast and $emit.

In general use case the usage of angular.element(catapp).scope() was designed for use outside the angular controllers, like within jquery events.

Ideally in your usage you would write an event in controller 1 as:

$scope.$on("myEvent", function (event, args) {
   $scope.rest_id = args.username;
   $scope.getMainCategories();
});

And in the second controller you'd just do

$scope.initRestId = function(){
   $scope.$broadcast("myEvent", {username: $scope.user.username });
};

Can you try including the firstApp module as a dependency to the secondApp where you declare the angular.module. That way you can communicate to the other app.

EpokK
  • 38,062
  • 9
  • 61
  • 69
  • 1
    In your example second controller must be child of the first controller. Also if your first controller is not presented on the page, nothing happens. – Vladimir Prudnikov Jun 22 '16 at 08:03