Anish Jr Anish Jr - 1 month ago 5
AngularJS Question

Loose Scope in angular JS

I have a multiple tab Html page . On one tab i have add 3 input box and an add button. Whenever the add button is clicked the data to be added into a grid below. But scope is not accessing these variables. Attaching my code below :

<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>

<div ng-app="myApp" ng-controller="myCtrl">
<div id="tabs">
<ul>
<li ng-repeat="tab in tabs"
ng-class="{active:isActiveTab(tab.url)}"
ng-click="onClickTab(tab)">{{tab.title}}</li>
</ul>
<div id="mainView">
<div ng-include="currentTab"></div>
</div>
</div>
<script type ="text/javascript" id="one.tpl.html">
<div class="form-group">
<label class="col-md-2 control-label">Name</label>
<div class="col-md-4">
<input type="text" class="form-control" name="name"
ng-model="names" />{{name}}
</div>
</div>

<div class="form-group">
<label class="col-md-2 control-label">Employees</label>
<div class="col-md-4">
<input type="text" class="form-control" name="employees"
ng-model="employeess" />
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">Headoffice</label>
<div class="col-md-4">
<input type="text" class="form-control" name="headoffice"
ng-model="headoffices" />
</div>
</div>
<div class="form-group">
<div style="padding-left:110px">
<input type="button" value="Add" ng-click="addRow()" class="btn btn-primary"/>
</div>
</div>
<div>
<table class="table">
<tr>
<th>Name
</th>
<th>Employees
</th>
<th>Head Office
</th>
</tr>
<tr ng-repeat="company in companies">
<td>{{company.name}}
</td>
<td>{{company.employees}}
</td>
<td>{{company.headoffice}}
</td>
</tr>
</table>
</div>
</script>


<script type="text/ng-template" id="two.tpl.html">
<div id="viewTwo">
<h1>View Two</h1>
<p>Test 2</p>
</div>
</script>

<script type="text/ng-template" id="three.tpl.html">
<div id="viewThree">
<h1>View Three</h1>
<p>Test 3</p>
</div>

</script>
</div>






<script>


var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope) {


$scope.companies = [];



$scope.tabs = [{
title: 'One',
url: 'one.tpl.html'
}, {
title: 'Two',
url: 'two.tpl.html'
}, {
title: 'Three',
url: 'three.tpl.html'
}];



$scope.currentTab = 'one.tpl.html';


$scope.onClickTab = function(tab) {
$scope.currentTab = tab.url;
}
$scope.isActiveTab = function(tabUrl) {
return tabUrl == $scope.currentTab;
}


$scope.addRow = function(){
$scope.companies.push({ 'name':$scope.names, 'employees': $scope.employeess, 'headoffice':$scope.headoffices });

$scope.names='';
$scope.employeess='';
$scope.headoffices='';

}
});
</script>

<style>
#tabs ul {
list-style: none;
padding: 0;
margin: 0;
}
#tabs li {
float: left;
border: 1px solid #000;
border-bottom-width: 0;
margin: 3px 3px 0px 3px;
padding: 5px 5px 0px 5px;
background-color: #CCC;
color: #696969;
}
#mainView {
border: 1px solid black;
clear: both;
padding: 0 1em;
}
.active {
background-color: #FFF;
color: #000;
}
</style>
</body>
</html>


Following variables are not accessible in scope :

$scope.names
$scope.employeess
$scope.headoffices

Answer

That's because ng-template creates child scope, so you can basically do one of 2 things:

Example: https://plnkr.co/edit/sFkim5WwN5ffPsWtdcDP?p=preview

$scope.newRow = {
  names: '',
  employeess: '',
  headoffices: ''
}

And access them via the same prefix:

ng-model="newRow.employeess"

Explanation:

Scopes have common structure, where $parent property is the parent scope e.t.c up to $rootScope.

When you're using ng-template it creates a new child scope, so the values, assigned within it are stored in the child scope and not in $parent (your controllers scope). The values you're searching for are in child scope because ng-model works in current scope. So you need to make sure that ng-model knows which scope to write. It can be done via $parent parameter or within object. As for 2nd option - the reson is simple. Object value can't be assigned when object is undefined, so search goes to upper level and so on.