I'm trying to use a custom control to get contenteditable elements in Angular as described in this example. However, I also need to use a controller which causes the contenteditable portion of the code to fail even if my controller is completely empty.
This Plunker shows the desired behavior, but does not include the controller.
<body ng-app="myApp">
<div>
<h1 contenteditable ng-model="test">123</h1>
<textarea ng-model="test"></textarea>
</div>
</body>
This Plunker shows the addition of the controller to the div on line 10 of the HTML file, however the desired behavior from the first Plunker is no longer there.
<body ng-app="myApp">
<div ng-controller="mainController">
<h1 contenteditable ng-model="test">123</h1>
<textarea ng-model="test"></textarea>
</div>
</body>
You have to explicitly register a controller with the app - global controller functions are not allowed by default:
.controller("mainController", function mainController($scope){
});
This is now the default option in Angular v1.3+
(of course, you have other issues with binding to untrusted HTML, but that's a different story)
Related
First, ng-app should be to set the area where angular take place, right? Even if there is ng-controller tag outside ng-app, they should be omitted?
However, when I test on jsfiddle (link here), it seems this is not the case:
HTML
<div ng-app="myApp">
<div ng-controller="MyCtrl">
Hello, {{name}}!
<input ng-model="name">
</div>
</div><br><br>
<div class="not-inside-my-app">
<div ng-controller="MyCtrl">
...... Some Many other content in real case that I don't want angular to touch .......<br>
So this is to test angular is not working here.<br>
Hello, {{name}}!
<input ng-model="name">
</div>
</div><br><br>
<div ng-app="myApp">
<div ng-controller="MyCtrl2">
Hello, {{name}}!
<input ng-model="name">
</div>
</div>
Javascript
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', ['$scope', MyCtrlFunction]);
function MyCtrlFunction($scope) {
$scope.name = 'Superhero';
}
myApp.controller('MyCtrl2', ['$scope', MyCtrlFunction2]);
function MyCtrlFunction2($scope) {
$scope.name = 'Non-superhero';
}
The angular code is still working in the middle div. Is my concept on ng-app wrong? Or what have I missed to limit the scope?
P.S. I know I can control the scope by using ng-controller, but it seems to be a waste on resource to do scanning on sections that I know I don't need angularJS.
Since ng-app attribute added to body tag, which is why all controllers are running.
Since angular considers first ng-app attribute and ignore other ng-app attributes. The above code is working.
NOTE: Though the code written in the html section didn't contain the body tag. You can able to insert the body tag by clicking on the gear icon in the html section of fiddle site. Which is what the main cause for this addition of ng-app attribute added to body tag. Thanks for pointing it out Durga
remove body tag <body ng-app="myApp"> from html section, there is no issue with jsfiddle.
It seems some issue with JS jsFiddle, try to run the same example in you local machine it will not work or here you get the answer:
https://www.w3schools.com/code/tryit.asp?filename=FEYVPGYHZAY5
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
I am including a view using the ngInclude directive. The included view has properties that binds values to $scope.model. This is a problem, since the parent scope is using $scope.model. What i need to do is to "reroute" the included views $scope.model to the parent scope's property $scope.include1.model. How can i do this "scope reroute" the way i want to?
Here is an example showing my problem
<div ng-controller="myCtrl">
<div ng-include="'input.html'"></div>
<div ng-include="'input.html'"></div>
</div>
<script type="text/ng-template" id="input.html">
<div ng-controller="childCtrl">
<input type="text" ng-model="model"/>
</div>
</script>
As you can see i have two includes to the same view, and both input text boxes will be bound to the same value. I want to bind them to different values in myCtrl
I can't make any changes to either my childCtrl or the included view.
You can try this
<div ng-include="'input.html'" ng-init='model=include1.model'></div>
<div ng-include="'input.html'" ng-init='model=include2.model'></div>
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
Hey all I'm trying to get a feel for angular and have ran into a little snag.
I have a container structure like the following:
<div class="main-container" ng-view>
<!-- The below divs are constantly being
reloaded based on the current URL and it's associated view -->
<div class="left-col">
</div>
<div class="right-col">
</div>
</div>
Before I implemented Angular I just had a simple script that would check the height of the window and set the height of the left column and right column divs accordingly.
With angular there is probably a better way to do this then attaching an event function to the window object. Basically I want to fire a function everytime a new view is rendered but not duplicate the below code in all of my angular controllers like so:
$scope.$on('$viewContentLoaded', setColumnHeight);
Any help would be appreciated. Thanks!
I've solved this problem in my app by having a root "Application Controller" at the top of the DOM tree. For example:
<body ng-controller='applicationController'>
...
<div class="ng-view"></div>
...
</body>
applicationController is always there, and can set up bindings on its scope when it is created.
How about putting that event listener on the root scope:
$rootScope.$on('$viewContentLoaded', setColumnHeight);
You could use something like this:
<div class="main-container" ng-view>
{{ setColumnHeight() }}
<!-- The below divs are constantly being
reloaded based on the current URL and it's associated view -->
<div class="left-col">
</div>
<div class="right-col">
</div>
</div>
and it will check the height every time a render is made, however, this seems to be a bit over processing.
The best approach would be to only update the height from both columns when the height of one of them changes. For that you could use DOM Mutation Observers, however they are not yet available on all browsers. If that's not a problem for you, check the mutation-summary lib.
If you are using jQuery you can also try this: https://github.com/jqui-dot-net/jQuery-mutate (examples here).