Angular Js two way binding - angularjs

I have few text boxes and would like to implement the simple calculation like:
Value of (TextBox1 + TextBox2 + textBox3) = Value of TextBox4.
(TextBox4 + TextBox5)= value of TextBox6
How can achieve this in AngularJS?
See below for an example:
<table ng-app="" ng-controller="acadController">
<tr ng-repeat="x in semone">
<td>{{ x.SubjectName }}</td>
<td>{{ x.Credit }}</td>
<td><input type="number" ng-model="pt1" /></td>
<td><input type="number" ng-model="pt2"/></td>
<td><input type="number" ng-model="ia"/></td>
<td><input type="number" value="{{pt1+pt2+ia}}" ng-model="semMarks" class="marks_catotal" /></td>
<td><input type="number" ng-model="endSemMarks" class="marks_endsem" /></td>
<td><input type="text" class="marks_total" value="{{ semMarks + endSemMarks }}"/></td>
</tr>
<table>

You can use use $scope.watch to watch those variables and their sum and if it changes add it to $scope.marks
$scope.$watch('pt1 + pt2', function(v) {$scope.marks = v;});
See this plnkr: http://embed.plnkr.co/p0rQkUBMfEmYZkKh4Nrt/

You can use the $watch function to react to user changes :
Inside your controller, you can fire a function when a value is modified.
function calculateResult(){
$scope.semMarks = $scope.pt1 + $scope.pt2 + $scope.ia;
}
$scope.$watch('pt1', calculateResult);
$scope.$watch('pt2', calculateResult);
Instead of your watch, you could also have registered a function that will be fired directly when you modify a value :
$scope.calculateResult = calculateResult;
And then, inside your view, you would just have to call this function when an input is modified.
<td><input type="number" ng-model="pt2" ng-change="calculateResult()"/></td>
Most of the time, using an event consumes less processor than using a $watch. Angular evaluates every $watch and check if there were any changes during each $digest cycle. Angulars uses also a lot of $watches itself, so adding too much $watches can significally decrease performances.

Consider introducing a controller for endSemMarks and marks_total.

You should simply bind to a function that evaluates the sum of the values. As mentioned above, $watch is more expensive and a little harder to understand.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.tb1 = 0;
$scope.tb2 = 0;
$scope.tb3 = 0;
$scope.tb5 = 0;
$scope.sum123 = function() {
return $scope.tb1 + $scope.tb2 + $scope.tb3;
}
$scope.sum45 = function() {
return $scope.tb1 + $scope.tb2 + $scope.tb3 + $scope.tb5;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="plunker" ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<div>1 :
<input type="number" ng-model="tb1">
</div>
<div>2 :
<input type="number" ng-model="tb2">
</div>
<div>3 :
<input type="number" ng-model="tb3">
</div>
<div>4 :
<input type="number" ng-value="sum123()">
</div>
<div>5 :
<input type="number" ng-model="tb5">
</div>
<div>6 :
<input type="number" ng-value="sum45()">
</div>
</body>

Related

Why does this ng-model variable not work?

So I'm trying to create a program in Angular for displaying train schedules. Here's my question, why does the "firstTT" variable break the program?
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<div ng-app = "myApp" ng-controller = "myCtrl">
<table>
<tr><th>Train Name</th><th>Destination</th><th>Frequency</th><th>Minutes Away</th><th>Next Arrival</th><th></th></tr>
<tr ng-repeat="x in trainArray">
<td>{{ x.name }}</td>
<td>{{ x.dest }}</td>
<td>{{ x.freq }}</td>
<td></td>
<td></td>
<td>X</td>
</tr>
</table>
{{dayMinutes}}
<form>
Train Name: <input type = "text" ng-model = "name"/>
<br>
<br>
Destination: <input type = text" ng-model = "dest"/>
<br>
<br>
First Train Time: <input type="text" placeholder = "(ex. 08:45 for 8:45pm)" ng-model = "firstTT">
<br>
<br>
Frequency (Minutes): <input type="text" style = "width: 50px;" ng-model = "freq">
<br>
<br>
<input type = "submit" value = "submit" id = "submit" data-toggle = "tool-tip" title = "add train">
</form>
</div>
<script>
var dayMillis = moment().diff(moment().startOf('day'));
//minutes since start of day
var dayMinutes = dayMillis/60000;
//why the hell does it say this is "not defined" and break the program?
// console.log(firstTT);
//regardless, I need to get the diff between this and the start of the day.
//that should look something like this:
// var startMinutes = moment(firstTT, "hh:mm").diff(moment().startOf('day'));
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope){
$scope.firstTT = "";
$scope.dayMinutes = dayMinutes;
$scope.trainArray = [
{
name: "Thomas",
dest: "New York",
first: "05:00",
freq: 30
},
{
name: "Duncan",
dest: "Boston",
first: "06:00",
freq: 45
}]
})
</script>
</body>
</html>
It claims the variable is undefined, and that causes all the AngularJS to cease to function. I tried adding the "init" and the "$scope", but that didn't work. What's the deal?
The variable firstTT is indeed undefined, you never declare it. It seems that you are expecting firstTT to be the value of the input field where you have declared ng-model="firstTT". In angularjs the model part of the model-view-controller is a $scope, this means that ng-model="firstTT" binds to $scope.firstTT which can only be accessed in your controller implementation.
My guess is that you would like to calculate startMinutes when the value in the input field changes, to do this you need to do a couple of things.
First implement a method which can be called when the input value changes, you must do this on the $scope so that you can bind the method in the view.
$scope.onFirstTrainTimeChange = function() {
var startMinutes = moment($scope.firstTT, "hh:mm").diff(moment().startOf('day'));
};
Then use the ng-change directive on your input field to call the method above when the input changes.
<input ... ng-model="firstTT" ng-change="onFirstTrainTimeChange()">
You may also want to do other things, like handle errors when the input is not in the correct format, and use the ng-model-options directive to control when the model gets updated (e.g. debounce) so that the method isn't called until the user stops making changes to the input field.

