How to do multiple levels of nested tables in JQuery/HTML - javascript

I'm trying to create tables with multiple levels of nesting which can be expanded/collapsed. So the main table has rows which can be expanded to show the child rows in the middle of the table, who themselves can be expanded.
Each table needs to have their own headers and preferably the columns would all line up but have the start of the child tables be slightly indented as I try to show below.
For example:
ColHeader1 ColHeader2 // main table headers only shown at the top
record1 ...
ChildHeader1 ChildHeader2 // child headers shown for each table
childrec1 ...
SubChildHeader1 SubChildHeader2 // child headers shown for each table
subchildrec1 ...
childrec2 ...
record2 ...
ChildHeader1 ChildHeader2 // child headers shown for each table
childrec5 ...
record3 ...
I've tried to create the code by expanding a sample I found, but it doesn't work for expanding the inner most table. The code can be found here: http://jsfiddle.net/afsz5brg/
The end product will be in a ASP.Net MVC app, but for now I'm just trying to get it working in javascript/JQuery so that hopefully I can just change the data being sent to it.
I'm happy to consider alternative ways for doing it or be told if any of the code is doing something bad/deprecated.

There are a couple of bugs I have discovered in your code. I would list them one by one.
1) Your assumption of registering a callback on $('#detailsTable tbody td').on('click', ...); and that being called on every new instance of that table that gets created is wrong.
If jQuery Data Table was internally cloning the #detailsTable element, then your code would work. But that isn't the case as you are retrieving the HTML markup of #detailsTable and returning it to fnOpen like so: oTable.fnOpen(nTr, fnFormatDetails(iTableCounter, detailsTableHtml), 'details'); so the callback never gets called.
You need to register a callback to the newly created details table. Check out this JsFiddle to see how.
2) I think I also spotted another bug while reading your code. I haven't fixed it as I was not sure if I was right or not. In the callback for your #detailsTable, you call fnFormatDetails() instead of fnFormatSubDetails() like so oInnerTable.fnOpen(nTr, fnFormatDetails(iSubTableCounter, subDetailsTableHtml), 'subdetails'); No one is calling fnFormatSubDetails() at the moment. Please check if this is a bug or not.

Related

Why is datatable sort wiping data from table

I have 2 tables in my view both using dataTables , first table works fine but second table when i try to sort data with headers is wiping data from table.
Demo
This is how i defined dataTables for my both tables
to get the idea i used screenshot
Code
here is my second table code to define datatables
var table = $("#customerTable").DataTable();
any idea what is wrong?
If you need more code just let me know i'll update the question.
Update
Based on code i shared in jsFiddle (link in comments) if i move my second table definer to success function of my first table like:
// rest of function then at the end having like...
var otable = $("#customerTable").DataTable();
}
});
});
$("#data_table2 tbody tr:first-child").trigger("click");
});
It will allow me to sort my second table data BUT it replace my data with first data (confused? :) see GIF below)
To see Video version click here
Explanation:
as you see my first selected row has returned data in second table which has value of nullewqrf2wrtf but my second selected row the returned data has value of null
when i click sort on my second data it returns data of my previous selected row nullewqrf2wrtf
Solved
The solution for me was:
Moving my update function completely to my first table success
function
Double check my other functions in that success function and get
misspelled var's
With fixing my var's misspelled id's etc. now i can sort my data and issue in my update part has fixed as well.
Hope it can help others as well.

jQuery adding an <tr> line when loading / jQuery and PHP

I have a table built that comes from data in the server. I have a button that will activate or deactivate a category. If the category is active, it will show the action of "inactivate" and so the way around. So I need the table to refresh so when the user clicks activate it will automatically switch. I am almost done with this. Issue is that when I use the jQuery load function, it seems like it's adding one additional line instead of just refreshing it.
This is my code, I send a request to the server, then wait for it to finish to load.
My code is below:
async function cambiarStatus(tipo_transa, ruta, estadoCat, idCat, div, file)
{
await modStat(tipo_transa, ruta, estadoCat, idCat);
$(div).load(file+div);
}
With the table I built with PHP I only have one ... but then it goes and another one which ends up in making the table go nuts.
Many thanks for your help!!!!!
I'm going to have to guess that the value of the variable div is something like #c-i-1, or # plus the id of whichever table row you're trying to replace.
In that case, the code as written is telling jQuery to replace the content of the table row, not the table row itself, with the matching table row loaded from the file. That's going to cause exactly the problem you're showing, a table row being put inside a table row.
You need to replace the table row itself with the retrieved table row. For that, as convenient as jQuery's load method is, it doesn't offer the functionality you need.
Something like this should work better:
$.get(file, table => {
const row = $(table).find(div);
$(div).replaceWith(row);
});

Add dynamic column to table in smart-table [angularjs]

