I have this module routes:
var mainModule = angular.module('lpConnect', []).
config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/home', {template:'views/home.html', controller:HomeCtrl}).
when('/admin', {template:'views/admin.html', controller:AdminCtrl}).
otherwise({redirectTo:'/connect'});
}]);
Home HTML:
<div ng-include src="views.partial1"></div>
partial1
HTML:
<form ng-submit="addLine()">
<input type="text" ng-model="lineText" size="30" placeholder="Type your message here">
</form>
HomeCtrl
:
function HomeCtrl($scope, $location, $window, $http, Common) {
...
$scope.views = {
partial1:"views/partial1.html"
};
$scope.addLine = function () {
$scope.chat.addLine($scope.lineText);
$scope.lines.push({text:$scope.lineText});
$scope.lineText = "";
};
...
}
In the addLine
function $scope.lineText
is undefined
, this can be resolved by adding ng-controller="HomeCtrl"
to partial1.html
, however it causes the controller to be called twice. What am I missing here?
As @Renan mentioned, ng-include creates a new child scope. This scope prototypically inherits (see dashed lines below) from the HomeCtrl scope.
ng-model="lineText"
actually creates a primitive scope property on the child scope, not HomeCtrl's scope. This child scope is not accessible to the parent/HomeCtrl scope:To store what the user typed into HomeCtrl's $scope.lines array, I suggest you pass the value to the addLine function:
In addition, since lineText is owned by the ngInclude scope/partial, I feel it should be responsible for clearing it:
Function addLine() would thus become:
Fiddle.
Alternatives:
ng-model="someObj.lineText
; fiddlelineText
property on the HomeCtrl $scope:ng-model="$parent.lineText"
; fiddleIt is a bit involved to explain why the above two alternatives work, but it is fully explained here: What are the nuances of scope prototypal / prototypical inheritance in AngularJS?
I don't recommend using
this
in the addLine() function. It becomes much less clear which scope is being accessed/manipulated.Instead of using
this
as the accepted answer suggests, use$parent
instead. So in yourpartial1.html
you'll have:If you want to learn more about the scope in
ng-include
or other directives, check this out: https://github.com/angular/angular.js/wiki/Understanding-Scopes#ng-includeI've figured out how to work around this issue without mixing parent and sub scope data. Set a
ng-if
on the theng-include
element and set it to a scope variable. For example :In your controller, when you have set all the data you need in your sub scope, then set show to
true
. Theng-include
will copy at this moment the data set in your scope and set it in your sub scope.The rule of thumb is to reduce scope data deeper the scope are, else you have this situation.
Max
This is because of
ng-include
which creates a new child scope, so$scope.lineText
isn’t changed. I think thatthis
refers to the current scope, sothis.lineText
should be set.