Angularjs allows data updates only for the first rows - angularjs

I have a code that displays three rows of information from json using angularjs.
Now I want if any values entered in the form inputs corresponding to that rows to replace the already existing values in the view for that rows.
Eg. In row 1 , I have value hello sub 1 for subcomment Variable. Now I want if I enter another values say New sub 1 in the form inputs on that, it will replace/updates the already existing values in the **angular view ** for that rows.
The problem with the code above is that it keeps on replacing/updating only the subcomment values of the first row each time a new subcomment is entered. irrespective of the save button that was clicked
I don't know whether problem is from in the line of code below
$scope.posts[index].comment[0].subcomment = subcomment;
below is the entire partially working code which keeps updating only the first row no matter which submit button that was clicked
html
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="test" ng-controller="testCtrl">
<div ng-repeat='post in posts'>
<b>Post Title:</b> {{ post.title }}
<div ng-repeat='comment in post.comment'>
<br>
<b>sub comment</b>: {{comment.subcomment}}
<div>
<table>
<tr>
<tr>
<td>Enter subcomment</td>
<td>
<input type='text' ng-model='subcomment' placeholder="Enter Value For subcomment and Save.">
</td>
</tr>
<tr>
<td> </td>
<td>
<input type='button' id='but_save' value='Save and Replace/Update' ng-click='setResponse4(post.id,1,$index,subcomment,comment.id)'>
</td>
<td>
<input type='button' style="display:none" ng-init='getComments1(comment.id,5)'>
</td>
</tr>
</table>
</div>
</div>
<hr style="width:100%;font-size:10">
</div>
</body>
js
var app = angular.module('test', []);
app.controller('testCtrl', function ($scope, $http) {
$scope.posts = [
{
"id": "1",
"title": "my first title.",
"comment": [
{
"subcomment": "Hello sub 1"
}
]
},
{
"id": "2",
"title": "my second title.",
"comment": [
{
"subcomment": "Hello sub 2"
}
]
},
{
"id": "3",
"title": "my third title.",
"comment": [
{
"subcomment": "Hello sub 3"
}
]
}
];
//initialize an arrays of comments
$scope.commenting = [];
$scope.setResponse4 = function (postid, type, index, subcomment, commentid) {
var subcomment = subcomment;
alert(subcomment);
$scope.posts[index].comment[0].subcomment = subcomment;
}
});
Screenshot is attached

The problem in your code is you have 2 ng-repeats and $index passes the index of the inner ng-repeat whereas you need the index of the outer ng-repeat if you modify your code to take the index of outer ng-repeat as following, it should solve your issue.
1) First add this ng-init to your outer ng-repeat
<div ng-repeat='post in posts track by $index' ng-init="outerIndex=$index">
2) use outerIndex in your save function
<input type='button' id='but_save' value='Save and Replace/Update' ng-click='setResponse4(post.id,1,outerIndex,subcomment,comment.id)'>
Demo