I needed a little help over here on adding dynamic columns to table and I'm using smart-table project https://lorenzofox3.github.io/smart-table-website/
Please look at plunker
https://plnkr.co/edit/uTDa6hfwdgGtGWkYqL7S?p=preview
Click on add new column, it will update the table header, but I can't update the td element because I haven't created or binded any td element for new column.
Need help on two things.
1) Any number of new columns might come in future from server dynamically, so I can't bind any element statically in html like I did right now.
2) This is a little long one(I want to create a only one header as MV and in colspan I want current and next) and How do I accomplish that one ? If I divide like that, how do I go frame the data ?
Additional Note on Question 1: I have tried dynamically showing the data in table. please look at line 27 in index.html. But again, If I go with this approach, the values get binded to different different columns since, data's are framed dynamically on controller. To be simple, there is no guarantee that data will be in in this order.
(SNo, companyName, companyFullName, MarketValueCurrent, MarketValueNext, QuarterCurrent, QuarterNext)
companyName might come first or at last. If I go by dynamic looping using ng-repeat, it binds MarketValueNext in first column, then companyName, etc in whichever the order the data is coming.
Thanks in advance.

Remove row from JQuery DataTable - but it returns as soon as the table is redrawn. Is my .JSP data source the cause?

I have a button in each row, when pressed that row is removed from one table, and added to another table:
var row = $(this).closest("tr").remove().clone()
$('.my-other-table-class').append(row);
and at first it appears to work perfectly, the row is removed from one table and added to another, but when I force a re-draw (by changing the sorting of one of the columns, for example) all the rows are back as they were, and the buttons no longer work. This is the case for both the removed rows, and the rows added to the other table.
Is this because I'm using a .jsp table as a data-source? Would this work correctly if I dynamically added all the rows to the table using JavaScript at load-time, or if I used a modelMap collection as a data-source?
Thanks a lot for any advice.
Solution for future googlers - I have no idea how my google-Fu did not find the answer, I had all the right keywords!
In short:
I was doing this to add:
$('.my-other-table-class').append(row);
And this to remove:
var row = $(this).closest("tr").remove().clone()
but I should've been doing this add:
$('.my-other-table-class').dataTable().fnAddData([$(this).attr("data-val1"), "var2"]);
And this to remove:
$('.my-table').dataTable().fnDeleteRow($(this).closest('tr')[0]);
With more detail:
What I am really doing here is modifying the DOM with JQuery (well duh, but I'm really new at this, remember...) - I figured the DOM was the data-source for my table, so that made sense? The table is redrawn, it rereads the DOM and updates? Well not really.
In order to be dynamic, if you use DOM (in other words HTML, or in my case .jsp rendered as HTML) as your data-source, upon initialization, datatables will copy all that information into a JavaScript array.... so rather then my original thought:
"The DOM is not updating correctly, and that issues is propogating up in to my table... because HTML is static...or something?"
it turns out the actual problem was:
"I was updating the DOM, but the real data source was a JavaScript array I wasn't seeing. So upon redraw, this array was overwriting the DOM and my changes were being lost."
TL;DR: Use the Data-tables API and don't modify the data-source directly, unless you need to.
If the event handlers are one of the issues, it may help to set up your event handler like this:
$("#myTable").on("click", "button.moveMe", function(e) {
e.preventDefault();
var row = $(this).closest("tr").remove().clone()
$('.my-other-table-class').append(row);
});
This will set a handler on the table that has id="myTable". The handler will look for click events on buttons with the "moveMe" class. It will catch the event on rows that are added later, as well as the rows that exist when this hook is created.
Reference: http://api.jquery.com/on/

How do I hide jQuery changes to the page until all processing is complete?

I have a page with a large table. At the top of the table I've added several filters for eliminating rows in the table. When someone changes a filter, jQuery processes the changes and shows/hides rows in the table that match the filters.
The processing code starts by showing all the rows in the table. Then, it steps through each filter, and wherever necessary, it hides rows in the table. So, each time the user changes a filter, they will see the entire table momentarily and then watch as the rows disappear until the filtering is complete.
Is there a JavaScript or jQuery function for delaying output to the browser until all processing is complete?
You can clone the table, perform whatever operations you need to on the clone, and replace the original table once you're done:
var newTable = $("#yourTable").clone();
//Do whatever you need to do to newTable
$("#yourTable").replaceWith(newTable);
Here's a working example.
Here is a crude example: http://jsfiddle.net/YNZJf/
Basically use jquery to change the html, then once finished set it back to you table.
$tmp = $( $('#table').html()));
$tmp.filter(); // do work;
$('#table').html($tmp.html());
I know you've already accepted an answer, but cloning the table is not how I would choose to implement this. I'd prefer to change the code that modifies the table to not modify it directly. Instead, create an output array that contains the list of modifications you will make to the actual visible table. Then, run your code and have it create this output array (which rows are shown and hidden or any other modifications). Then, when the lengthy part of the code is all done and you have this output array, you simply loop through the final output array and apply the changes. If this last part is all done in one synchronous piece of JS, the viewer will not see the intermediate steps, just the final result.
You should note that there are some characteristics of cloning and operating on it before it's inserted into the document to be aware of:
There could be issues cloning and operating on something with ids assigned to elements in it (since you can only have one object with a given id).
Non-jQuery event handlers may not get copied onto new objects.
You should specify the appropriate parameters to the .clone([withDataAndEvents], [deepWithDataAndEvents]) function
If your table is large, cloning might be slow (lots of duplicate objects and properties to create).
If any of your operations to modify the table assume it's in the document, they might not work on the cloned table until it's inserted.

Categories

Resources