accessing global variables in angular scope - javascript

In http://www.w3schools.com/angular/tryit.asp?filename=try_ng_repeat_object
instead of
<div ng-app="" ng-init="names=[
{name:'Jani',country:'Norway'},
{name:'Hege',country:'Sweden'},
{name:'Kai',country:'Denmark'}]">
Is there a syntax to refer to an external variable declared elsewhere in ng-init (and NOT declared in angularjs controller) as this one doesn't work:
<script>
var myNames = [
{name:'Jani',country:'Norway'},
{name:'Hege',country:'Sweden'},
{name:'Kai',country:'Denmark'}]
</script>
<div ng-app="" ng-init="names=myNames">
I know it's bad practice but I use another framework also and don't want to duplicate the content of the variable. And it's just for prototyping not code for real app.
Or else if I use ng-init initial declaration, can I refer it from another script variable ?

It will not work because of the following reasons
Script tag is for to the html document's javascript. It has no relationship with angular's ng-init directive.
The angular documentation about ngInit directive warns as shown below.
Best practise is to go with controllers when these kind of situations arises.
Updated as per the discussion in chat
<body>
<script>
var myNames = [
{name:'Jani',country:'Norway'},
{name:'Hege',country:'Sweden'},
{name:'Kai',country:'Denmark'}];
var app = angular.module('myApp',[]);
app.controller('myController',function($scope){
$scope.names=window.myNames;
});
</script>
<div ng-app="myApp" ng-controller="myController">
<p>Looping with objects:</p>
<ul>
<li ng-repeat="x in names">{{ x.name + ', ' + x.country }}</li>
</ul>
</div>
</body>

Related

How same variable is used for ng-bind and ng-model

I am exploring AngularJS1 and found something strange, please help me to find how name is working for both ng-bind and ng-model here.
Output is coming as :John Doe but it is working for same variable name with bind and model there it is confusing me.Please help me to understand.
<div ng-app="myApp" ng-controller="myCtrl">
<input ng-model="name">
<h1>{{name}}</h1><br>
<p ng-bind="name"></p>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.name = "John Doe";
});
</script>
They are all the same variable. You have $scope.name and you're telling ng-bind and ng-model to use $scope.name;
ng-model="name" <-- Angular looks on the scope object for a property called name. If it's there it uses it, if it's not, it'll create it.
ng-bind="name" <-- Angular looks on the scope for a property called name. Then uses that value.
Angular created a scope object for the div with ng-controller
<div ng-app="myApp" ng-controller="myCtrl">
<input ng-model="name">
<h1>{{name}}</h1><br>
<p ng-bind="name"></p>
</div>
All directives with-in that div's hierarchy can access the scope object.
If you Google "Understanding Angular scopes" or something similar you'll get a lot of articles on it.
http://blog.carbonfive.com/2014/02/11/angularjs-scopes-an-introduction/

ng-controller variable Vs ng-init vairable

For below code, using angularJS,
<script type="text/javascript">
angular.module('app').controller('add', ['$scope',function($scope) {
$scope.name = "Bonita Ln";
}]);
</script>
corresponding Javascript code to access $scope variable member name is,
<div ng-app="app" ng-controller="add">
<script type="text/javascript">
var dom_el = document.querySelector('[ng-controller="add"]');
var ng_el = angular.element(dom_el);
var ng_el_scope = ng_el.scope();
var name = ng_el_scope.name;
</script>
</div>
Below is the angular code, accessing ng-init variable name using angular expression,
<body ng-app="">
<div ng-init="name='Bonita Ln'">
{{name}}
</div>
</body>
How do I access the ng-init variable name using JavaScript?
you can do this by accessing variable $scope.name in your controller, but it has to be define inside your scope.
<div ng-init="name='Bonita Ln'">
{{name}}
<div ng-controller="MyCtrl">
Hello, {{name2}}!
</div>
</div>
angular.module('myApp',[]).controller('MyCtrl',function($scope) {
$scope.name2 = $scope.name;
})
this works, as you have define name in parent scope to controller, and is being inherited
but if for same controller html template will look like that:
<div ng-controller="MyCtrl">
<div ng-init="name='Bonita Ln'">
{{name}}
Hello, {{name2}}!
</div>
</div>
then it won't work, as variable was undefined when controller function was invoked
You could use it in exactly the same way, but you shouldn't.
I've downvoted your question because it is really really really bad practice, and I mean like every line of code you provided is bad practice.
I'm struggling trying to find out what you'd like to do, so I can't really provide you with better code to do so, but I can provide you with some links you must check out before continuing with whatever you're coding now.
Shaping up with Angular is a free codeschool course provided by the angular team, it is a really good course that will give you more insight on how to use angular than the phone-tutorial on the angular website.
Papa Johns Angular styleguide a great guide on how to write maintainable code.
thinkster.io a step by step guide to learn to master Angular
egghead.io a collection of good video tutorials
I know that my comment sounds quite harsh, but future you will thank you if you write more standardized Angular, and keep to a defined style-guide.
Also remember, in angular, your code should not know about the DOM, you don't need to specify eventListeners to DOM-elements, just use the appropriate directives like ng-click.
(yes I am aware that there can be exceptions to the rule)

