Trying to loop over an array and display the results, but only the last element showing multiple times.
Here is my code.
Making a get request.
showItems(id: any): Observable<any> {
return this.http.get(`${this.url}${id}`)
}
Console logging works fine here, I can see the expected results.
ngAfterViewInit(): void {
this.showItems()
}
showItems(): void {
const id: any = []
this.idFromList.forEach((val: any) => id.push(val.nativeElement.innerText))
for(let i = 0; id.length > i; i++) {
this.ItemService.showItems(id[i]).subscribe(data => {this.api_items = data.item.current
console.log(this.api_items)});
}
}
HTML
<table>
<thead>
<tr>
<td>Name</td>
<td>Price</td>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of items | filter: searchQuery" >
<td >
<a href="" #btn>{{item.id}}</a>
{{ item.name }}
</td>
<td *ngFor="let api_item of api_items | keyvalue">
{{ api_item.value }}
</td>
</tr>
</tbody>
</table>
Tried using fake JSON server, same results.
1) Quick answer
Push items in an array instead of replacing its value :
api_items = [];
this.ItemService.showItems(id[i]).subscribe(data => {
this.api_items.push(data.item.current);
});
2) Complete answer
As #MoxxiManagarm said, you're replacing api_items value at each iteration of your for loop.
You might want to check & use RxJS to handle multiple observables in a cleaner way: for example, by generating an array of Observable to resolve them together.
3) Ressources & useful links you might want to check for more information
https://www.learnrxjs.io/
There is a table which loops and outputs the data which comes from API. I have added a button inside the table. When you click it, it should send the id of the clicked button and till it recieves the data of the function which needs to be printed, it should be in loading. Here is my code.
<table id="customers">
<tr>
<th>{{$t('message.numberReport')}}</th>
<th>{{$t('message.periodFrom')}}</th>
<th>{{$t('message.periodTo')}}</th>
<th>{{$t('message.printButton')}}</th>
</tr>
<tr v-for="(item,index) in getReportInfo" :key="index">
<td>{{ item.id }}</td>
<td>{{ item.periodFrom }}</td>
<td>{{ item.periodTo }}</td>
<td>
<v-btn
class="primary"
:loading="loading"
:disabled="loading"
#click="fetchGetReportDetailed(item)"
>{{ $t('message.printButton')}}</v-btn>
</td>
</tr>
</table>
But when I clicked the particular button, all the buttons are getting in loaded mode. How do I fix it? Any suggestion would be deeply appreciated.here is the visual example
Using index of item in list.
You can register a new variable in your data for example indexClicked .
data () {
return {
// Some predefined value, 0 isn't good because index can be 0.
indexClicked: undefined // Some predefined value
}
}
And when you click at button you can send index value:
<td>
<v-btn class="primary"
:loading="loading && indexClicked === index"
:disabled="loading && indexClicked === index"
#click="fetchGetReportDetailed(item, index)">
{{ $t('message.printButton') }}
</v-btn>
</td>
And in your fetchGetReportDetailed(item, index) method you need to assign index to this.indexClicked like:
fetchGetReportDetailed (item, index) {
// Your code
this.indexClicked = index;
}
This should work. But if you need more information please provide more code.
Note if you have a problem with multiple conditions in :disable you can create a method which will return true or false depends on condition loading && this.indexClicked === index.
Good luck!
You're using a single data property for all rows, so in mounted hook add a property called loading to each row like :
mounted(){
this.getReportInfo=this.getReportInfo.map(rep=>{
rep.loading=false;
return rep;
});
}
and the template do:
<tr v-for="(item,index) in getReportInfo" :key="index">
<td>{{ item.id }}</td>
<td>{{ item.periodFrom }}</td>
<td>{{ item.periodTo }}</td>
<td><v-btn class="primary" :loading="item.loading" :disabled="loading" #click="fetchGetReportDetailed(item,index)" >{{ $t('message.printButton')}}</v-btn></td>
</tr>
in fetchGetReportDetailed method :
fetchGetReportDetailed(item,index){
....
this.getReportInfo[index].loading=true;
this.$set(this.getReportInfo,index,this.getReportInfo[index])
}
You could separate the tr that is displaying the data into its own state-full component and call the function from within the component.
This way the state of loading for each item in the array will be local to its own component.
I am trying to create a table where the number given in the url for example:
localhost:8000/add/:num
where the num is value given and it will create a table with rows which should contain the sums of all possible numbers from 0 to :num.
server.js
app.get('/add/:num', function(req,res) {
console.log(Number(req.params.num)+ Number(5));
res.render('add.hbs', {
number_1: 5,
number_2: req.params.num,
sum: Number(req.params.num)+ Number(5)
});
});
add.hbs
{{#each users}}
<tr>
<td>
{{number_1}}
</td>
<td>
{{number_2}}
</td>
<td>
{{sum}}
</td>
</tr>
{{/each}}
Now I can render the HTML table but i cannot dynamically add rows when a specific number is given on the URL. So if the number is passed as 2, it should add 0 + 1 onto one row, 1 + 2 onto the next row. I know i need to create a helper function in order to render that on the .hbs file but i cant figure out the logic behind it.
I am generating following json data from my database where keys like sid and name is static but task1,task2,task3 .... are dynamic and they can be upto value n(where n=1,2,3......)
My data:
[
{"sid":"10","name":"nam1","task1" :"1","task2" :"0","task3" :"1","task4" :"0","task5" :"0"},
{"sid":"20","name":"nam2","task1" :"0","task2" :"1","task3" :"0","task4" :"1","task5" :"1"},
{"sid":"30","name":"nam3","task1" :"1","task2" :"1","task3" :"0","task4" :"0","task5" :"1"},
{"sid":"40","name":"nam4","task1" :"0","task2" :"0","task3" :"0","task4" :"0","task5" :"1"}
]
app.js
app.controller('taskCrtl', function ($scope, $http, $timeout) {
$http.get('get.php').success(function(data){
$scope.list = data;
$scope.currentPage = 1; //current page
$scope.entryLimit = 5; //max no of items to display in a page
$scope.filteredItems = $scope.list.length; //Initially for no filter
$scope.totalItems = $scope.list.length;
});
Now i am trying to access key values using ng-repeat like below:
<tr ng-repeat="data in list| unique: 'sid'">
<td>{{data.sid }}</td>
<td>{{data.name}}</td>
<td>{{data.task1}}</td>
<td>{{data.task2}}</td>
<td>{{data.task3}}</td>
<td>{{data.task4}}</td>
<td>{{data.task5}}</td>
<tr/>
The above code works well for fixed keys like task1,task2,task3... but i am generating "task" key dynamically so it will be always unknown to me that how many task keys are there.There may be a case when there are keys from task1 to task100 so the above code will fail on that case.
I am trying to dynamically access the task keys to generate associate data.To achieve this i am concatenating a number( produced by an incremental loop) with the task key so that i becomes like task1,task2 .... value n
<tr ng-repeat="data in list| unique: 'sid'">
<td> {{ data.sid }} </td>
<td> {{ data.name }} </td>
<td ng-repeat="data in list| limitTo:n">
{{ id=$index+1; 'data.task'+id}}
</td>
</tr>
Id starts with 1 and incremented in every loop so that we can dynamically access data.task1,data.task2 and so on
I am facing two problems here.After concatenation i was supposed to get the value of a corresponding task key but i am getting like this data.task1,data.task2,data.task3 that is i am getting keys itself instead of key values.
The second problem is i want to loop up to n number of times so i am limiting the ng-repeat by n like this way ng-repeat="data in list| limitTo:n" but the value of n is unknown to me.Here n should be equal to the highest number of dynamic task key(or total task keys).
For example if in the data list there exist task1,task2,task3,task4,task5 then n will be 5 since there are total 5 task keys.If there exist task1 to task100 then n will be 100 as there are total 100 task keys.
One idea to achieve this could be counting total unique keys from the array and then subtract 2 static keys from it to get the number of dynamic keys which will be used as value of n to limit the loop.
For example in above data set the unique keys are sid,name,task1,task2,task3,task4,task5 if somehow we can manage to calculate total number of unique keys from the array then the total number of unique keys will be 7 in this case, and if we subtract 2 from the number 7 then we have 5 which is equal to the number of dynamic keys in the array, that we want to use as n to limit the loop.
Any idea how to solve my above problems using angularjs ?
I assume that the total number of task attributes on an Item may be varied.
By returning the list of Keys which start with Task you can iterate over that list instead and making it a function, you can call that during each iteration of ngRepeat:
$scope.getTaskKeys = function(row) {
return Object.keys(row).filter(function(keyname) {
return keyname.startsWith('task');
});
Leaving you free to call it as the collection for the second iteration:
<tr ng-repeat="data in list| unique: 'sid'">
<td> {{ data.sid }} </td>
<td> {{ data.name }} </td>
<td ng-repeat="taskKey in getTaskKeys(data)">
{{data[taskKey]}}
</td>
</tr>
Created a working example here: https://jsfiddle.net/zd1yjc0m/
Try this it will work as per your expectation..
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function($scope) {
$scope.list = [
{"sid":"10","name":"nam1","task1" :"1","task2" :"0","task3" :"1","task4" :"0","task5" :"0"},
{"sid":"20","name":"nam2","task1" :"0","task2" :"1","task3" :"0","task4" :"1","task5" :"1"},
{"sid":"30","name":"nam3","task1" :"1","task2" :"1","task3" :"0","task4" :"0","task5" :"1"},
{"sid":"40","name":"nam4","task1" :"0","task2" :"0","task3" :"0","task4" :"0","task5" :"1"}
];
for (var i in $scope.list) {
var res = Object.keys($scope.list[i]).filter(item => { return item.indexOf("task") > -1; });
$scope.tasksList = res;
}
});
table,td {
border: 1px solid black;
padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<table>
<tr ng-repeat="data in list">
<td> {{ data.sid }} </td>
<td> {{ data.name }} </td>
<td ng-repeat="item in tasksList"> {{ data[item] }} </td>
</tr>
</table>
</div>
data[0] contain the JSON data and data[1] contain dynamic key
<tr ng-repeat="x in data[0] ">
<td ng-repeat="j in data[1]">
[[ x[j] ]]
</td>
</tr>
I am trying to update quantity number of individual items in a table whenever the user clicks the item in another table.
For example, I have list of all items in Table A
<tr ng-repeat="item in items">
<td>{{item.fid}}</td>
<td{{ item.fname }}</td>
<td>{{ item.calorie }}</td>
<td>{{ item.protein }}</td>
<td>{{ item.carb }}</td>
<td>{{ item.fat }}</td>
<td><button ng-click=additem(values)>Add</button>
<tr>
Now when the user clicks this Add button, the selected item gets added to another table (Table B).
I have disabled duplicates in Table B and want that if the user is repeatedly adding same item then the quantity of the item in Table B should increase.
Table B
<tr ng-repeat="sitem in sitems>
<td>{{sitem.fname}}</td>
<td>{{sitem.calorie}}</td>
<td>{{sitem.protein}}</td>
<td>{{sitem.carb}}</td>
<td>{{sitem.fat}}</td>
<td>*</td>
<td><button ng-click="removeItem(values)">Remove</button></td>
</tr>
is the one where i want the increased quantity to be shown.
I have tried using "this" keyword but didn't worked, I am new to angular so i don't know what all are my options and got mixed up.
You have to keep track of two separate array to accomplish this.
This is the code snippet: `
$scope.additem = function(item) {
var index = $scope.sitems.indexOf(item);
if (index === -1) {
item.quantity = 1;
$scope.sitems.push(item);
return;
}
item.quantity++;
$scope.sitems[index] = item;
};
`
Complete Working fiddle: https://jsfiddle.net/nbakliwal18/4kbo7Lfo/2/
Also you check for quantity before adding.
You can simply pass item to the function addItem() :
<td><button ng-click=addItem(item)>Add</button>
and push this item to your array sitems in your function :
$scope.addItem = function(item) {
$scope.sitems.push(item);
}
A workaround for the duplicates in ng-repeat is to add track by $index to it :
<tr ng-repeat="sitem in sitems track by $index">
Update 1:
Updated my answer with working example in Plunker
Update 2:
Here is an example with lodash for quantity Plunker