AngularJS - change scope of HTML element to new scope - javascript

I am learning AngularJS and doing some freaking experiments to clear by concepts about scope, directives and dom.
AIM : Change the scope of HTML element <div id="grocery"> to newly created child scope'
index.html
<html ng-app="eggly" ng-controller="rootCtrl">
<body>
<div id="grocery">
{{box}}
</div>
</body>
</html>
rootCtrl
eggly.controller('rootCtrl',function($scope,$timeout,$compile){
$scope.box = "lunchbox"; --> first assign box = lunchbox
$timeout(function(){
//delete $scope;
var newScope = $scope.$new(); --> create a new scope
newScope.box = "dinnerbox"; ---> Assign new value
$compile($('#grocery'))(newScope); --> compile div with new scope
//newScope.$apply(); --> I think $timeout already do $apply so commented out
},1000);
});
My issue is:
If I do not create new scope and do not $compile in $timeout function then my view is updated with dinnerbox as I am expecting
If I create new scope and $compile in $timeout function then my view shows me old value i.e lunchbox however chrome console show me angular.element($0).scope().box shows me dinnerbox in scope (after $timeout execution).
What I am doing wrong?

When $compile is being called, #grocery contents are lunchbox and not {{ box }}. At this moment ng-controller directive was already linked and binding information is not available as plain HTML.
This shortcoming can be overcome by using directive substitute to {{ }} binding:
<div id="grocery"><span ng-bind="box"></span></div>

Related

ng-controller within an include that is within another controller potential scope issue

I am using node and angularjs. I have a frame like page inside an ejs that is passed content to load into the includes dynamically.
<div ng-app="thisApp">
<div ng-controller='MainCtrl'>
{{ firstMessage }}
<div id='contentFromNode' ng-include='<%= pageContent %>'></div>
</div>
</div>
<script>
var thisApp = angular.module('thisApp', []);
thisApp.controller('MainCtrl', [ '$scope', function($scope) {
$scope.firstMessage = "Main Controller Working Fine";
}])
</script>
and then the passed content might be just an html page containing something like this:
<div ng-controller='NestedCtrl' id='content-type-container'>
{{ nestedMessage }}
</div>
<script>
thisApp.controller('NestedCtrl', [function(){
var nested = this;
nested.nestedMessage = "Nested Won't Work";
}])
</script>
So I have tried $scope within the NestCtrl instead of referencing this, I have tried moving the script tag above and below (ideally this get separated eventually anyway). I have tried aliasing the controllers, however my problem is the in registration of the controller itself as I get that great Error: [$controller:ctrlreg] error. The page is loading the content fine? Any ideas what I am doing wrong here?
Seems JQlite doesn't support this. You have to include jquery or lazy load the script. Refer
AngularJS: How to make angular load script inside ng-include?

Which element does myVar bind to? Problems with `ng-init` [duplicate]

This question already has answers here:
What are the nuances of scope prototypal / prototypical inheritance in AngularJS?
(3 answers)
Closed 5 years ago.
I'm wondering what's happening behind the scenes when using ng-init.
Sometimes ng-init does some unexpected things, and I have a hard time debugging.
Let's say I have the following structure:
<!-- App -->
<div ui-view>
<!-- Component -->
<custom-component>
<!-- Transcluded component -->
<transcluded-component>
<!-- Controller -->
<div ng-controller="MyCtrl">
<!-- Element -->
<div ng-init="myVar = 'hello'">
{{myVar}}
</div>
</div>
</transcluded-component>
</custom-component>
</div>
Which element does myVar bind to?
Edit 2017-07-21: Added an example
In the following template block (especially within an ng-repeat), I may use an ng-init:
<span ng-init="path = getPath()">
<a ng-if="path" ng-href="path">
Click here
</a>
<span ng-if="!path">
Some text
</span>
</span>
In this case, I skipped a function call twice, and kept my template clean.
Sometimes ng-init does some unexpected things, and I have a hard time debugging.
The ng-init directive evaluates an Angular Expression in the context of the scope of its element. Numerous directives (ng-repeat, ng-controller, ng-if, ng-view, etc.) create their own scope.
For more information, see
AngularJS Developer Reference - scopes
AngularJS Wiki - Nuances of Scope Prototypical Inheritance
Avoid using ng-init
Avoid using ng-init. It tangles the Model and View, making code difficult to understand, debug and maintain. Instead initialize the Model in the controller.
From the Docs:
ngInit
This directive can be abused to add unnecessary amounts of logic into your templates. There are only a few appropriate uses of ngInit, such as for aliasing special properties of ngRepeat, as seen in the demo below; and for injecting data via server side scripting. Besides these few cases, you should use controllers rather than ngInit to initialize values on a scope.
— AngularJS ng-init Directive API Reference
Update
Q: I've also added an example of a code block I sometime use.
<!-- Controller -->
<div ng-controller="MyCtrl">
<!-- Element -->
<div ng-init="myVar = 'hello'">
{{myVar}}
</div>
</div>
To do the equivalent initialization in the controller:
app.controller("MyVar", function($scope) {
this.$onInit = function() {
$scope.myVar = 'hello';
};
});
By separating concerns of Model and View, the code becomes easier to understand, debug and maintain.

Scope of ngController doesn't update with ngInclude