Angularjs:ng model is not accessible

I am using ng-template in angularjs
<script type="text/ng-template" id="ng-wig/views/ng-wig.html">
<div class="ng-wig">
........
</div>
<script>
and i have a textarea using this ng-template.
<textarea ng-wig="content" ng-model="contents"></textarea>
but this ng-model cannot be accessed inside the controller.
please help.
As you are loading your textarea template inside ng-include, if you look at ng-include directive you will see that it does create a new scope which is prototypically inherited from the parent scope.
If you use any scope variable which are declared in controller won't be accessible inside the include div. In order to get the controller variable accessible inside ng-include the you must declare it as object like $scope.model= {} then you should declare the properties in it. like ng-mode="model.contents"
Markup
<textarea ng-wig="model.content" ng-model="model.contents"></textarea>
Controller
$scope.model = {};
Here you can find similar answer
There are several approaches apart from above by which you could solve this issue.
The other way around would be, you could use controller as approach in that way you can avoid. In that you need to use this inside a controller & use controller alias while showing variable on html like vm.contents here
Makrup
<div ng-controller="myCtrl as vm">
<div ng-include="'ng-wig/views/ng-wig.html'"></div>
</div>
Textarea
<textarea ng-wig="content" ng-model="vm.contents"></textarea>
Also you could point to the parent scope of ng-include which is nothing but controller scope just by doing $parent in your ng-model, this case your ng-model would be $parent.contents
Textarea
<textarea ng-wig="$parent.content" ng-model="$parent.contents"></textarea>
Note
Don't use this approach, use the 1st one which is more preferable.

How to pass an item from ng-repeat to a controller created/loaded by ng-include?

I have an ng-repeat that loads an ng-include. I'd like to have a separate controller inside the view that the ng-include loads.
But I'm having trouble accessing the item from ng-repeat in that controller. I tried something like this, and it fails.
How do I get at result inside of SubController?
<div ng-repeat="result in results">
<div class="box" ng-include="view/someinclude.html"></div>
</div>
view/someinclude.html:
<div ng-controller="SubController">
...
</div>
controller js:
angular.module('SubController', [])
.controller('SubController', ['$scope',
function ($scope) {
//fails
console.log($scope.result);
}
]);
Make sure your scopes are a part of the same module, or they they're different include one in the other, if that's not the problem then it'll be something outside what you've shown, as something like this:
angular.module("app").controller.(testController", ["$scope", function($scope){
console.log($scope.x)
}])
with:
<div ng-repeat = "x in [1,2]">
<div ng-include = "'./views/vew.test.html'">
</div>
</div>
and in vew.test.html:
<div ng-controller = "testController">
{{x}}
</div>
Will wack 1 and 2 on the screen and in the console.
Make sure you're using the same module:
angular.module('SubController').controller('SubController', function() {...});
Try using $parent.result instead of $scope.result inside your controller as ng-include creates a new scope of its own that prototypically inherits from its parent scope.

Multiple ng-app directives on a page

