Is it possible to group data (using rowspan as explained here) in a table rendered with angularjs. Data is hierarchical, with state having many counties and each counties has multiple zipcodes. I want a table with only column for state, county, zip etc (so give a rowspan for length of the collection). I am not sure ng-repeat-start and ng-repeat-end can be used to achieve this. Please see the starter template here
<table>
<thead>
<tr>
<th>State</th>
<th>County</th>
<th>Zip</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='st in states'>
<td>{{st.name}}</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
data
var oh_counties = [
{name: "Franklin", zips: [111,222,333,444,555]},
{name: "Adams", zips: [111,222,333,444]},
{name: "Allen", zips: [111,222,333]}
],
wi_counties = [
{name: "Dane", zips: [111]},
{name: "Adams", zips: [111,222,333,444]}
]
$scope.states = [
{name: "OH", counties: oh_counties},
{name: "WI", counties: wi_counties},
];
Edit:
A handcrafted version of the desired output is here http://plnkr.co/edit/T7toND0odx6qr8mVC121?p=preview
This is a variant of Holly Cummins' answer. The repeat is moved into the tr with ng-repeat-start and ng-repeat-end to prevent the tbody from being repeated. Also uses a slightly different method to hide the first row.
<tbody>
<tr ng-repeat-start='st in states'>
<th rowspan="{{st.counties.length}}">{{st.name}}</th>
<td>{{st.counties[0].name}}</td>
</tr>
<tr ng-repeat-end ng-repeat='county in st.counties' ng-hide="$first">
<td>{{county.name}}</td>
</tr>
</tbody>
This variant of KayakDave's answer improves the structuring by pulling the first nested row out to share the <tr> of the header:
<tbody ng-repeat='st in states'>
<tr>
<th rowspan="{{st.counties.length}}">{{st.name}}</th>
<td>{{county[0].name}}</td>
</tr>
<tr ng-repeat='county in st. counties' ng-show="$index > 0">
<td>{{county.name}}</td>
</tr>
</tbody>
Sure. Is something like this what you had in mind:
<tbody ng-repeat='st in states'>
<td rowspan="{{st.counties.length+1}}">{{st.name}}</td>
<tr ng-repeat='county in st.counties'>
<td>{{county.name}}</td>
</tr>
</tbody>
I kept this example simple, nested 2 deep. But in the fiddle, below, I've got it nested 3 deep (so it includes zip).
demo fiddle
This may be usefull
<table>
<tbody ng-repeat='st in states'>
<tr>
<th >{{st.name}}</th>
<td>
<table>
<tr ng-repeat='county in st.counties'>
<td>{{county.name}}</td>
<td>
<table>
<tr ng-repeat='zip in county.zips'>
<td>{{zip}}</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
Related
I am working with a table that has two rows: the header row and then the body row. In the body row, each column contains another table. Like this:
<table id="example">
<thead>
<tr>
<td>Col A</td>
<td>Col B</td>
<td>Col C</td>
</tr>
</thead>
<tbody>
<tr>
<td valign="top">
<table>
<tr>
<td>Data</td>
<td>Data2</td>
</tr>
</table>
</td>
<td valign="top">
<table>
<tr>
<td>Data3</td>
<td>Data4</td>
</tr>
</table>
</td>
<td valign="top">
<table>
<tr>
<td>Data5</td>
<td>Data6</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
I have my datatable setup like this:
<script type="text/javascript">
const columns = [
{ title: '' },
]
let table = $('#example').DataTable({
createdRow: function(row) {
$(row).find('td table')
.DataTable({
columns: columns,
dom: 'tf'
})
}
})
</script>
The problem is that when I search for something, I want ALL the tables (including the nested ones) to filter out the results. So in my code above, as an example, if I search for "Data2", I would expect the second and third columns to become empty and just one result appear in the first column. However, at present, since "Data2" is found in this row (of which there is only one in this table), it simply returns ALL the data.
I found a REALLY good example that is close to what I want (which I what my current code is based on):
http://jsfiddle.net/davidkonrad/8pzkr6yn/
If we use the example from the JSFiddle, you can see searching for "722" returns only the last row, but still all the results from each nested table from within that row are there. I'd like it so that searching 722 globally will return the results as if 722 was searched individually in each column.
How can I adjust the code to make it so that all the nested tables get filtered out, not just the main table?
Bonus points if we can eliminate the search box in every nested datatable!
Can anyone help me learn how to convert an HTML table into a dynamic Javascript table using the for loop? This is an example I found in my book and wanted to see how I could go about doing this.
Heading There is sections of the table that need to have the rows combined and he columns combined. I have been struggling with this for some time. Any help would be appreciated. I did not include the CSS portion of the code only the table.
<html>
<body>
<table class="table">
<tr>
<th colspan= "3" class= "MH">Conversion Tables</th>
</tr>
<tr>
<th rowspan="3" class="heading1">Meters to
<br />Feet</th>
<td>1 meter</td>
<td>3.28 feet</td>
</tr>
<tr class="difrow">
<td>50 meters</td>
<td>164.04 feet</td>
</tr>
<tr>
<td>100 meters</td>
<td>328.08 feet</td>
</tr>
<tr class="difrow">
<th rowspan="3" class="heading1">Kilometers to
<br />Miles</th>
<td>1 kilometer</td>
<td>0.62 miles</td>
</tr>
<tr>
<td>50 kilometers</td>
<td>31.07 miles</td>
</tr>
<tr class="difrow">
<td>100 kilometers</td>
<td>62.14 miles</td>
</tr>
</table>
</body>
</html>
you can add id attribute to table tag then call a javascript method on page load:
<table class="table" id="tableId">
function createRows(){
var items = "<tr><td></td></tr>...";
document.getElementById("tableId").innerHTML = items;
}
in javascript method you can use for to generate table rows.
I am receiving a data object of results that have been pivoted and I am unable to change the structure that is returned to me. My only option at this point is to manipulate the data to parse it how I need to.
Here is what my results look like:
// Object from service
let dataObj = [{
CostCenter: '12345',
HasLevel1Access: 'No',
HasLevel2Access: 'No',
HasLevel3Access: 'Yes',
FirstName: 'Bob',
LastName: 'Jones',
UID: '12345'
},
{
CostCenter: '555',
HasLevel1Access: 'Yes',
HasLevel2Access: 'No',
HasLevel3Access: 'Yes',
FirstName: 'Tommy',
LastName: 'C',
UID: '6789'
},
{
CostCenter: '51112',
HasLevel1Access: 'Yes',
HasLevel2Access: 'No',
HasLevel3Access: 'Yes',
FirstName: 'Smithson',
LastName: 'J',
UID: '8888'
}];
From this data, I need to make a table. The trick here is that I need to use some of the property names as the column headers but exclude others.
My table is very basic, it contains the persons name and then all of the dynamic column names:
<table class="table table-condensed" border="1">
<thead>
<tr>
<th>Employee Name</th>
<th *ngFor="let m of columnNames">{{ m }}</th>
</tr>
</thead>
<tbody>
<!-- Example Record 0 -->
<tr>
<td>Bob Jones</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
</tr>
<!-- Example Record 0 -->
</tbody>
</table>
The first thing I did in order to get the column names is create an array of the IgnoreColumns which is the property names I wan't to exclude from being its own column in the table.
// Hold all of the column names
private columnNames = [];
// Ignore these columns, they dont get printed as headers
private ignoreColumns = ['CostCenter', 'FirstName', 'LastName', 'UID'];
I then looped over the first record in the result set and pushed all of the property names to an array that are not in our ignoreColumns array. This leaves me with a unique array of the dynamic columns.
// Find all the keys in our first result
for (var p in dataObj[0]) {
// Get the key names
if (dataObj[0].hasOwnProperty(p)) {
// If this key name doesnt already exist in the array AND its not in our ignored list push them to our array
if (!_.includes(this.columnNames, p) && !_.includes(this.ignoreColumns, p)) {
this.columnNames.push(p);
}
}
}
I am stuck at this point. I was able to create the table structure with the headings in place but I don't know how I should proceed to get the data aligned under the correct columns in the table.
This is what I am going for in my final output:
<table class="table table-condensed" border="1">
<thead>
<tr>
<th>Individual</th>
<th>HasLevel1Access</th>
<th>HasLevel2Access</th>
<th>HasLevel3Access</th>
</tr>
</thead>
<tbody>
<tr>
<td>Bob Jones</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>Tommy C</td>
<td>Yes</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>Smithson J</td>
<td>Yes</td>
<td>No</td>
<td>Yes</td>
</tr>
</tbody>
</table>
Here is a plunkr of where I am at: http://plnkr.co/edit/9WygBXsQaDaxTMudb7ZB?p=preview
Any advice on how to approach this?
What about
<tr *ngFor="let item of dataObj">
<td>{{item.FirstName}} {{item.LastName}}</td>
<td *ngFor="let m of columnNames">{{item[m]}}</td>
</tr>
Working demo
You meant something like this?
<tr *ngFor="let data of dataObj">
<td>{{data.FirstName+" "+data.LastName}}</td>
<td>{{data.HasLevel1Access}}</td>
<td>{{data.HasLevel2Access}}</td>
<td>{{data.HasLevel3Access}}</td>
</tr>
http://plnkr.co/edit/EHsVFaiaK1UUcWrbm6zX?p=preview
I have the following json array string
queryResults=
[
{"name":"cliff","age":"20","hobby":"tennis","email":"cliff#gmail.com"},
{"name":"jason","age":"30","hobby":"golf","email":"jason#gmail.com"}
]
I need to use ngFor to produce the following html layout
<table>
<tr>
<td>name:</td><td>cliff</td>
<td>age:</td><td>20</td>
</tr>
<tr>
<td>hobby:</td><td>tennis</td>
<td>email:</td><td>cliff#gmail.com</td>
</tr>
</table>
<table>
<tr>
<td>name:</td><td>jason</td>
<td>age:</td><td>30</td>
</tr>
<tr>
<td>hobby:</td><td>golf</td>
<td>email:</td><td>jason#gmail.com</td>
</tr>
</table>
How can i accomplish this? any suggestion will be helpful thank you
Assuming that your JSON is in array form, you can solve this by using *ngFor like this
<table *ngFor="#it of queryResults">
<tr>
<td>Name:</td><td>{{it.name}}</td>
<td>Age:</td><td>{{it.age}}</td>
</tr>
<tr>
<td>hobby:</td><td>{{it.hobby}}</td>
<td>email:</td><td>{{it.email}}</td>
</tr>
</table>
I'm using #Mottie's excellent fork of Tablesorter and would like to be able to filter table column(s) with external links.
It isn't strictly necessary, but I'd like to make multiple clicks toggle the filter on and off. Alternatively, I could always add an All Records link that resets the column(s).
I don't need to combine filters in a single column. In other words, the data wouldn't be both January and October.
I found a table sort with external link demo, but that one sorts, not filters, and it doesn't toggle.
I also found a table filter with buttons demo which is pretty close. However, as I mentioned, I'd really like links instead, would like to have the links toggle if possible, and don't need the filters to combine.
Thanks in advance.
This was actually a lot easier than I thought. Here's a working demo that came directly from Mottie's demo code above. I replaced the buttons with links, renamed the associated class so it made more sense and replaced the class on the JavaScript function to match the one on the links.
Fair warning: I don't claim to know everything, so my modifications could have very silly errors.
$('.link-filter').click(function() {
var filters = $('table').find('input.tablesorter-filter'),
col = $(this).data('filter-column'),
txt = $(this).data('filter-text');
// filters.val('');
filters.eq(col).val(txt).trigger('search', false);
});
The filters in the various columns combine, but I only need a single column filter at the moment, so that's not really an issue for me.
Country:<br>
All Countries |
Netherlands |
Belgium |
Germany
<br /><br />
<table id="festivaloverzichttable" class="tablesorter">
<thead>
<tr>
<th width="17%" data-placeholder="Search...">Event</th>
<th width="18%" data-placeholder="Search...">Date</th>
<th width="9%" data-placeholder="Search...">Duration</th>
<th width="12%" data-placeholder="Search...">Place</th>
<th width="10%" data-placeholder="Search...">Country</th>
<th data-placeholder="Zoek...">Genre(s)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Event 1</td>
<td data-date="06-02">TBA</td>
<td>2</td>
<td>Oisterwijk</td>
<td>Netherlands</td>
<td>Hardstyle</td>
</tr>
<tr>
<td>Event 2</td>
<td data-date="10-11">11 October t/m 13 October</td>
<td>3</td>
<td>Volkel</td>
<td>Netherlands</td>
<td>Pop, Rock, Urban, Electronic</td>
</tr>
<tr>
<td>Event 3</td>
<td data-date="06-02">TBA</td>
<td>1</td>
<td>Amsterdam</td>
<td>Netherlands</td>
<td>Electronic</td>
</tr>
<tr>
<td>Event 4</td>
<td data-date="09-01">TBA</td>
<td>1</td>
<td>Utrecht</td>
<td>Netherlands</td>
<td>Electronic, Urban</td>
</tr>
<tr>
<td>Event 5</td>
<td data-date="07-06">6 July - 7 July</td>
<td>2</td>
<td>Beek en Donk</td>
<td>Netherlands</td>
<td>Electronic, Hardstyle</td>
</tr>
...
</tbody>
</table>
Javascript
$("#festivaloverzichttable").tablesorter({
sortList: [[0, 0]],
widgets: ['zebra', 'filter', 'saveSort'],
widgetOptions: {
filter_reset: 'button.reset'
}
});
$('.link-filter').click(function() {
var filters = $('table').find('input.tablesorter-filter'),
col = $(this).data('filter-column'),
txt = $(this).data('filter-text');
// filters.val('');
filters.eq(col).val(txt).trigger('search', false);
});