I need to get the value in a row of a table on click and display it in popup
HTML:
<md-data-table-container>
<table md-data-table class="md-primary" md-progress="deferred">
<thead md-order="query.order" md-trigger="onorderchange">
<tr>
<th name="Task To Be Done"></th>
<th name="Office"></th>
<th name="Due Date"></th>
</tr>
</thead>
<tbody ng-click="showAlert($event)">
<tr ng-repeat="dessert in desserts.data" ng-click="showAlert($index)" flex-sm="100" flex-md="100" flex-gt-md="auto">
<td>{{dessert.task}}</td>
<td></td>
<td>{{dessert.due_on}}</td>
</tr>
</tbody>
</table>
</md-data-table-container>
JS:
$scope.desserts = {
"count": 6,
"data": [{
"task": "Frozen yogurt",
"type": "Ice cream"
}, {
"task": "Ice cream sandwich",
"type": "Ice cream"
}, {
"task": "Eclair",
"type": "Pastry"
}, {
"task": "Cupcake",
"type": "Pastry"
}, {
"task": "Jelly bean",
"type": "Candy"
}, {
"task": "Lollipop",
"type": "Candy"
}, {
"task": "Honeycomb",
"type": "Other"
}]
};
$scope.showAlert = function (index) {
$scope.obj = $scope.desserts.data[2];
$scope.task = $scope.obj.task;
alert($scope.task);
console.log($scope.task);
};
issue in my code is that i could get the value on the array which i have specified ".data[2]". Actually when i click a row in my table i need that value to be displayed to popup "sweetAlert". is there any solution
Don't pass the $index, as this can be a bit dangerous if the underlying data changes, and in this case it just forces you to re-get the item from the array.
Pass the actual item you want to display back to the alert.
<tr ng-repeat="dessert in desserts.data" ng-click="showAlert(dessert)" flex-sm="100" flex-md="100" flex-gt-md="auto">
<td>{{dessert.task}}</td>
<td></td>
<td>{{dessert.due_on}}</td>
</tr>
Don't assign to scope unless you really need it elsewhere.
$scope.showAlert = function (dessert) {
alert('Task:' + dessert.task);
// if you're just using a variable in this function, declare it locally
var dessertType = dessert.type;
console.log(dessertType);
};
See an example of $index causing issues:
http://codeutopia.net/blog/2014/11/10/angularjs-best-practices-avoid-using-ng-repeats-index/comment-page-1/
Related
My requirement is to have dropdowns in each row of two columns of grid as below:
Here is stackblitz for my problem: https://stackblitz.com/edit/angular9-primeng9
User can select values for each row and save. I am able to fetch data from data source using service and initialize dropdown options in subscribe of observable. However, I am not able to set the selected item of each row on page load to display pre-existing rows (I think problem of setting up [(ngModel)]).
Also, I need to add a plus button which would add a new row to this table and result should be saved to database on save action. Any guidance / lead to address this issue would be of great help.
Below is HTML code I am using:
<p-table [columns]="cols" [value]="rows">
<ng-template pTemplate="header" let-columns>
<tr>
<th *ngFor="let col of columns">
{{col.header}}
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-rowData let-columns="columns">
<tr>
<td>
<p-dropdown [options]="DropdownSource" [(ngModel)]="rowData.AAttribute" placeholder="Select"
[showClear]="true"></p-dropdown>
</td>
<td>
<p-dropdown [options]="DropdownSource" [(ngModel)]="rowData.BAttribute" placeholder="Select"
[showClear]="true"></p-dropdown>
</td>
</tr>
</ng-template>
</p-table>
and in component (subscribe in onchanges):
this.cols = [
{ "field": "field_0", "header": "A Attribute" },
{ "field": "field_1", "header": "B Attribute" }
];
this.rows = [{ "AAttribute": "Data3", "BAttribute": "DataC" },
{ "AAttribute": "Data5", "BAttribute": "DataE" }];
this.DropdownSource= [
{ "AAttribute": "Data1", "BAttribute": "DataA" },
{ "AAttribute": "Data2", "BAttribute": "DataB" },
{ "AAttribute": "Data3", "BAttribute": "DataC" },
{ "AAttribute": "Data4", "BAttribute": "DataD" },
{ "AAttribute": "Data5", "BAttribute": "DataE" },
{ "AAttribute": "Data6", "BAttribute": "DataF" }]
ngmodel expects object from the array.
refer below stackblitz https://stackblitz.com/edit/angular9-primeng9-dgxsjj
this.mappingRows = [{ "targetCol": "DataF", "SourceCol": this.sourceAttributes.find(p=>p.label === "Data3") },
{ "targetCol": this.targetAttributes[3], "SourceCol": "Data6" },
{ "targetCol": "DataC", "SourceCol": "Data1" }];
Below is my JSON object and I am trying to show the same in html table.
$scope.results = {
"data": [
{
"name": "Sam",
"details": [
{
"official": [
{
"address1": "Link road",
"pincode": 76755554
},
{
"address1": "K main road",
"pincode": 9766565
}
]
},
{
"name": "John",
"details": [
{
"official": [
{
"address1": "Old college road",
"pincode": 11111
},
{
"address1": "near east side",
"pincode": 6555446
}
]
}
]
}
]
}
]
}
I have used ng-repeat to achieve the below output. But I am not getting the expected result
This is the code which I have tried and got stuck JSFIDDLE
Any idea on how to achieve my expected result will be really helpful.
You may have to tweak this slightly if your data structure can get more complicated when there are more levels, but this should reformat your data and flatten everything into an array of people without all the different levels.
$scope.peopleFlat = [];
function flattenPeople(people) {
people.forEach((person) => {
$scope.peopleFlat.push({
name: person.name,
addresses: person.details[0].official
});
if (person.details.length > 1) {
flattenPeople([person.details[1]]);
}
});
}
flattenPeople($scope.people);
Then you can use a combination of ng-repeat-start and ng-repeat-end to make it work using rowspan instead of a nested <table> element.
<table class="table table-bordered table-condensed">
<tr>
<th>Name</th>
<th>Address</th>
<th>Pincode</th>
</tr>
<tr ng-repeat-start="person in peopleFlat">
<td rowspan="{{person.addresses.length || 1}}">{{person.name}}</td>
<td>{{person.addresses.length ? person.addresses[0].address1 : ''}}</td>
<td>{{person.addresses.length ? person.addresses[0].pincode : ''}}</td>
</tr>
<tr ng-repeat-end ng-repeat="address in person.addresses.slice(1)">
<td>{{address.address1}}</td>
<td>{{address.pincode}}</td>
</tr>
</table>
I dynamically created an array using rows and columns
[
{
"name": "table 1",
"rows": [
"row 1",
"row 2",
"row 3",
"row 4",
"row 5"
],
"columns": [
"column 1",
"column 2"
],
"col1": [
{
"1": "row1col1"
},
{
"2": "row2col1"
},
{
"3": "row3col1"
},
{
"4": "row4col1"
},
{
"5": "row5col1"
}
],
"col2": [
{
"1": "row1col2"
},
{
"2": "row2col2"
},
{
"3": "row3col2"
},
{
"4": "row4col2"
},
{
"5": "row5col2"
}
]
},
{
"name": "table 2",
"rows": [
"row 1",
"row 2",
],
"columns": [
"column 1",
"column 2",
"column 3"
],
"col1": [
{
"1": "row1col1"
},
{
"2": "row2col1"
],
"col2": [
{
"1": "row1col2"
},
{
"2": "row2col2"
],
"col3": [
{
"1": "row1col3"
},
{
"2": "row2col3"
]
}
]
Then using this dynamic array I created a table and stored it as finalArray
which was okay until I went to the body of my table to show data for col and row
<div *ngFor="let table of finalArray">
<span>{{table.name}}</span>
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col"></th>
<th *ngFor="let column of table.columns" scope="col">{{column}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of table.rows ; let i = index">
<td>{{row}}</td> // this works fine
<td *ngFor="let column of table.columns; let x = index"> {{table.['col' + x].[i+1]}}</td>
// this is the problem
</tr>
</tbody>
</table>
</div>
Note that the array was created dynamically so rows and columns is not fixed and col1 and col2 was created based on columns.
I attempt to something like table.col[index].[loop all values]?
You are almost there. Iterate thru columns in the second loop for more precision. Remove '.'s when getting elements. Interchange + 1 from i to x when getting columns and use Object.keys to get the array of key names so you can get the corresponding column content. I put it in a method for for readability
HTML
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col"></th>
<th *ngFor="let column of table.columns" scope="col">{{column}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of table.rows ; let i = index">
<td>{{row}}</td>
<td *ngFor="let col of table.columns; let x = index">
{{getColumnContent(table['col'+(x+1)][i])}}
</td>
</tr>
</tbody>
</table>
Typescript
getColumnContent(col) {
return col[Object.keys(col)[0]] // always [0] as it contains a single element
}
Demo
/*factory method for getting particular customers order*/
factory.getCustomer = function(customerId) {
for(var i=0,len=customers.length ; i<len ; i++) {
if(customers[i].id === parseInt(customerId)){
return customer[i];
}
}
return {};
};
return factory();
/*Controller*/
myApp.controller('OrdersController',['$scope','$routeParams','customersFactory', function($scope,$routeParams,customersFactory) {
var customerId = $routeParams.customerId;
$scope.customer = null;
function init() {
$scope.customer = customersFactory.getCustomer(customerId);
}
init();
}]);
/*View*/
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>{{customer.name}}'s Orders</h2>
<table class="table table-hover">
<tr>
<th>Product</th>
<th>Total</th>
</tr>
<tr ng-repeat="order in customer.orders">
<td>{{ order.product }}</td>
<td>{{ order.total | currency }}</td>
</tr>
</table>
</div>
</div>
</div>
/*JSON FILE*/
{
"id": "1",
"joined": "2000-12-2",
"name": "Wali",
"city": "Dubai",
"orderTotal": "9.0765",
"orders": [
{
"id": "1",
"product": "protein",
"total": "11.987"
}
]
},
{
"id": "2",
"joined": "2004-12-2",
"name": "Ali",
"city": "London",
"orderTotal": "20.0765",
"orders": [
{
"id": "2",
"product": "bcca",
"total": "2.3456"
},
{
"id": "3",
"product": "baseball",
"total": "4.3456"
}
]
},
{
"id": "3",
"joined": "1980-11-2",
"name": "Zen",
"city": "Australia",
"orderTotal": "6.500",
"orders": [
{
"id": "3",
"product": "chocolate",
"total": "6.4567"
}
]
}
I have made a customers table from which we can perform the CRUD functionality, but when I click to check the particular customer order it is redirecting me to the right view via routing but particular customers orders are not displaying.
can any one suggest a solution for this?
According to your JSON data, the ID is a String, but you are parsing it into an integer, and using ===, which will match only if the value and the type of the compared variables match.
You need to change the if statement, one option is:
if (parseInt(customers[i].id) === parseInt(customerId))
Another option will be:
if (customers[i].id == customerId)
And yet another option is using angular's $filter service.
You need to inject it into your factory, and than in order to get the client, you can use:
var customer = $filter('filter')(customers, {id: customerId.toString()}, true);
return customer.length === 1 ? customer[0] : null;
The toString part is only because your JSON data have ID as as string, and the third argument is set to true to prevent 'like' filter (default $filter behavior will return id 10 for example also if the customerId is 1).
I need to draw a table in AngularJS based on the following array
$scope.list = [
{ "Row":1, "Column": 1, "Value": "11" },
{ "Row":1, "Column": 2, "Value": "12" },
{ "Row":1, "Column": 3, "Value": "13" },
{ "Row":2, "Column": 1, "Value": "21" },
{ "Row":2, "Column": 2, "Value": "22" },
{ "Row":2, "Column": 3, "Value": "23" },
];
So I need to get a table with 2 rows and 3 columns
I understand that I have to use two nested ngRepeat but I couldn't make it work
Please could you help me ??
Regards
I developed the solution I found a filter 'Unique' here
For each unique row number I get the list of columns
<table border="2">
<tr ng-repeat="row in list | unique:'Row'">
<td>Row: {{row.Row}}</td>
<td ng-repeat="col in list | filter:{'Row':row.Row}">{{col.Value}}</td>
</tr>
</table>
You should first transform your array to such one:
$scope.table = [
["11", "12", "13"],
["21", "22", "23"],
];
That way, it will be easier to iterate over the values in your view:
<table>
<tr ng-repeat="row in table">
<td ng-repeat="column in row">
{{column}}
</td>
</tr>
</table>