I have two DIVs, each one is a self-contained user control or partial view, if I want one team to work on dog div, the other team work on fox div. can each team have their own angular module, controller, view, etc ? If yes, can you show me a code snippet?
another question: if I want to these two DIVs loosely coupled, what is the best angular way to let them communicate ?
<body ng-app>
<div id="dog">
<input type="text" ng-model="name"/> {{name}}
</div>
<div id="fox">
</div>
</body>
Thank you!
For other new ng developer's reference, this is the final code, if you have better solution, please feel free to improve it.
<body ng-app="airborneApp">
<div id="dog" ng-controller="dogController">
<input type="text" ng-model="name" /> {{name}}
</div>
<div id="fox" ng-controller="foxController">
<input type="text" ng-model="name" /> {{name}}
</div>
<script>
angular.module('airborneApp', ["dogCompany", "foxCompany"]);
angular.module('dogCompany', []).
controller('dogController', ['$scope', function ($scope) {
$scope.name = 'hello dog';
}]);
angular.module('foxCompany', []).
controller('foxController', ['$scope', function ($scope) {
$scope.name = "hello fox";
}]);
</script>
</body>
You can make as many modules as you can, you just have to reference all of them as a dependency in you main App module definition (and load them in correct order)
app
angular.module('myApp', ['firstModule', 'secondModule'])
modules
angular.module('firstModule', []) // empty array as a second parameter creates new module instead of using existing one
.controller(...)
.directive(...)
angular.module('secondModule', [])
.controller(...)
.directive(...)
For communication between different modules, the simplest way is to inject $rootScope into all controllers.
But preferred way is to create a service in main app module, which will be injected into both modules
angular.module('myApp')
.factory('SharedData', function() {
var a = {},
b = {};
return {
a: a,
b: b
}
})
and then use it
angular.module('firstModule')
.controller('something', function($scope, SharedData) {
SharedData.a.data = 'new data';
})
angular.module('secondModule')
.controller('something else', function(SharedData) {
console.log(SharedData.a.data); //will output 'new data'
})
each div can have a separate controller using:
<div ng-controller="firstCtrl"></div>
<div ng-controller="secondCtrl"></div>
for the other part of your question see:
What's the correct way to communicate between controllers in AngularJS?
Related
I am having trouble with something very simple like inject a basic service into a controller and despite reading documentation and other SO question i really don't see the mistake i'm making.
Here's my simplified code:
angular.module ('travelApp', ['ui.bootstrap', 'ngRoute'])
//CONTROLLERS
.controller('searchController', ['$scope','myParams', function ($scope,ngRoute,myParams){
$scope.place = myParams.place;
$scope.$watch('place', function(){
myParams.place = $scope.place;
});
$scope.bind = function(){
console.log(myParams.getPlace);
};
}])
//SERVICES
.service('myParams', function(){
this.place = 'start';
});
//MY HTML
<div class="container" ng-app="travelApp">
<div class="jumbotron" id="searchPage" ng-controller="place">
<div>
<h3>Start Here</h3>
<input type="text" class="form-control" id="searchBar" ng-model="place">
<a type="button" class="btn btn-default" ng-click="bind()">bind data</a>
</div>
</div>
I have tried a number of things in the past few hours but keep getting the
"TypeError: Cannot set property 'place' of undefined"
It seems the service is just no available inside the controller, i don't know if it has something to do with routing but i doubt so.
Can someone please point me in the right direction?
Here is a Plunker
Your dependencies must match if you use array syntax. Remove ngRoute from the controller's arguments.
.controller('searchController', ['$scope','myParams', function ($scope, myParams){
I'm in a project that uses angularjs and rails. So, i'm using this library too:
https://github.com/FineLinePrototyping/angularjs-rails-resource
Well, when i'm using the controller as syntax from angularjs, some strange behaviour is happening. You can see that in this plunker example:
http://plnkr.co/edit/i4Ohhh8llS7WN68sLX5q?p=preview
The promise object returned by the remote call in first controller using the angularjs-rails-resource library in some way is setting the instance variable that belongs to the second controller. I don't know if it is a bug in the library, or an angular behaviour that i should know. Anyway, is clearly an undesirable behaviour.
Here is the same plunker code (index.html):
<!doctype html>
<html ng-app="Demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.js"></script>
<script src="https://rawgit.com/FineLinePrototyping/dist-angularjs-rails-resource/master/angularjs-rails-resource.min.js"></script>
<script src="example.js"></script>
</head>
<body>
<div ng-controller="Controller1 as ctrl1">
<form>
<label>should appear first remote</label>
<input type="text" ng-model="ctrl1.remote.name"/><br>
<label>should appear first local</label>
<input type="text" ng-model="ctrl1.local.name"/>
</form>
</div>
<br>
<div ng-controller="Controller2 as ctrl2">
<form>
<label>should appear second local</label>
<input type="text" ng-model="ctrl2.remote.name"/><br>
<label>should appear second local</label>
<input type="text" ng-model="ctrl2.local.name"/>
</form>
</div>
</body>
</html>
My angularjs code (example.js):
angular.module('Demo', ['rails']);
angular.module('Demo').controller('Controller1', ['$scope', 'Remote', function($scope, Remote) {
ctrl = this;
ctrl.remote = {};
Remote.get().then(function(remote) {
ctrl.remote = remote;
});
ctrl.local = {};
ctrl.local.name = "first local";
}]);
angular.module('Demo').controller('Controller2', ['$scope', function($scope) {
ctrl = this;
// SAME VARIABLE NAME
// WILL RECEIVE VALUE FROM REMOTE CALL ON FIRST CONTROLLER!!!
ctrl.remote = {};
ctrl.remote.name = "second local";
// SAME VARIABLE NAME
ctrl.local = {};
ctrl.local.name = "second local";
}])
angular.module('Demo').factory('Remote', [
'railsResourceFactory',
'railsSerializer',
function (railsResourceFactory, railsSerializer) {
return railsResourceFactory({
url:'clients.json',
name: 'remote',
})
}]
);
clients.json
{
"name":"first remote"
}
Any ideias how fix this without having to change variable names to avoid conflict? Because that way we will just mask the problem.
I report the problem to angularjs-rails-resource library but no answer until now.
You need to use var when declaring your variables, otherwise they're global.
Use
var ctrl = this; instead of just ctrl = this;
Also, 'use strict' is a nice thing to use(and it helps in these situations)
<body ng-app="myApp">
<div ng-controller="myCntlr">
Enter First Name: <input type="text" ng-model="frn" />
<br />
Enter First Name: <input type="text" ng-model="lrn" />
<br />
Full name: {{FullName()}}<br />
</div>
<script>
var myApp = angular.module('myApp', []);
myApp.controller('myCntlr', ['$scope', function ($scope) {
$scope.frn ="Jitendra";
$scope.lrn = "Rajput";
$scope.FullName = function () {
return $scope.frn + " " + $scope.lrn;
}
}]);
</script>
</body>
-
Here i am writing a function to display full name dynamicaly.Its working fine but i am not able to understand that what is the role of $scope??
$scope is the execution context for your expressions, objects and functions, see https://docs.angularjs.org/guide/scope
AngularJS will invoke the controller with a $scope object.
In AngularJS, $scope is the application object (the owner of application variables and functions).
for more:
Is this the correct way of doing it? The main disadvantage is that I have to do this on each form and controller.
I have one form and want to access that form by storing a variable in a controller variable and then access it in my controller.
In my view im doing this:
<form name="formName">
<div ng-init="setForm(formName);" />
</form>
And in my controller i got
$scope.setForm = function (form) {
$scope.myForm = form;
}
Now after doing this I have a controller variable which is $scope.myForm.
The form will automatically be available via $scope, no need to explicitly save it.
If you however need to log it at controller initialization you need to wait for Angular to have processed it.
HTML:
<body ng-controller="MyController">
<form name="formName">
</form>
</body>
JS:
app.controller('MyController', function($scope, $timeout) {
$scope.$evalAsync(function() {
console.log($scope.formName);
});
});
Demo: http://plnkr.co/edit/wGPKKIGjlQ6Q4GT0aAC6?p=preview
Here is the jsfiddle.
http://jsfiddle.net/CLcfC/
code
var app = angular.module('app',['']);
app.controller('TestCtrl',function($scope){
$scope.text = 'Change Me';
$scope.$watch('text',function(){
alert('Changed !');
});
})
HTML
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="TestCtrl">
<input type="text" ng-model='text'/>
<span>{{text}}</span>
</div>
</div>
I am not able to see the change in $scope.text. Please help.
This is so easy but what am I missing?
Change the module creation to this, make sure you don't put a empty string in the []. (Obvious the empty string is not a module that can be injected.)
var app = angular.module('app', []);
Demo: http://jsfiddle.net/MWa66/
Your JavaScript file loads after the AngularJS initialization and that's why it fails to find your module. In order to fix it change the initialization to a manual initialization.
First change your HTML and remove the ng-app directive:
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<div id="appRoot">
<div ng-controller="TestCtrl">
<input type="text" ng-model='text'/>
<span>{{text}}</span>
</div>
</div>
Then go to your JavaScript and use angular.bootstrap method to manually attach your module:
var app = angular.module('app',[]);
app.controller('TestCtrl',function($scope){
$scope.text = 'Change Me';
$scope.$watch('text',function(){
alert('Changed !');
});
});
angular.element(document).ready(function() {
angular.bootstrap(document.getElementById('appRoot'), ['app']);
});
You can find more help on manual AngularJS initialization here.
Thank you! I solved this annoying thing!
The solution that worked for me was that I use angular UI router and there I had used the following code
.state('app.monimes', {
url: "/monimes",
views: {
'menuContent' :{
templateUrl: "templates/monimes.html",
controller: 'sampleCtrl'
}
}
})
so then in the controller I had
/***
*
*Controller for tests..
*/
.controller('sampleCtrl',['$scope','sampleService', function($scope, $sampleService) {
$scope.username="em";
// Watch for changes on the username property.
// If there is a change, run the function
$scope.$watch('username', function(newUsername) {
// uses the $http service to call the GitHub API
// //log it
$scope.log(newUsername);
// and returns the resulting promise
$sampleService.events(newUsername)
.success(function(data, status, headers) {
// the success function wraps the response in data
// so we need to call data.data to fetch the raw data
$scope.events = data.data;
});
},true);
}
]);
and in the view I had
<div>
<label for="username">Type in a GitHub username</label>
<input type="text" ng-model="username" placeholder="Enter a GitHub username, like a user" />
<pre ng-show="username">{{ events }}</pre>
</div>
but that didn't work.
so I added ng-controller="sampleCtrl"
to the div and now it works :D
so that means that the view is loaded after the controller loads and the watcher doesn't get added to the watching variable.