Here is a Plunker: http://plnkr.co/edit/F6QM4KUU8DPNq6muInGS?p=preview
Including an html file with ng-include, having set the ng-controller in the same tag, doesn't update the controller's scope models. Using the ng-model directly inside of the html works perfectly fine, and also setting the controller inside of the included html file is working. But ng-include together with ng-controller $scope.models don't update and stay as they are.
For whatever reason if you set the model inside of the controller, it is done suring it's loading. But having a method setting the model (not included in the plunker) only changes the mdoel inside of the controller's scope and not the html one.
Also if I use an ng-include in the scope of another controller and want to access the included models return undefined or the value you set the model to. Calling methods from the included html works fine in both cases, but they can't really operate as the values are wrong.
I saw that a similar issue has already been postet and should have been resolved (https://github.com/angular/angular.js/issues/4431), but as you can see in the plunker for me it doesn't.
Do I miss something, or is this a problem of angular?
Kind Regards,
BH16
PS: Here is the code from the Plunker:
index.html - body
<body ng:controller="MainCtrl">
<input type="text" ng:model="input">{{input}} {{getInput()}}
<div ng:include="'main2.html'" ng:controller="Main2Ctrl"></div>
</body>
main2.html
<div>
<input type="text" ng:model="input2">{{input2}} {{getInput2()}}
</div>
script.js
angular.module('testApp', [])
.controller('Main2Ctrl', function($scope) {
$scope.input2 = 1234;
$scope.getInput2 = function() {
console.log("input2");
return $scope.input2;
};
})
.controller('MainCtrl', function($scope) {
$scope.input = 1234;
$scope.getInput = function() {
console.log("input");
return $scope.input;
}
});
For all of those who are are also having this issue: Just use the controllerAs syntax: http://toddmotto.com/digging-into-angulars-controller-as-syntax/
This solves all of the issues above and simplifies the code A LOT!
This is the basic idea of controllerAs (taken from the site above):
<div ng-controller="MainCtrl as main">
{{ main.title }}
<div ng-controller="AnotherCtrl as another">
Scope title: {{ another.title }}
Parent title: {{ main.title }}
<div ng-controller="YetAnotherCtrl as yet">
Scope title: {{ yet.title }}
Parent title: {{ another.title }}
Parent parent title: {{ main.title }}
</div>
</div>
</div>
It's related to that ng-include creates it's own scope.
To see what's actually happens you can try plugin(for google chrome, probably something similar exists for others browser's too): "AngularJS Batarang", it will include additional tab to dev tools.
And possible solution will be:
main2.html:
<div ng:controller="Main2Ctrl">
<input type="text" ng:model="input2"> {{input2}} {{getInput2()}}
</div>
http://plnkr.co/edit/daIehNjxWdam3NyH3ww4?p=preview

AngularJS doesnt "bootstrap" new DOM elements

I have an AngularJS app which (reduced to relevant parts) looks like this:
<div ng-app="myModule">
<div id='container'>
<div say-hello-to name="Frank">f</div>
<div say-hello-to name="Billy">b</div>
</div>
</div>
the application works fine. Now, if after the angular bootstrapping process, I add a new dom element, which corresponds to a directive, it isn't interpreted. Note that the "Addition" is done by non-angularjs JavaScript Code.
<div say-hello-to name="Dusty">d</div>
it is just "dead" div.
JsFiddle Link: http://jsfiddle.net/Nn34X/
The question is: How can I add a new DOM Element into the application and let AngularJS know that there is a new Element to be interpreted (I could easily point angularjs exactly to all inserted elements)
Cheers, and thanks in Advance!
Retrieve the $injector service:
var $injector = angular.element(document.querySelector('#container')).injector();
Select the element:
var element = angular.element(document.querySelector('[name="Dusty"]'));
Use the $injector service to retrieve the $compile service and link the element to the scope:
$injector.invoke(function ($compile) {
var scope = element.scope();
$compile(element)(scope);
});
Demo: http://jsfiddle.net/6n7xk/
Short explanation: Call Angular JS from legacy code

AngularJS - ng-include ng-controller and scope not binding

I have the following main view
<div ng-include="'otions.html'"></div>
and options.html has the following
<div ng-controller="OptionsController">Options</div>
<input type="text" ng-model="keyword" value="{{keyword}}" />
<button ng-click="search()">Search</button>
But "keyword" is not binding to the scope in OptionsController.
app.controller('OptionsController',
['$scope', function($scope) {
$scope.keyword = "all";
$scope.search = function() {
console.log("hello")
};
}]);
when I click on the button, I don't see hello and the keyword all doesn't appear in the input text.
I tried moving the ng-controller part as follows
<div ng-controller="OptionsController" ng-include="'otions.html'"></div>
And things work as expected.
I read through the answers in AngularJS - losing scope when using ng-include - and I think my problem is related, but just need some more explanation to undertstand what's going on.
You should write options.html like this:
<div ng-controller="OptionsController">Options
<input type="text" ng-model="keyword" value="{{keyword}}" />
<button ng-click="search()">Search</button>
</div>
OptionsController should be put in the outer html element.
i have face same problem,
Under main tag it will be work fine but, When bind some data to nav.html it not work.
find this link
AngularJS - losing scope when using ng-include
inside include its work child scope.
better option to create custom directive its easy solution

Categories

Resources