I want to be able to use multiple ng-app="{angular.module}" directives on one page. I want to do this to make the bits of my app more modular. I figure, if I can create angular modules and plug several of them into one document, I could take those modules and plug them into other projects easily.
I have seen people say that you can only use one ng-app directive on your page... is this true? Is it most accurate to say, "one ng-app directive per view"?
I hope this is not the case, or if it is the case that there is still a best way to achieve a high degree of abstract modularity.
Here are my modules/apps and their controllers...
var searchModj = angular.module('searchModule', []);
var controllers = {};
controllers.SearchList = function ($scope){
$scope.coworkers = [
{name: 'Joe Bob', city: 'Ukrainia'},
{name: 'Adam Blobnovski', city: 'Logan' },
{name: 'Carlos Sanchez', city: 'Deerbushle'},
{name: 'Martin Kellerweller', city: 'Uptown'},
{name: 'John Doe', city: 'New York City'}
];
};
searchModj.controller(controllers);
var fruitModj = angular.module('fruiter', []);
controllers.SomeFruit = function ($scope) {
$scope.fruits = ['apple', 'banana', 'pear'];
};
fruitModj.controller(controllers);
Ok, now here is the relevant part of my markup...
<div ng-app="searchModule">
<div ng-controller="SearchList">
Name:
<br/>
<input type="text" ng-model="name" />
<br/>
<ul>
<li ng-repeat="coworker in coworkers | filter:name">{{ coworker.name }} - {{ coworker.city }}</li>
</ul>
<p>You are searching for <em>{{ name }}</em></p>
</div>
</div>
<div ng-app="fruiter">
<div ng-controller="SomeFruit">
<ul>
<li ng-repeat="fruit in fruits">{{ fruits }}</li>
</ul>
</div>
</div>
I think because it comes first in the document, my "searchModule" app works and the second app does not. When I comment out the first app, the second works. So it looks like I'm confirming my most unfortunate suspicions. Regardless... if this is the case, then what is the best approach I can bear in mind to make the functionality on my projects as modular as possible?
you only want one ng-app on a page, but you can insert your other modules as dependencies of the main ng-app module.
var app=angular.module('myNgAppName', ['searchModule']);
This will expose any directives , controllers etc you have in your 'searchModule'
The limitations of the ngApp directive is just that, limitations of the directive, not AngularJS itself. Angular allow you to associate modules with multiple elements in a page, it even allows you to associate more than one module with each element.
Referencing other modules from you module will work. Another approach that will work is using the angular.bootstrap() method. See: https://stackoverflow.com/a/18583329/984780
Finally you can create a directive that works like ngApp without it's limitations. It would work exactly the way it does in your markup code. That's what I did you can get the code here:
http://www.simplygoodcode.com/2014/04/angularjs-getting-around-ngapp-limitations-with-ngmodule/
The directive is called ngModule. Here's a code sample:
<!DOCTYPE html>
<html>
<head>
<script src="angular.js"></script>
<script src="angular.ng-modules.js"></script>
<script>
var moduleA = angular.module("MyModuleA", []);
moduleA.controller("MyControllerA", function($scope) {
$scope.name = "Bob A";
});
var moduleB = angular.module("MyModuleB", []);
moduleB.controller("MyControllerB", function($scope) {
$scope.name = "Steve B";
});
</script>
</head>
<body>
<div ng-modules="MyModuleA, MyModuleB">
<h1>Module A, B</h1>
<div ng-controller="MyControllerA">
{{name}}
</div>
<div ng-controller="MyControllerB">
{{name}}
</div>
</div>
<div ng-module="MyModuleB">
<h1>Just Module B</h1>
<div ng-controller="MyControllerB">
{{name}}
</div>
</div>
</body>
</html>
Yes you only want one ng-app per page, but you can create other modules and declare them as dependencies of your main app.
var app=angular.module('appModule'); //resuable module
var app=angular.module('myApp', ['appModule']); //in the HTML ng-app="myApp"
So you can put re-usable stuff in appModule and use it in other projects. For example, I like to put my routing logic (i.e. re-routing users depending on their access levels) in a module that I reuse in other projects.
Note: You might want to look into $provider http://docs.angularjs.org/api/AUTO.$provide if you want to use data from your re-usable ("appModule") module inside the config method of your ng-app ("myApp") module.

Categories