How to get values of current table row's html controls on button click?

Not getting the values of table row's HTML controls after binding the table by angularjs ng-repeat, by below code
$(".btnAddToCartClass").click(function () {
var item = $(this).closest("tr").find(".ddlCategoryClass").val();
var itemQty = $(this).closest("tr").find(".txtQuantityClass").val();
var itemCondition = $(this).closest("tr").find(".chkUrgentClass").is(':checked');
alert(item + ' ' + itemQty + ' ' + itemCondition);
});
<table id="TblAdminDash">
<tbody ng-repeat="IL in ItemsListForOrder">
<tr>
<td ng-bind="IL.ItemName"></td>
<td>
<select class="ddlCategoryClass" id="ddlCategory"
ng-model="ddlCategory">
<option value="" disabled>Select Category</option>
<option value="DryClean">Dry Clean</option>
</select>
</td>
<td>
Qty
<input id="txtQuantity" class="txtQuantityClass"
type="number" max="10000" min="1" value="1" />
</td>
<td>
<input type="checkbox" id="chkUrgent" ng-model="chkUrgent"
class="chkUrgentClass"/> Urgent
</td>
<td>
<input type="button" class="btnAddToCartClass" value="Add"/>
</td>
</tr>
</tbody>
</table>
I tried by jquery like above before binding its worked as expected but after bind the table its not working..
Use the ng-click directive to specify a function in the controller to add the item:
<tbody ng-repeat="IL in ItemsListForOrder">
<tr>
<!-- ... -->
<td>
<input type="button" class="btnAddToCartClass" value="Add"
ng-click="addItem(IL) />
</td>
</tr>
</tbody>
JS
$scope.addItem = function(item) {
console.log(item);
//...
};
For more information, see
AngularJS ng-click Directive API Reference
I need clicked button's current rows other Html control values like I getting mentioned jquery code.
Bind the model to the ng-repeat iterator:
<tbody ng-repeat="IL in ItemsListForOrder">
<tr>
<td>
<input type="checkbox" id="chkUrgent" ng-model="IL.chkUrgent"
class="chkUrgentClass"/> Urgent
</td>
<!-- ... -->
</tr>
</tbody>
$scope.addItem = function(item) {
console.log(item);
console.log(item.chkUrgent);
//...
};
New AngularJS developers often do not realize that ng-repeat, ng-switch, ng-view, ng-include and ng-if all create new child scopes, so the data hiding problem often shows up when these directives are involved. (See this example for a quick illustration of the problem.)
This issue with primitives can be easily avoided by following the "best practice" of always have a '.' in your ng-models – watch 3 minutes worth. Misko demonstrates the primitive binding issue with ng-switch.
For more information, see
What are the nuances of scope prototypal / prototypical inheritance in AngularJS?
I got it by like below
<input type="button" class="btnAddToCartClass"
data-ng-click="AddToCart($event)" value="Add" />
$scope.AddToCart = function (event) {
var item = $(event.target).closest("tr").find(".ddlCategoryClass").val();
var itemQty = $(event.target).closest("tr").find(".txtQuantityClass").val();
var itemCondition = $(event.target).closest("tr").find(".chkUrgentClass").is(':checked');
alert(item + ' ' + itemQty + ' ' + itemCondition);
};

AngularJS dynamic form input with fieldset via ng-repeat

