alfajango / jquery-dynatable

A more-fun, semantic, alternative to datatables
http://www.dynatable.com
Other
2.77k stars 363 forks source link

Records out of order whilst using Chrome #225

Open Samuel1989 opened 8 years ago

Samuel1989 commented 8 years ago

Hey Guys,

I have noticed that the original order of json data is not being preserved whilst using Chrome, however, it is correct when using FireFox and Internet Explorer.

Is there an obvious fix for this?

Thank you, Sam

tehandyb commented 8 years ago

I'm having the same issue with Chrome. I'll page back and forth between pages and the some of the records will change. I wonder if the issue has to do with using Array.sort, where apparently Chrome, Firefox and Safari use different sort algorithms and Chrome's sort algorithm may return different results each time. That's the impression I got from reading this http://blog.rodneyrehm.de/archives/14-Sorting-Were-Doing-It-Wrong.html

JangoSteve commented 8 years ago

Can anyone provide a live example of this happening? I don't believe it should have anything to do with the default sort algorithm of the browser, as the way dynatable handles this is by creating a dynatable-original-index attribute to each record in the json collection and setting it to whatever the index is of that record within the original order of the records.

So, it's literally sorting by an array of index integers, which should be both consistent and correct, no matter what the default sort algorithm of the browser is.

If someone has a live example of this happening, maybe we can pinpoint what's going wrong (i.e. are the dynatable-original-index attributes getting set incorrectly, or not at all, or is something wrong with the actually sorting, or something completely different?

tehandyb commented 8 years ago

I have a page where I'm using the dynatable here at the bottom: http://mrr.devtechlab.com/mrr-dashboard.html If you page next, and then previous, the second record in the table will keep changing. Also sorting by the number column, and then clicking next a few times will show issues with non numeric records randomly popping up. I am using the dynatable wrapped inside a DC.js container which has it's own render lifecycle but I don't think that should affect just going next and previous in the table.

JangoSteve commented 8 years ago

@tehandyb, I took a look, and if you open the developer console on your page and inspect the records for the current dynatable page, e.g. the first record:

$('#project-table-id').data('dynatable').settings.dataset.records[0]

There is no dynatable-original-index property of the record, which means it's not getting added. Taking a closer look at dynatable, this property is added and set here in the records.getFromTable() function, which means we only add the default sort order when the records are read in from the HTML table when the page loads on document ready.

So, if you're populating the records directly yourself from a JSON collection, dynatable doesn't mess with the properties of the JSON collection; since dynatable isn't responsible for building the JSON like it is when it has to build the collection from the table rows in the initial HTML, it plays it safe and doesn't mess with your JSON (e.g. by adding meta-data) collection that you explicitly passed in.

Of course, that seems to lead us to our current issue where it doesn't seem to keep the order as you're paging back and forth. What's really weird though is that when you page back and forth, all dynatable is doing is slicing the records from that page out of the settings.dataset.originalRecords array of JSON records. That shouldn't change (it's the pristine copy of your data that never changes, no matter what paging, sorting, filtering, etc. you do with the working copy of the records at settings.dataset.records). In other words, Dynatable shouldn't need any meta-data here to determine the original order, because a JSON array in JavaScript retains its order according to RFC 7159.

What I can't figure out is why the order of records in settings.dataset.originalRecords seems to be changing in your live example, every time I click to page 2 and then back to page 1:

var dynatable = $('#project-table-id').data('dynatable');
//=> undefined
dynatable.settings.dataset.originalRecords[1].project_name
//=> "Value Chain activity."
dynatable.paginationPage.set(2); dynatable.process()
//=> undefined
dynatable.settings.dataset.originalRecords[1].project_name
//=> "Incentives Driving Economic Alternatives for the North, East, and West (IDEA-NEW)"

Given that the order of a JSON array is preserved unless you actually change the array, and given that there is only one line in the entire dynatable source that sets the settings.dataset.originalRecords array, which is in the init() function on this line (and that it's done in a way that creates a deep-cloned copy, so changing anything in dataset.records has no effect on dataset.originalRecords), my guess is that there is some code somewhere outside of dynatable that is changing $('#project-table-id').data('dynatable').settings.dataset.originalRecords each time the page is set or dynatable.process() is called. There are several event hooks that could be bound to by external libraries to accomplish this.

To answer the original question in this ticket, I don't know that there's any obvious fix, as I'm not sure that this behavior is being caused within the dynatable code. Hopefully this helps though and can lead someone to the solution. If anyone can do a bit more research and determine that there is something in dynatable causing this, or maybe just come up with an isolated example e.g. on jsfiddle or something, I'd be happy to figure out a fix.

EDIT

Also, if it further helps anyone debug this issue, what happens at the beginning of every sort/page/filter operation is that the working recordset is reset to the original recordset, and then the sorts, page slicing, and filters are applied. Even there, you can see the settings.dataset.originalRecords is left untouched.

pandorawombat commented 8 years ago

Jango Steve - thank you so much for helping me finally figure this out. Forcibly adding the attribute 'dynatable-original-index' to each of the records I was generating in my JSON fixed this problem in Chrome. I was experiencing this exact problem in Chrome only - all other browsers were honoring the exact order in which I was sending the records. Perhaps someone should consider amending the documentation to explain that if you are generating your OWN JSON and doing sorting on the server side, you should add a 'dynatable-original-index' value to each record in the JSON you generate and use that to index them in order? Because that certainly fixed the problem. As it stands, the documentation about the specifics of doing the server-side JSON generation was a bit sparse and I had to do a lot of trial-and-error before I could get most of it to work as expected.

shanecutts commented 7 years ago

Is anyone able to provide more information on this? I'm still experiencing this issue in Chrome only, but unsure of what 'dynatable-original-index' is or how/where to use it.

ben2613 commented 6 years ago

Hey Guys, I guess I find the problem. In resetOriginal, settings.dataset.originalRecords is assigned to settings.dataset.records Then when settings.dataset.records is sorted, settings.dataset.originalRecords is also sorted.

This can be fixed by settings.dataset.records = $.extend(true, [], settings.dataset.originalRecords) || [];

angrymarker commented 4 years ago

I had the same problem - JangoSteve's comment helped a ton. I just added the "dynatable-original-index" key to the json object, starting at 0 and going up and this solved it.

Thanks!