0

I am new to angularjs. I tried to create 2 different modules in an single js file and them manually bootstrap one of them to a element. This was suggested in one of the stackoverflow questions. But this doesnot seem to work. Both of the modules work fine independently. I am not sure what is going wrong here. Here's my code :-

myApp.js

var app = angular.module("myApp", []);
var myController = app.controller("ctrl1", function($scope){
"use strict";
$scope.fname = "Bill";
$scope.lname = "Goldberg";
$scope.updatevalue = function () {
    $scope.fullname = $scope.fname + $scope.lname;
    //$scope.fname = "newName"
};
});
app.directive("w3TestDirective", function() {
    "use strict";
    return {
        template : "<h1>This is my life!</h1>"
    };
});

var loginController = angular.module('loginController', []);
loginController.controller('loginCntrl', function ($scope) {
"use strict";
$scope.username="email";
$scope.password="password";
$scope.present = false;
$scope.login = function () {
    "use strict";
    if ($scope.username == "Amar" & $scope.password == "Amar") {
        $scope.present=true;
        $scope.loginMessage = "logged in successfully";
    } else {
        $scope.present=true;
        $scope.loginMessage = "Invalid username or password";
    }
}
});

angular.bootstrap(document.getElementById("loginDiv"),['loginController']);

Index.html

<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<!--script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular-route.js"></script-->
<script src="scripts/services/myApp.js"></script>
<!--script src="scripts/services/login.js"></script-->
<body>

  <div  id="demoDiv" ng-app="myApp" ng-controller="ctrl1">
    <span>Values:</span>
    <input type="text" ng-model="fname"/>
    <input type="text" ng-model="lname"/>
    <button ng-click="updatevalue()">fullname</button>
    <br></br>
    {{ fullname }}
    <br></br>
    <w3-test-directive></w3-test-directive>
  </div>
  <br></br>
  <div id="loginDiv" ng-app="loginController" ng-controller="loginCntrl">
    <input type="text" ng-model="username"/>
    <input type="text" ng-model="password"/>
    <button ng-click="login()">submit</button>
    <br></br>
    <div ng-if="present"> {{ loginMessage }} </div>
  </div>

</body>
</html>
Amar Dev
  • 1,360
  • 2
  • 18
  • 38
  • An update, the first div with the angular behaviour works i.e. div with id demoDiv works, but the one that is manually bootstrapped doesnot – Amar Dev Dec 03 '16 at 16:30
  • It should be specified what 'does not work' means. But likely the problem is that `angular.bootstrap` is executed before page load was completed. It should be also noticed that multiple bootstrapping isn't a common practice and should be used only when the dev knows what he/she's doing very well (in practice it is almost never). The fact that you're 'new to angularjs' suggests that you probably doing it the wrong way. – Estus Flask Dec 03 '16 at 17:04
  • My BAD!!!! the binding doesnot work, The 2nd div doesnot show angular behaviour, I get {{ loginMessage }} in the browser. But the first div works well and shows angular behaviour – Amar Dev Dec 03 '16 at 17:19
  • Always check the console, the answer is there. Again, in 99,9% of cases there should be a single app instance. – Estus Flask Dec 03 '16 at 17:28
  • why are you trying to do it this way? besides the fact that it is an extremely bad practice to run two angular apps on a single page (and they can't communicate between each other anyway), you can't manually bootstrap angular **and** add `ng-app` (x2!) at the same time, you can only use one or the other. – Claies Dec 03 '16 at 17:38
  • also, can you provide the link to the question where someone suggested that you should bootstrap a second app, so I can go downvote it? :) – Claies Dec 03 '16 at 17:40
  • I got it from here http://stackoverflow.com/questions/18571301/angularjs-multiple-ng-app-within-a-page – Amar Dev Dec 03 '16 at 17:47
  • I'm not *really* going to downvote that question (though maybe I should), since it was posted in 2013, and this may have been a valid practice with that framework version. It is usually pretty important to note **when** an answer is posted, since frameworks change so fast, but angular changes ***very*** frequently, so it's a lot more important to not pay attention to answers that are nearly 4 years old. I posted a proposed solution that should adhere to the modern standards. – Claies Dec 03 '16 at 17:55

3 Answers3

0

This is the completely wrong approach. You CAN have your controllers in more than one module, but you should always have a single module which is the main parent for the app.

Let's Assume myApp is your parent module, and make some changes:

First, move the ng-app to the body element:

<body ng-app="myApp">

  <div  id="demoDiv" ng-controller="ctrl1">
...

Next, remove ng-app from the loginDiv:

<div id="loginDiv" ng-controller="loginCntrl">

Finally, inject the loginController module into the myApp module:

var app = angular.module("myApp", ['loginController']);

Now, the app will be able to attach both controllers without issue.

http://plnkr.co/edit/rkFY0ASCHaQUTByaHJg3?p=preview

Claies
  • 22,124
  • 4
  • 53
  • 77
0

I fixed my issue with the following code :-

var app = angular.module("myApp", ['utilModule','loginModule']);
var myController = app.controller("ctrl1", function($scope){
"use strict";
$scope.fname = "Bill";
$scope.lname = "Goldberg";
$scope.updatevalue = function () {
    $scope.fullname = $scope.fname + $scope.lname;
    //$scope.fname = "newName"
};
});
app.directive("w3TestDirective", function() {
    "use strict";
    return {
        template : "<h1>This is my life!</h1>"
    };
});


<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<!--script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular-route.js"></script-->
<script src="scripts/services/myApp.js"></script>
<script src="scripts/services/util.js"></script>
<script src="scripts/services/login.js"></script>
<body ng-app="myApp">

  <div  id="demoDiv" ng-controller="ctrl1">
    <span>Values:</span>
    <input type="text" ng-model="fname"/>
    <input type="text" ng-model="lname"/>
    <button ng-click="updatevalue()">fullname</button>
    <br></br>
    {{ fullname }}
    <br></br>
    <div ng-controller="utilCntrl">
      {{ test }}
    <testDirective></testDirective>
    </div>
    <w3-test-directive></w3-test-directive>
  </div>
  <br></br>
  <div id="loginDiv" ng-controller="loginCntrl">
    <input type="text" ng-model="username"/>
    <input type="text" ng-model="password"/>
    <button ng-click="login()">submit</button>
    <br></br>
    <div ng-if="present"> {{ loginMessage }} </div>
  </div>

</body>
</html>

There is only 1 issue, the testDirective tag doesnot print anything on the browser. but that is not a requirement, so I will just ignore this for the time being. I realize that this is what @Claies has posted. Claies, Thank you very much for your time and effort.

Amar Dev
  • 1,360
  • 2
  • 18
  • 38
0

You can't use the ng-app directive and angular.bootstrap function to bootstrap you angular application. You either use ng-app or angular.bootstrap.

If you have two modules "myApp" and "loginController" like you do in your app, you must make "loginController" a dependency of "myApp". "myApp" will be your angular application module that you can add more dependencies, external or custom.

angular.module('myApp', ['loginController', 'ui-router', 'etc'...])
coderdark
  • 1,481
  • 14
  • 30
  • You are right btinoco, I figured this out and wired my application the right way. Thanks for taking the time out to respond to this question.Much appreciated!!!! – Amar Dev Dec 04 '16 at 13:01