Yes as the code says, you are accessing only the specific index of the array and setting the 0th element value,
$scope.posts[index].comment[0].subcomment = subcomment;
in order to set all values you can use angular.forEach
angular.forEach($scope.posts[index].comment, function(value, key){
value.subcomment = subcomment;
}

Related

Angularjs permits update of a single(first) row for sub comments of each post

Angularjs having issues in updating each subcommets/subpost of inputted data.
I have a json file which contains two posts. The First Post contains ** three** subposts(subcomment) each with an update button. The second post contains two subpost(subcomment) each with an update button.
My intention was to allow user to input any values corresponding to each rows under each post so the new inputed data will replace the already existing data in the angular js view for that row.
The problem is that only the first row of each subcomment for that post gets updated when data is posted.
For instance in post 1, If you enter a value at the first row and submit, it will update the already existing {{comment.subcomment}} data of the first row. If you input on row 2 for the same post 1, it will update the first row of post 1 instead of second row of that post.
Some Stackoverflow scholars like NTP in the link below
Angularjs allows data updates only for the first rows
suggested solution that since the code has 2 ng-repeats and $index passes the index of the inner ng-repeat whereas one need the index of the outer ng-repeat. He concluded that if one modify code to take the index of outer ng-repeat as following, it should solve the issue.
1) First add this ng-init to your outer ng-repeat
<div ng-repeat='post in posts track by $index' ng-init="outerIndex=$index">
2) use outerIndex in your save function
<input type='button' id='but_save' value='Save and Replace/Update' ng-click='setResponse4(post.id,1,outerIndex,subcomment,comment.id)'>
But the solution above only updates first inputed values of the of the first subcomment row for each post.
If you input on row 2 for the same, it will update the first row of that post instead of second row of that post for which the button was clicked.
below is the code
js
var app = angular.module('plunker', []);
app.controller('MainCtrl', function ($scope) {
$scope.name = 'World';
$scope.posts = [
{
"id": "1",
"title": "my first post title.",
"comment": [
{
"subcomment": "post 1 subcomment 1", "status": "**working**"
},
{
"subcomment": "post 1 subcomment 2", "status": "**Not working**"
},
{
"subcomment": "post 1 sub comment 3", "status": "**Not working**"
}
]
},
{
"id": "2",
"title": "my second post title.",
"comment": [
{
"subcomment": "post 2 subcomment 1", "status": "**working**"
},
{
"subcomment": "post 2 subcomment 2", "status": "**Not working**"
}
]
}
];
$scope.setResponse4 = function (postid, type, index, subcomment, commentid) {
var subcomment = subcomment;
$scope.posts[index].comment[0].subcomment = subcomment;
}
});
html
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.5.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<div ng-repeat='post in posts track by $index' ng-init="outerIndex=$index">
<h3>
<b>Post ID: {{ post.id }}</b>
</h3>
<b>Post Title:</b> {{ post.title }}
<div ng-repeat="comment in post.comment ">
<br>
<b>sub comment</b>: {{comment.subcomment}},
<b>status</b>: {{comment.status}},
<div>
<table>
<tr>
<tr>
<td>Enter subcomment</td>
<td>
<input type='text' ng-model='subcomment' placeholder="Enter Value For subcomment and Save.">
</td>
</tr>
<tr>
<td>
{{outerIndex}}
</td>
<td>
<input type='button' id='but_save' value='Save and Replace/Update' ng-click='setResponse4(post.id,1,outerIndex,subcomment,comment.id)'>
</td>
<td>
<input type='button' style="display:none" ng-init='getComments1(comment.id,5)'>
</td>
</tr>
</table>
</div>
</div>
<hr style="width:100%;font-size:10">
</div>
</body>
</html>
In order to access the elements of your comments array you need the index of your inner ng-repeat, Try the following.
1) modify your setResponse4 function to take index of inner ng-repeat and use this index instead of 0.
$scope.setResponse4 = function (postid, type, index,innerIndex, subcomment, commentid) {
var subcomment = subcomment;
$scope.posts[index].comment[innerIndex].subcomment = subcomment;
}
2) initialise innerIndex
<div ng-repeat="comment in post.comment" ng-init="innerIndex = $index">
3) pass innerIndex to your function
<input type='button' id='but_save' value='Save and Replace/Update' ng-click='setResponse4(post.id,1,outerIndex,innerIndex,subcomment,comment.id)'>
Demo

ng-repeat loop through object is not behaving properly

