Variable defined in controller not available in the html - angularjs

I'm trying to access variables defined in my Angular Controller in an html file using this controller. But they're not there. Here's my code:
In MapsController:
angular.module('Maps').controller('MapsController', ['$scope', '$location', 'MapsService', function($scope, $location, MapsService) {
$scope.number = 5;
... ...
}]);
In Search.html:
<div class="generic-container" ng-controller="MapsController as ctrl">
number: {{ctrl.number}}
</div>
When I run this, number is always empty. What am I missing?
(This is obviously a simplified version. In fact I'm trying to access an array that gets populated by the database. But it seems like in principal the idea is the same.)

Using contoller as syntax (MapsController as ctrl) you tell angular to assign the controller instance to scope's variable ctrl. So add you property number to the controller instead of scope.
Change $scope.number = 5; to this.number = 5; and it will work.

You are using the controller wrong in html
<div class="generic-container" ng-controller="MapsController as ctrl">
number: {{ctrl.number}}
</div>
this will not work because you don't need to create an alias for a Controller in html.
<div class="generic-container" ng-controller="MapsController">
number: {{ctrl.number}}
</div>
Also to access any variable in the scope of controller, you don't need to specify the controller object to access it.
<div class="generic-container" ng-controller="MapsController">
number: {{number}}
</div>
it should do the job.

Related

AngularJS | Handling $broadcast & $on for specific instance of the same controller

I have a utility controller build to manage documents attachments for reusing across my application.
<div ng-controller="someController">
<div ng-controller="documentController as temp1"></div>
<div ng-controller="documentController as temp2"></div>
</div>
Under the parent controller i.e. someController I have a broadcast method..
var module = angular.module("MyModule");
module.controller("someController",
function ($scope) {
$scope.$broadcast("callSomeFunctionInDocumentsController");
});
module.controller("documentController",
function($scope) {
$scope.$on("callSomeFunctionInDocumentsController", function() {
//do something here
});
});
Now the problem I am facing is that since the documentController is added twice to the view, the $on method is executed twice as well. Whereas based on some condition I would want to call the $on method either in temp1 or temp2 instance and not both.
I am not sure if what I wish to achieve is possible but any help will be much appreciated.
Thanks.
The $broadcast works simply: everyone who registered is notified through $on.
In your example, both controllers are registered.
So why do you use the same controller twice? Maybe worth to switch to component?
What about this one:
<div ng-controller="someController">
<div ng-controller="documentController as temp1"></div>
<div ng-if="oneCtrlGotNotification" ng-controller="documentController as temp2"></div>
</div>
where oneCtrlGotNotification is some flag (maybe under $rootScope).
So you will display second controller only when 1st already notified.
But it is a workaround.
One approach is to give a unique id to each element with a controller:
<div ng-controller="someController">
<div id="temp1" ng-controller="documentController as temp1"></div>
<div id="temp2" ng-controller="documentController as temp2"></div>
</div>
Then use the $attrs local to differentiate:
app.controller("documentController", function($scope, $attrs) {
$scope.$on("callSomeFunctionInDocumentsController", function() {
if ($attrs.id == "temp1") {
//do something specific to "temp1" controller
});
});
})
For more information, see
AngularJS Comprehensive Directive API Reference - controller
AngularJS $attrs Type API Reference

Is it valid to have form name "<controller_as_identifier><dot><namespaced_form_name>"

So, the code like this:
<form ng-controller="MyCtrl as myCtrl"
name="myCtrl.form">
<button type="button"
ng-click="myCtrl.logScope()"
>log scope</button>
</form>
...
controller('MyCtrl', [
'$scope',
function($scope) {
var vm = this;
vm.logScope = function() {
console.log($scope);
}
....
}]);
Outputs to console that the form was published successfuly under $scope.myCtrl.form. So, does anyone use such syntax, is it intended / valid to do this way? Angular 1.5
when you use ContrllerAs syntax, you assign all your contoller logic to viewmodel
they put the (vm) varible defined under $scope .
the thing to use controllerAs or the use just scope is that
when you use $scope you attach new varibles under .
using var vm=this
you attach the whole varible under $scope
It is absolutely valid as you can see from th screenshot.

Programmatically creating new instances of a controller

