angular table with dynamic column names - javascript

Is it possible to populate a table with angular.js without defining the column names prior to the 'ng-repeat'? For example this is how I'm currently populating the table..
<table class="table">
<thead>
<tr>
<th>Arup Mnemonic</th>
<th>Organism</th>
<th>Test</th>
<th>Result</th>
<th>Source</th>
<th>Source Value</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in data">
<td>{{ x.Arup_Mnemonic }}</td>
<td>{{ x.organism }}</td>
<td>{{ x.test }}</td>
<td>{{ x.result }}</td>
<td>{{ x.source }}</td>
<td>{{ x.source_value }}</td>
</tr>
</tbody>
</table>
Is it possible to remove all the hard coding and have the scope variable determine the column names along with and data ?
Quick Edit:
heres a quick look at the data in its current state.. I need the key in the key:value elements of this object. Is there a way to get those values with pure javascript ?

My understanding is that you don't know what the columns are beforehand. So, you need the keys of the first object to understand what the columns are.
angular:
var obj = data[0];
$scope.columns = Object.keys(obj).filter(function(key) {
if (obj.hasOwnProperty(key) && typeof key == 'string') {
return key;
}
});
$scope.format = function(str) {
return str.replace('_',' '); //do the rest of the formatting here.
}
html:
<table class="table">
<thead>
<tr>
<td ng-repeat="column in columns">
{{format(column)}}
</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="datum in data">
<td ng-repeat="column in columns">
{{datum[column]}}
</td>
</tr>
</tbody>
</table>
Edit: Took the filter on the keys from another answer as good practice when getting keys from objects.

Why not use a own model for your headlines to iterate through it?
Let headlines be an array, holding up all possible headlines, one for each index.
<table class="table">
<thead>
<tr ng-repeat="headline in headlines">
<th>{{ headline }}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in data">
<td>{{ x.Arup_Mnemonic }}</td>
<td>{{ x.organism }}</td>
<td>{{ x.test }}</td>
<td>{{ x.result }}</td>
<td>{{ x.source }}</td>
<td>{{ x.source_value }}</td>
</tr>
</tbody>
</table>

A possible solution (please note that this is not tested):
// in controller
$scope.headlines = Object.keys(data[0]).filter(function(key) {
if (data[0].hasOwnProperty(key) && typeof key == 'string') {
return key;
}
});

<tr data-ng-repeat="(key,val) in gridData">
<th></th>
<th data-ng-repeat="col in columns" data-ng-init="CurrKey = col.key">{{val[CurrKey]}}
</th>
</tr>

Related

Multiple table rows as single component

What would be a way to have multiple table rows in a single Angular component ?
I would like to display two rows per item of a given list, and have it in an HTML table.
I tried using ng-template with a component as attribute to avoid having a component tag breaking the table flow, but the input won't work in that case. Ideally I'm looking for a way to remove the component tag from the dom...
<table>
<thead>
<th>Name</th><th>City</th>
</thead>
<tbody>
<ng-container app-located-person
*ngFor="let person of persons"
[person]="person">
</ng-container>
</tbody>
</table>
App located person
<tr>
<td>{{ person.name }}</td>
<td>{{ person.city }}</td>
</tr>
<tr *ngIf="details">
<td>Last connection</td>
<td>{{ person.lastConnection }}</td>
</tr>
I finally made it not to break the table dom flow by using display: table-row-group; on the component node :)
Why don't you include the tr's inside the ng-container tag?
<table>
<thead>
<th>Name</th><th>City</th>
</thead>
<tbody>
<ng-container
*ngFor="let person of persons"
[person]="person">
<tr>
<td>{{ person.name }}</td>
<td>{{ person.city }}</td>
</tr>
<tr *ngIf="details">
<td>Last connection</td>
<td>{{ person.lastConnection }}</td>
</tr>
</ng-container>
</tbody>
</table>
If you want to use a component:
<table>
<thead>
<th>Name</th><th>City</th>
</thead>
<tbody>
<ng-container
*ngFor="let person of persons">
<app-located-person [person]="person"></app-located-person>
</ng-container>
</tbody>
</table>
Try the following:
<table>
<thead>
<th>Name</th><th>City</th>
</thead>
<tbody>
<ng-container *ngFor="let person of persons">
<tr>
<td>{{person.name}}</td>
<td>{{person.city}}</td>
</tr>
<tr *ngIf="person.lastConnection">
<td>Last connection</td>
<td>{{person.lastConnection}}</td>
</tr>
</ng-container>
</tbody>
</table>
Stackblitz: Link

Appending from one table to another then deleting/manipulating data