Please click on the demo below
www.jsfiddle.net/rnnb32rm/1370
My problem is: "Add input" is working fine. But whenever i invoke "Add
Fields", the subsequent field will be sync with the first one. I want
the subsequent to be filled with only one input. Stuck for hours already. Please guide!
Picture to illustrate:
May be help you.
var app = angular.module("app",[]);
app.controller("MyCtrl" , function($scope){
$scope.data ={
items:[{ name:"",family:"",age:""}]
};
$scope.addRow = function(index){
var item = { name:"",family:"",age:""};
if($scope.data.items.length <= index+1){
$scope.data.items.splice(index+1,0,item);
}
};
$scope.deleteRow = function($event,item){
var index = $scope.data.items.indexOf(item);
if($event.which == 1)
$scope.data.items.splice(index,1);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="MyCtrl">
<table>
<tr ng-repeat="name in data.items track by $index">
<td> <input type="text" ng-model="data.items[$index].name"></td>
<td> <input type="text" ng-model="data.items[$index].family"></td>
<td> <input type="text" ng-model="data.items[$index].age"></td>
<td> <input type="button" ng-click="addRow($index)" value="Add" ng-show="$last"></td>
<td> <input type="button" ng-click="deleteRow($event,name)" value="Delete" ng-show="$index != 0"></td>
</tr>
</table>
<span>{{data|json}}</span>
</div>
I answered this the first time you posted this question, but you deleted it.
You only have one choices array, and you are using it over and over:
$scope.addNewChoice = function() {
// ...
// Same array each time
$scope.choices.push({'id':'choice'+newItemNo});
};
<fieldset data-ng-repeat="choice in choices2">
<div data-ng-repeat="choice in choices "> <!-- Same array each time -->
You probably want one array for each entry in the choices2 array.
Also, both of your ng-repeat elements use the same variable name (choice) which is confusing.

AngularJS: Iterating over object properties and two way binding

I want to loop over an object's property. Also, there should be a two-way data binding so that any change will change the Object as well.
Both key and value of the object property can be changed from UI and should reflect in the object's structure.
I am able to do it for object's value with ng-model="contents[index]"
but how to do that with object property key e.g. interface in the object will change if I change it on UI.
$scope.contents = {
"interface": "GigabitEthernet",
"interfaceNumber": "1",
"BGPneighborIp": "00.0.112.499",
"BGPremoteAs_[1]": "701",
"BGPneighborIp_[2]": "8.3.112.170",
"BGPremoteAs_[2]": "702"
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<tbody>
<tr ng-repeat="(index, p1) in contents">
<td>
<input class="form-control" type="text" ng-model="index">
</td>
<td>
<input class="form-control" type="text" ng-model="contents[index]">
</td>
</tr>
</tbody>
Try this solution:
angular.module('app',[]).controller('test',['$scope', function($scope){
$scope.contents = {
"interface": "GigabitEthernet",
"interfaceNumber": "1",
"BGPneighborIp": "00.0.112.499",
"BGPremoteAs_[1]": "701",
"BGPneighborIp_[2]": "8.3.112.170",
"BGPremoteAs_[2]": "702"
};
$scope.arr = [];
for(var prop in $scope.contents)
$scope.arr.push({oldKey:prop, newKey:prop});
$scope.change = function(item){
$scope.contents[item.newKey] = $scope.contents[item.oldKey];
delete $scope.contents[item.oldKey];
item.oldKey = item.newKey;
}
}])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app' ng-controller='test'>
<input ng-repeat-start='item in arr' type='text' ng-model="item.newKey" ng-change='change(item)'>
<input type='text' ng-model="contents[item.oldKey]" >
<br ng-repeat-end>
<p>{{contents|json}}</p>
</div>

How to watch ng-model included in ng-repeat?

This is my html code:
<table>
<tr ng-repeat="park in parkOptions.parks">
<td>
<label for="{{park.park_id}}">
<input id="{{park.park_id}}" type="radio" name="connection" ng-model="$parent.currentPark" value="{{park.park_id}}" ng-click="selectValue('park',park)"/>{{park.park_name}}
</label>
</td>
</tr>
</table>
How can i watch the changes in my model( I mean i want to see in $watch another park when i click radio button)
I've got a working version to help you - Fiddle.
HTML
<div ng-app ng-controller="ParentCtrl">
<div ng-controller="ChildCtrl">
<table>
<tr ng-repeat="park in parkOptions.parks">
<td>
<label for="{{park.park_id}}">
<input id="{{park.park_id}}" type="radio" name="connection" ng-model="parkOptions.currentPark" value="{{park.park_id}}" ng-click="selectValue(park)"/> {{park.park_name}}
</label>
</td>
</tr>
</table>
</div>
</div>
JS
function ParentCtrl($scope) {
}
function ChildCtrl($scope) {
$scope.parkOptions = {};
$scope.parkOptions.parks = [
{park_id: '01', park_name: 'England Park'},
{park_id: '02', park_name: 'France Park'}
];
$scope.$watch('parkOptions.currentPark', function(newValue) {
if (newValue != undefined) {
console.log(newValue);
}
});
}
This may not be exactly what you want (as I see $parent in your code) but we can come to the right solution with any further information from you.
I don't use $parent and prefer sending and receiving events.

Resources