So here is my problem, I have some functions/variables in a parent controller
function parentController($scope) {
$scope.numberOfChildren = $scope.numberOfChildren + 1 || 1;
console.log($scope.numberOfChildren);
$scope.someFunction = function(argument) {
// do stuff
$scope.someVariable = result of the function
}
}
I am calling this controller in two other controllers that are directives controllers and are called in the same view
function firstChildController ($scope, $controller) {
var aVariable = 1;
$scope.otherVariable = 10;
$controller('parentController', {$scope: $scope});
$scope.someFunction(aVariable);
}
function secondChildController ($scope, $controller) {
var aVariable = 6;
$scope.otherVariable = 11;
$controller('parentController', {$scope: $scope});
$scope.someFunction(aVariable);
}
What I want, is not to share the parent scope for the two children.
Right now, there is only one instance of the parent controller and so when I call two directives depending on it on the same view, I get $scope.numberOfChildren === 2.
What I want is this parent controller to be loaded twice but have separated scopes ($scope.numberOfChildren === 1 in each child controller)
I managed to do this using ng-controller in the view template and deleting the $controller calls but I want to do it programmatically. (I don't want to have to write the same ng-controller code each time I am calling the directive).
<div ng-controller="parentController">
<first-directive></first-directive>
</div>
<div ng-controller="parentController">
<second-directive></second-directive>
</div>
Finally, to keep homogeneity in the code of the project, I'd rather not use the this and vm stuff to do the job if it possible.
parentController does NOT have its own scope, it operates on the $scope you're passing to it when you instantiate it this way $controller('parentController', {$scope: $scope}).
Checkout this simple demo fiddle.
The problem in your case might be caused by directives sharing the same scope and, thus, passing the same scope to the parent controller.
What you expect is exactly same with the way system run: scope is not sharing between two controller.
When you use a ng-controller in html, a new scope (controller instance) will be created. From your code above, two controller instance will be created. You can see it by adding {{$id}} to html and see id of scope instance.
<div ng-controller="parentController">
{{$id}}
<first-directive></first-directive>
</div>
<div ng-controller="parentController">
{{$id}}
<second-directive></second-directive>
</div>
If you see {{numberOfChildren == 2}} mean that your code is wrong in somewhere, not by sharing scope issue.

Angularjs: parent and child scope

point 1
i just do not understand why i could not access child controller property this way {{$scope.parentcities}}. but if i write like this way {{parentcities}} then it is working. so why we can not write $scope dot and then property name
<div ng-app ng-controller="ParentCtrl">
<div ng-controller="ChildCtrl as vm">
{{$parent.cities}}
<br>
{{$scope.parentcities}}
</div>
</div>
function ParentCtrl($scope) {
$scope.cities = ["NY", "Amsterdam", "Barcelona"];
}
function ChildCtrl($scope) {
$scope.parentcities = $scope.$parent.cities;
}
point 2
need some guide line what kind of syntax it is ChildCtrl as vm ?
when we need to mention controller in html ChildCtrl as vm like this way ?
does it carry any special meaning?
looking for some guidance. thanks
Well, the point of $scope is that you don't need to write it when you bind values to the view. So $scope.supervalue = 'Hallo' will be accessed in the view like this {{ supervalue }}. That's it.
$parentis a keyword from the Angular framework to reference the parent scope.
The controllerAs syntax is made to get rid of the $scope keyword alltogether. So inside the controller, you can write it like this:
var self = this;
self.supervariable = 'Hallo';
In your config for this route, you specifiy controllerAs: 'vm'. So you can access your values in the view via {{ vm.supervariable }}. Have a look here to learn all about it.
But, it seems like you should do some groundwork first and learn about the basic Angular mechanism before you dive into controllerAs, which has some tricky parts to it later on.
As long as you are going to use Ctrl as c syntax please assign values to this variable
function ParentCtrl($scope) {
$scope.cities = ["NY", "Amsterdam", "Barcelona"];
}
function ChildCtrl($scope) {
this.parentcities = $scope.$parent.cities;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="ParentCtrl">
<div ng-controller="ChildCtrl as vm">
{{$parent.cities}}
<hr>
{{vm.parentcities}}
</div>
</div>

AngularJS: How can I assign values to main page from templates and show them?

In my mine file I have the div with ng-view and it is loaded with the some template. Inside the temp`late I have a button which will change the value.
after to click the button, I am trying to show the value in the index but I recieving a null value.
In index.html I could have something like:
<html>
...
<body ng-app="productsApp" ng-Controller="mycontroller">
<div ng-view></div>
{{value}}
</body>
</html>
In my controller I have something like
angular.module('productsApp').controller('ProductController',
['$scope', 'dataService', function ($scope, dataService) {
$scope.value;
$scope.button = function () {
$scope.value= "123";
};
}]);
The template could be something like:
<button ng-click="button">CHANGE</button>
How can I assign values to main page from templates and show them?
You need to beware which controller you set, the names have to match. Also beware of typos, even when typing fast ;). Also look into the function call. You forgot to use () at the end. And naming things a little bit better would be recommended to (I don't say my namings are the best, but calling a function button is not very readable).
HTML
<body ng-controller="MainCtrl">
<p>Value {{value}}!</p>
<button ng-click="btnPressed()">Change</button>
</body>
JS
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.value = "456";
$scope.btnPressed = function() {
$scope.value = 123;
}
});
The controllers name in this example is MainCtrl. You need to refer the correct name as well in your HTML (you mix mycontroller and ProductController).
Working Plnkr
http://plnkr.co/edit/tpl:8rFfZljYNl3z1A4LKSL2
You have defined $scope.button in ProductController which set $scope.value.
But this $scope.value is come under scope of ProductController and not available under scope of mycontroller which parent scope.Thats why you getting null value.
Define $scope.value and $scope.button in mycontroller.
Or better way is define this functionality in some factory and access it wherever needed.
Or define that function and variable in $rootScope like
$rootScope.value;
but it make this global.
or define like this
$scope.$parent.value;

Resources