fnGetData(): Can I get the actual object instance behind the row?

fnGetData(): Can I get the actual object instance behind the row?

BLSullyBLSully Posts: 24Questions: 1Answers: 0
edited August 2012 in DataTables 1.9
With fnGetData(row), I get back an Object with all my original properties + whatever other custom columns I've defined.

With more and more of my code moving to arrays of complex objects rather than 2d arrays of data, I want to be use the methods available on my 'typed' JS Objects.

[code]
function GameUser() {
this.name = 'someridiculoushandle';
this.score = 15;
}
GameUser.prototype.incrementScore = function( ) { this.score += 1; return this; }

//paraphrased....
//bind array of GameUser to DataTable
aGameUsers = [new GameUser()];
dt.fnAddData(aGameUsers);
//click on row
data = dt.fnGetData(row)[0];
if(data instanceof GameUser) { //this is false
//i want to be able to do this:
data.incrementScore();
}
[/code]

So, can I get to my original objects somehow (either using fnGetData or otherwise)? I have factory methods that convert 'plain' objects into instances, but it seems like a waste when those instances already exist somewhere. I've also tried caching my objects in another array and then looking them up when I get the row data from fnGetData....but that makes me feel incompetent ;)
«1

Replies

  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    Unfortunately you've hit upon, what I would say, is my biggest mistake in the development of DataTables. The root of the problem is that I originally wanted fnRender to be able to alter the data for filtering etc, so it wrote the return value back to the data source object - but I didn't want the data supplied to be overwritten, so I do a slice() or an $.extend on the data source (array / object) and take an independent copy.

    That's wrong :-(.

    fnRender should never has existed and it causing a bit of hassle now, but unfortunately it is also very widely used, so it can't simply be removed at the drop of a hat.

    If you look in _fnAddData you will see the slice / $.extend and you can remove that - your method should then work. It means modifying the ore until I've got a more permanent solution - which I hope to have as part of 1.10.

    Allan
  • BLSullyBLSully Posts: 24Questions: 1Answers: 0
    edited August 2012
    Allan,

    Thanks for the clear explanation. And I understand about fnRender... if it disappeared at the drop of a hat we would probably just lock the doors to the office and go home ;) Too much of our code from the past 2 years depending on it ;)

    I will look at the source of _fnAddData and maybe fork on github.

    Thanks again.
    -Brendan
  • rewenrewen Posts: 74Questions: 2Answers: 0
    +1 on this issue.

    I've been maintaining multiple lists and it's no fun. If my own data could instead be shared with datatables, instead of copied, that would be fantastic. It would make life so much easier and probably improve performance (or at least memory consumption). Right now I've got a lot of work-arounds going on to keep things in sync, and things are more complicated than I would like..

    I'd also love to be able to update a row that hasn't yet been rendered (bDeferRender). Right now if a row isn't rendered and I try an fnUpdate on it, it doesn't seem to take the new value. But that's another issue entirely I guess..
  • BLSullyBLSully Posts: 24Questions: 1Answers: 0
    Allan,

    I've been thinking about what you said and I think a reasonable workaround to this issue might be to keep the slice/extend in there, but keep a reference to the original data source available as well....in my head, something like fnGetOriginalData(row)

    I'm not sure what other impacts this might have.... I'm thinking the internals of keeping both DT's 'source' and the original data in sync during fnUpdate/fnDeleteRow operations might get tricky... maybe this isn't such a good idea after all.

    Dunno, I'll look sometime when I can think straight... or if you can think of something more appropriate?
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    @BLSully: I think an immediate solution would be to provide an initialisation parameter for DataTables which would bypass the slice() in _fnAddData. Then you would be working with the original data - but you must be aware if that is the case, and you are using the loathsome fnRender that your data will get nuked...

    Been thinking about this all day, and I'm very tempted to drop fnRender in the next major update (v1.10), with a solid migration path using mRender and mData being provided. v1.10 development should really kick off in November (time set aside for DataTables development :-) ), so I've got until then to kick the idea around, and I realise that it will cause some upgrade pains - but it is a major version change, so if its going to happen before DataTables 2, then this might be the ideal time.

    All thoughts are welcome!

    @rewen: Absolutely - it is also part of the reason that integrating DataTables with Backbone or Knockout is a real pain at the moment, since the reference is lost.

    Regarding the issue on fnUpdate and bDeferRender - that should actually work. Could you open a new thread on that, and link to a test case showing the problem please?

    Thanks,
    Allan
  • BLSullyBLSully Posts: 24Questions: 1Answers: 0
    Allan,

    An initialization parameter makes much more sense. I will investigate that this weekend.

    I've been using mRender exclusively in my latest work and I find it much more friendly than fnRender, even disregarding what's going on internally. Not had a chance to use the [, ].prop syntax, but that looks exciting too ;)

    Thanks for your input.
  • rewenrewen Posts: 74Questions: 2Answers: 0
    edited August 2012
    Allan,

    Disregard my comment about fnUpdate and bDeferRender. I could've sworn that aoData was reverting to the pre-update state after fnDraw but now it's not doing that.. I'm not sure why it didn't work for me at the time, but it's working fine now. I've even tried on older versions and it's working there, too.
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    @BLSully - Excellent to hear that mRender is working well for you!

    @rewen - Thanks for the update. Good to hear it is working after all :-)

    Allan
  • BLSullyBLSully Posts: 24Questions: 1Answers: 0
    @rewen: I forked DataTables and added in this functionality as suggested by @allan. It has worked in my current application, but might warrant some more testing.

    https://github.com/BLSully/DataTables/

    Commit of interest: https://github.com/BLSully/DataTables/commit/3461d5acadd2386566cc4f6267ea6b32d13bca61

    @allan: if you know of some other place this boolean might need to be checked, I'd definitely be interested in continuing to maintain this fork until your real solution ends up in 1.10 or 2.0
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    @BLSully - awesome stuff. The method you've used looks ideal in the comment, one just one little point is that the jquery.dataTables.js file is actually a generated file - it is built from the files in media/js - so changes should be made in those files rather than the 'main' file - otherwise the next build will nuke the changes.

    Still thinking about fnRender... If fnRender is dropped in 1.10 in favour of mRender / mData, then there will be no slice / $.extend required, so the behaviour introduced by your flag would be the default, and only, behaviour. I'm going to experiment a bit more before committing to go down that path, but I think it is the correct one to take.

    Regards,
    Allan
  • BLSullyBLSully Posts: 24Questions: 1Answers: 0
    @allan: Good point on the generated file. Didn't even occur to me as I'm so used to just using the jquery.dataTables.js file. I'll fix that this weekend.
  • BLSullyBLSully Posts: 24Questions: 1Answers: 0
    @allan: Any tips for configuring an ubuntu system to build the source? I've installed closure compiler, got jshint installed to a location in $PATH.

    I made the changes to the source files as you suggested above, but now if If I run ./make.sh in the scripts folder, it fails on jshint (unable to find config). If i run "./make.sh debug", I get the jquery.dataTables.js output file, but it's just the closure, with no JS inside (and a ton of "No such file or directory" errors).

    I don't have any experience with this kind of build process and I can't find any posts or tutorials on how to get my environment setup correctly to use your build scripts.

    Thanks. -B
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    If you run:

    [code]
    sh -x make.sh debug
    [/code]

    you will get a complete dump of what bash is trying to do and it will hopefully show some errors (although errors should show in the console anyway). I'm surprised make.sh debug doesn't work - that reasonably simple file concatenation. Perhaps you can dump the output from sh -x into paste bin and link to it?

    Allan
  • BLSullyBLSully Posts: 24Questions: 1Answers: 0
    @Allan: http://pastebin.com/yZ9grXwp

    Thanks for the help. I'm going to guess the "Cannot remove core/core.data.js\r.build" errors are the issue, but where does the r.build come from? (or ignore me if i'm chasing down the wrong trail) ;)
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    Ah - are you using bash as your shell, or something else?

    > echo $SHELL

    should tell you. I've only tested my script in bash and there are a few bash specific things in there...

    Allan
  • BLSullyBLSully Posts: 24Questions: 1Answers: 0
    @Allan: Ah.... Ubuntu uses 'dash' I believe. I'll install bash and see what happens. I pretty much just built that VM for the purposes of building DT, so I can mangle it however is needed to get DT to build.

    Thanks, I'll get back to you.
  • BLSullyBLSully Posts: 24Questions: 1Answers: 0
    hmmm... nevermind. It's claiming it's bash.

    brendan@durin:/media/sf_GitHub/DataTables/media/js$ echo $SHELL
    /bin/bash
  • rewenrewen Posts: 74Questions: 2Answers: 0
    @BLSully I'll probably be giving your fork a try soon :)

    Just curious.. with this modification everything DataTables does will refer to my original data, correct? I mean not only fnGetData but also fnUpdate, mData, mRender, fnCreateRow, etc?

    I assume that with the change each row's _aData properties will simply become references, which is exactly what I want, and therefore all of DataTables functions will be referring to my original data at all times.
  • rewenrewen Posts: 74Questions: 2Answers: 0
    Guys, is it just me or is 1.9.4 already functioning with my data references in-tact?

    Actually, before posting that I decided that I should just check the source code before myself to make sure.. and I found out that when you do a slice() it actually isn't creating an independant copy of the array items, at least not if they are Objects.

    Ex:
    fnAddData([
    ['string', Object, Object, Object]
    ['string', Object, Object, Object]
    ['string', Object, Object, Object]
    ]);

    That results in the Objects being referenced but the strings being copied. I can actually use that to my advantage (saves me from having to use BLSully's fork) but I don't imagine it's acting as you expected.

    To make sure that's in fact how it works I was able to modify the data in one of the _aData Objects for a row and the change was reflected my original data as well. If I change one of the _aData strings then it's only affecting DataTables and my original data remains with the original string.
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    > I found out that when you do a slice() it actually isn't creating an independant copy of the array items, at least not if they are Objects.

    Yes you are absolutely correct. The array is a copy, but since the "pointers" are pointing to the same objects as before, the reference is retained. A quick of Javascript, but it can be useful.

    If you want to live on the bleeding edge, I've committed the change for DataTables 1.10 that makes the change to not copy the data (you can grab it from Github).

    Allan
  • rewenrewen Posts: 74Questions: 2Answers: 0
    Seems I never noticed your reply.

    I am working on another project where the previous coder used BLSully's solution but I've run into a snag.

    If I change the data for one of the rows and I want to have that one row redrawn.. I have to do an fnUpdate on it, passing in the object that the row is already based upon.

    It turns out that if the object being passed in, is not a 'plain' object (in my case it's an instance of something else), fnUpdate breaks.

    As a workaround I can probably just tell it to fnUpdate the first column with the value that it already is. But is there a better way? Without redrawing the entire table, ideally.
  • girishmrgirishmr Posts: 137Questions: 0Answers: 0
    edited October 2012
    Can you not use fnStandingRedraw - Draws the row which was updated

    Ref : http://www.datatables.net/plug-ins/api

    FYI Link : http://www.datatables.net/forums/discussion/12403/are-it039s-possable-to-redraw-not-all-data-table-but-only-one-row-or-cell#Item_3

    This is another similar discussion thread
  • BLSullyBLSully Posts: 24Questions: 1Answers: 0
    @rewen: I ran into that issue as well sometime in the past month.... and for the life of me I can't find where, or what I did to solve it. I do recall finding that line...there's a $.isPlainObject(data) in the fnUpdate that makes it fail. If I run across my solution, I'll post it here.
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    This discussion is related to the isPlainObject issue: http://datatables.net/forums/discussion/12426 . This is certainly a bug that needs to be addressed in 1.10. I'll try to land a fix for that today.

    The new API in 1.10 is going to have a standing redraw option built in as well as a regular draw :-).

    Allan
  • BLSullyBLSully Posts: 24Questions: 1Answers: 0
    Thanks as always for your hard work Allan. Can't wait for 1.10 to hit stable :)
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    Me neither! Its probably a good month away at the earliest with everything that is going on.

    Allan
  • rewenrewen Posts: 74Questions: 2Answers: 0
    girishmr & allan,

    Neither a full or a standing redraw actually seem to update the table with the new values from their objects. They still remember the old value. It seems to be cached unless I use fnUpdate. I can see my new value in aoData but I can't get it to re-render the cell to match.

    Any tips?
  • sharathkusharathku Posts: 2Questions: 0Answers: 0
    edited November 2012
    HI ALL can i Add a ASP.net Control to datatable with customised values...
    I am new to this can any body help on the same..
  • sharathkusharathku Posts: 2Questions: 0Answers: 0
    I am new to this can any body help on the same..
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    @sharathku - Yes we can help - but what does your question have to do with the rest of the discussion in this thread? Post a new thread with your questions and read the instructions at the top of the new post page.

    @rewen:

    > Neither a full or a standing redraw actually seem to update the table with the new values from their objects. They still remember the old value

    They would do if you are just changing the data source object and unless you are using the very very latest v1.10 development code. Even then, I think you need to call fnUpdate in order to make sure that all parts of DataTables are using the latest values (i.e. we need to invalidate the cached filtering, sorting etc).

    Allan
This discussion has been closed.