In my Angularjs ng-repeat is have following only one object, fields are reduced actually i have more than 40 in this object. if i have 40 fields then 40 empty output is rendering (see below outout).
{"Name": "Raj", "Gender":"M", "Country": "India"} (ONLY ONE OBJECT)
Angular View
<table ng-repeat="emp in model.Employee">
<tr>
<td><strong>Name:</strong></td>
<td>{{emp.Name}}</td>
</tr>
<tr>
<td><strong>Gender:</strong></td>
<td>{{emp.Gender}}</td>
</tr>
</table>
Excepted output is
Name: Raj
Gender: M
But the actual out put is rendering three time without value.
Name:
Gender:
Name:
Gender:
Name:
Gender:
This is happening because you are iterating over an object instead of an array. So, the ngRepeat loop will run as many times as there are keys in your object. Since, there are three keys in the object, the loop is being run thrice. Also, emp(the iterable) is the key('Name', 'Gender', 'Country') instead of the complete object.
Change to :
[{"Name": "Raj", "Gender":"M", "Country": "India"}]
you can use (key,value) for this purpose.
var app = angular.module("app",[])
app.controller('ctrl',['$scope', function($scope){
$scope.data ={"Name": "Raj", "Gender":"M", "Country": "India"};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div class="item item-checkbox">
<table >
<tr ng-repeat="(key,value) in data" ng-if="key != 'Country'">
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
</table>
</div>

Filter not working with dynamic input and ng-repeat

I am trying to filter records in my repeater on the basis of a input text box but it is working unexpectedly and not filtering the correct record.
My html code:
<input ng-model="txtTest" type="text" class="form-control" id="txtTest"></input>
<table>
<tr ng-repeat="SampleData in SampleInfo|MaxAmountFilter:txtTest" ng-form="SampleForm">
<td>
<div>
<input type="text" name="DateOfLoss" ng-Model="SampleData.DateOfLoss" </input>
</div>
</td>
<td>
<div>
<input type="text" name="LossDesc" ng-model="SampleData.LossDesc"> </input>
</div>
</td>
</tr>
</table>
My Directive:
AngularApp.filter('MaxAmountFilter', function () {
return function(AmountArray, AmountEntered ) {
var filteredAmount = [];
angular.forEach(AmountArray, function (amt) {
if (AmountEntered >= amt.LossAmount) {
filteredAmount.push(amt);
}
});
return filteredAmount;
};
});
My scope data -
$scope.SampleInfo = [
{ "DateOfLoss": "01/01/2014", "LossAmount": "100", "LossDesc": "sasa"},
{ "DateOfLoss": "01/01/2015", "LossAmount": "500", "LossDesc": "ssss" },
{ "DateOfLoss": "01/01/2011", "LossAmount": "102", "LossDesc": "ddd" },
{ "DateOfLoss": "01/01/2012", "LossAmount": "700", "LossDesc": "hhhh"},
{ "DateOfLoss": "01/01/2010", "LossAmount": "250", "LossDesc": "dsdsd"}
];
This is working fine for static values ie when I do not filter on the basis of input values of text box. What is wrong with the code. Please suggest!
EDIT: Plnkr here
Type 101, 102 then it works but when you type 10000 in the text box It does not work. Now remove MaxAmountFilter:txtTest from the filter and simply add MaxAmountFilter:10000 This will work.
Your input doesn't have an ng-model="txtTest". So the text entered in the amount is not saved in txtTest and txtTest is thus undefined.
EDIT:
another problem is that you're using strings to represent numbers. See this updated plunkr. Using an input of type number, and replacing your strings in the objects by numbers make everything go fine.

Select All directive in AngularJS

I am using Checklist model directive with my App. I have issue, if -
I click select all button though it write up the array but its not
selecting checkbox. Same issue with Uncheck All though it empty the
model but it doesn't uncheck checkboxes.
If I select 2 or 3 randomly checkbox and click Select All Button it doesn't select All check-boxes.
Though its writing values to pushArray. But issues are checking and unchecking checkboxes.
$scope.items = [{id:1, name:"abc"},{id:2, name:"def"},{id:3, name:"ghi"}];
$scope.pushArray = [];
<table>
<tr ng-repeat="e in items">
<td class="text-right">
{{e.id}}
<input type="checkbox" checklist-change="imChanged()" checklist-model="pushArray" checklist-value="e.id" >
</td>
</tr>
</table>
I think you are pushing the complete list of object which is wrong. You just need to map the list and pass the id to the $scope
Edit: Works fine when you use $scope.pushArray as an object instead of array.
Working Plnkr
HTML
<body ng-controller="selection">
<table>
<tr ng-repeat="e in items">
<td>
<input type="checkbox" checklist-model="pushArray.ids" checklist-value="e.id"> {{e.name}}
</td>
</tr>
</table>
{{pushArray.ids | json}}
<br />
<button ng-click="select_all();">Select All</button>
<button ng-click="unselect_all();">Unselect All</button>
</body>
JS
var app = angular.module('app', ["checklist-model"]);
app.controller('selection', ['$scope', function($scope) {
$scope.items = [{
id: 1,
name: "abc"
}, {
id: 2,
name: "def"
}, {
id: 3,
name: "ghi"
}];
$scope.pushArray = { ids: []}; // Works fine when using it as an object
//$scope.pushArray = [];
$scope.select_all = function() {
$scope.pushArray.ids = $scope.items.map(function(item) { return item.id; });
};
$scope.unselect_all = function() {
$scope.pushArray.ids = [];
};
}]);
Hope it works for you!
I updated the examples on checklist-model and fix this issue. Check them out http://vitalets.github.io/checklist-model/

AngularJS Setting default SELECT values

Basic 'shopping cart' scenario.Users should be choosing their desired products in a form environment. Every product has a core price and multiple additional options available which change the price when selected.
Products and options are shown in two SELECT fields which are getting populated like this:
$scope.products = [
{
name:'Product A',
cost:5,
options: [{name:"Option 1", value:10}]
},
{
name:'Product B',
cost:10,
options: [{name:"Option 1", value:10},{name:"Option 2", value:15}]
}
];
$scope.cart = {
items: [{
qty: 1,
}]
};
and
<tr ng:repeat="item in cart.items">
<td>
<div class="type-select">
<select ng-model="item.product" ng-options="p.name for p in products"></select>
</div>
</td>
<td>
<div class="type-select">
<select ng-model="item.option" ng-options="o for o in item.product.options.name" ng- disabled="!checked">
</div>
</td>
<td>
<input ng:model="item.qty" value="1" size="4" ng:required="" ng:validate="integer" class="ng-pristine ng-valid ng-valid-required input-mini">
</td>
<td>
{{calculate()}}
</td>
</tr>
How can i set default value for the cart items?
You can have a watch on items.
As soon as an item is added, you should assign that item's product to be the first product. Something like that:
$scope.$watchCollection('cart.items', function(newValue, oldValue){
var changedItem = newValue[newValue.length-1];
changedItem.product = $scope.products[0];
});
Of course, that would be assuming you know that $scope.products is an array and that it is not empty. You can have some checks for that. Anyway, I think it is weird to have default values for that but there is a way for you.

Resources