Reputation: 11
Contains application module
app.js
var appProfileDetails = angular.module('profileDetailsApp', [
'ngMaterial','ngAria','ngAnimate','ngRoute']);
It has the controller file
contactController.js
appProfileDetails.controller('contactController', function($scope) {
$scope.msg= function() {
alert($scope.emailId);
};
});
Html piece(Contact.jsp)
<div ng-app="profileDetailsApp">
<div style="float: left;margin-left: 50px;width: 45%;" ng-controller="contactController" >
<div ng-include="'/mm/resources/html/ContactDetails2.html'">
</div>
</div>
This file is included in above piece
ContactDetails2.html
<div>
<input type="email" ng-model="emailId"/>
<input type="button" ng-click="msg()"/>
</div>
Upvotes: 1
Views: 98
Reputation: 2158
Try using controllerAs syntax. ng-controller="contactController as contact"
And then in the ContactDetails2 template do ng-model="contact.emailId"
(and also change the ng-click
value to contact.msg()
.
It will also work if you instantiate the emailId as '' in contactController. $scope.emailId = ''
.
Let me explain what is going on here in simple terms.
The problem with angular's scoping is that it uses prototypical inheritance. Angular will create scopes from top to bottom.
So it will first create your controller and create a new scope for it. Then it encounters the ng-include which sadly creates a new inherited scope.
This means that it is a new scope object but the prototype (aka parent) is set to the parent scope. Whenever angular looks up something in that new scope for ng-include it'll check does it exist on my local scope, if not, does it exist on the parent scope, and so on until it reaches the $rootScope.
The problem is that ng-model checks to see if emailId is present on the local scope. It can't find it on the local scope. It looks to the parent scope but it also can't find it there. Therefore it will create it LOCALLY. And that is why the parent scope does not have emailId present.
So, either guaranteeing it is already present on the controller (as then ng-model would work on the correct variable immediately) or using controller as fixes the problem. Using controllerAs syntax is definitely recommended as it avoids all similar problems without having to think about it.
Why does controllerAs work? because when it creates the scope for the controller it does so on a new scope with a property on it. In my suggestion it'll create "contact". Now, when ng-model runs inside ng-include it'll check "do I have contact?" no. But my parent has. Does the parent's contact have an emailId? No, OK. Let me create it there and manipulate it on my parent scope.
Definitely learn how scopes work if you want to avoid problems with angular 1. I recommend following a styleguide like john papa's guide. It also explains why you should follow these rules.
Upvotes: 1
Reputation: 7072
The reason why it doesn't work is that ng-include creates a new child scope thus breaking the prototypical scope inheritance.
Must reads in order to better understand this issue:
As a good rule of thumb, always use controller as syntax. Here's why you should use it.
Upvotes: 1