I am trying to add from one table to another with .click and i got it to work
but now when i try to use the search field on the top table it clears the appended rows from the bottom table
I need to get these to start generating a table under it so that i can delete them all together
$(document).ready(function(){
$("#student-table2 tbody tr").click(function(){
$(this).css("background-color", "#f4a941")
.appendTo("#student-table3 tbody");
});
$("#student-table2").DataTable();
$("body").on("click", "#student-table2 tbody tr", function(){
$("#student-table3").data("stu-id", $(this).data("id"))
.data("stu-name", $(this)
.data("name"));
});
$("#access-table").DataTable();
$(".datetimepicker").datetimepicker({
format: 'MM/dd/yyyy hh:mm:ss',
});
});
Like i mentioned, it seems i can add the data to the table , but it wont store the row i select on table 2 when i use the search field atop the first table
I was thinking , maybe i can just have jquery generate the entire table with table placeholders already set in place? and not have it at all in HTML like i do, see under, i have student-table and student-table2 stacked
Here's my HTML
{% include "core/header.html" %}
{% load widget_tweaks %}
<section class="ids-section form-section">
<h2>{{ title }}</h2>
<h2> All Students </h2>
<table id="student-table2" class="table table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
<th>School</th>
<th>License Plate</th>
<th>Active</th>
<th>Code</th>
<th>Added</th>
</tr>
</thead>
<tbody>
{% for stu in students %}
<tr data-id="{{ stu.id }}" data-name="{{ stu.name }}">
<td>{{ stu.name }}</td>
<td>{{ stu.school }}</td>
<td>{{ stu.license_plate }}</td>
<td>{{ stu.active }}</td>
<td>{{ stu.code }}</td>
<td>{{ stu.created }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<h2> Selected for Delete </h2>
<table id="students-table3" class="table table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
<th>School</th>
<th>License Plate</th>
<th>Active</th>
<th>Code</th>
<th>Added</th>
</tr>
</thead>
<tbody>
<br>
<tr data-id="{{ stu.id }}" data-name="{{ stu.name }}">
<td>{{ stu.name }}</td>
<td>{{ stu.dealership }}</td>
<td>{{ stu.license_plate }}</td>
<td>{{ stu.active }}</td>
<td>{{ stu.code }}</td>
<td>{{ stu.created }}</td>
</tr>
</tbody>
</table>
</section>
</div>
{% include "core/footer.html" %}
I figured out that i actually was on the right track, i didnt know .dataTables() was a bootstrap marker for the tables so i simplified the remfunc.js file to
/* Main part- on click adds to second table */
$(document).ready(function(){
$("#student-table2 tbody tr").click(function(){
$(this).appendTo("#student-table3 tbody");
});
/* Formats the table to coginate,
gives it an inputFilter and wraps it.
*/
$("#student-table2").DataTable();
});
$("#access-table").DataTable();
$(".datetimepicker").datetimepicker({
format: 'MM/dd/yyyy hh:mm:ss',
});
});
with and html file that looked like
{% include "core/header.html" %}
{% load widget_tweaks %}
<section class="ids-section form-section">
<h2>{{ title }}</h2>
<h2> All Students </h2>
<table id="student-table2" class="table table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
<th>School</th>
<th>License Plate</th>
<th>Active</th>
<th>Code</th>
<th>Added</th>
</tr>
</thead>
<tbody>
{% for stu in students %}
<tr data-id="{{ stu.id }}" data-name="{{ stu.name }}">
<td>{{ stu.name }}</td>
<td>{{ stu.school }}</td>
<td>{{ stu.license_plate }}</td>
<td>{{ stu.active }}</td>
<td>{{ stu.code }}</td>
<td>{{ stu.created }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<h2> Selected for Delete </h2>
<table id="students-table3" class="table table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
<th>School</th>
<th>License Plate</th>
<th>Active</th>
<th>Code</th>
<th>Added</th>
</tr>
</thead>
<tbody>
<br>
<tr data-id="{{ stu.id }}" data-name="{{ stu.name }}">
<td>{{ stu.name }}</td>
<td>{{ stu.dealership }}</td>
<td>{{ stu.license_plate }}</td>
<td>{{ stu.active }}</td>
<td>{{ stu.code }}</td>
<td>{{ stu.created }}</td>
</tr>
</tbody>
</table>
</section>
</div>
{% include "core/footer.html" %}

Angular2 Clickable table row, except last cell

I have a table with data, and my last cell is a delete button to be able to delete a row.
The problem I'm facing is that my rows are clickable which take me to another page to edit the element, and so when I click the delete button, it deletes the element but also takes me to the edit page.
Here is my code :
<table class="data-table-format">
<thead>
<tr>
<th>id</th>
<th>Maker</th>
<th>Model</th>
<th>Year</th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let car of pagedItems" (click)="editCar(car)">
<th>{{ car.car_id }}</th>
<td>{{ car.car_maker }}</td>
<td>{{ car.car_model }}</td>
<td>{{ car.car_year }}</td>
<td><i class="material-icons" style="color:red" (click)="deleteCar(car.car_id)">delete_forever</i></td>
</tr>
</tbody>
</table>
Any suggestion on how to do it with angular/typescript ?
You can try this. This is not jQuery
<tbody>
<tr *ngFor="let car of pagedItems" (click)="editCar(car)">
<th>{{ car.car_id }}</th>
<td>{{ car.car_maker }}</td>
<td>{{ car.car_model }}</td>
<td>{{ car.car_year }}</td>
<td><i class="material-icons" style="color:red" (click)="$event.stopPropagation();deleteCar(car.car_id)">delete_forever</i></td>
</tr>
</tbody>

Vue.js - Change the class of a single table row in v-for

I am displaying a table of customers generated dynamically using v-for. Each row has a button that adds the customer ID in an object that will be sent to the API. The thing is, I want to add the Bootstrap .success class to the clicked row, so the user knows that the customer has been selected, but I can only achieve that all the rows in the table get the .success class. Also, I would like that when the user clicks another customer, the selected customer loses the .success class.
Here's my code:
<table class="table table-responsive table-striped table-hover">
<tbody>
<tr v-for="customer in customers">
<td><button class="btn btn-default" v-on:click.prevent="selectCustomer(customer.id)"><i class="glyphicon glyphicon-ok"></i></button></td>
<td>{{ customer.first_name }}</td>
<td>{{ customer.last_name }}</td>
<td>{{ customer.oib }}</td>
<td>{{ customer.phone }}</td>
<td>{{ customer.email }}</td>
<td>{{ customer.street }} {{ customer.city }}, {{ customer.country }}</td>
</tr>
</tbody>
export default {
data(){
return {
customers: [],
selectedCustomer: ''
}
},
methods: {
selectCustomer(id, clicked){
this.selectedCustomer = id;
console.log(this.selectedCustomer);
}
}
Thank you!
Binding success class to the row based on selectedCustomer value should help you achieve what you're looking for. Something like this, untested:
<table class="table table-responsive table-striped table-hover">
<tbody>
<tr v-for="customer in customers" v-bind:class="{'success': (customer.id == selectedCustomer)}">
<td><button class="btn btn-default" v-on:click.prevent="selectCustomer(customer.id)"><i class="glyphicon glyphicon-ok"></i></button></td>
<td>{{ customer.first_name }}</td>
<td>{{ customer.last_name }}</td>
<td>{{ customer.oib }}</td>
<td>{{ customer.phone }}</td>
<td>{{ customer.email }}</td>
<td>{{ customer.street }} {{ customer.city }}, {{ customer.country }}</td>
</tr>
</tbody>

jQuery traverse upwards and find

I have a table which uses jQuery sortable to drag-drop and sort elements in a table.
When dropping an element into a "sortable-row" , I want to read the data-id from the previous "section-row" .
I've managed to achieve this for when the row is dropped in the row directly beneath a "section-row", or 2 levels below.
First level down :
($(ui.item[0]).closest('tr').prev('.stop-row').data('id');
Second level down :
$(ui.item[0].previousElementSibling).closest('tr').prev('tr.stop-row').data('id');
The problem is that a "section" can have any amount of rows added to it, so I need some kind of loop which will check if the previous element is a "section-row", if not, check on the following previous.
How do i achieve this with jQuery?
My Table:
<table class="table table-bordered table-responsive">
<thead>
<tr>
<td>Assignment</td>
</tr>
<tr>
<td>Type</td>
</tr>
<tr>
<td>Time</td>
</tr>
<tr>
<td>Level</td>
</tr>
</thead>
<tbody class="sortable">
<tr class="section-row" data-id="{{ id }}">
<td> Section-{{ id }}</td>
</tr>
<tr class="sortable_row">
<td>{{ assignment }}</td>
<td>{{ type }}</td>
<td>{{ time }}</td>
<td>{{ level }}</td>
</tr>
</tbody>
</table>
You can do this:
$(ui.item[0]).closest('tr').prevAll('.section-row:first').data('id');
It will go to the closest tr, search all preceeding tr and stop at the first one with the class .section-row.

Categories

Resources