multi-user concurrent system editing

multi-user concurrent system editing

loukinglouking Posts: 259Questions: 52Answers: 0

The latest project I'm building with Editor will be multi-user. I started thinking about locking and multi-user concurrency and found discussions at https://datatables.net/forums/discussion/15828 and https://datatables.net/forums/discussion/comment/127493/#Comment_127493.

The one point which is not made in either of these is that the default editor fields in an edit form are filled from the table entry which was loaded to the browser some time ago. If the table is browser based, the data is loaded at the time the page first loads. Even if the table is server based, the data is loaded when the page is loaded. These could be sitting there for a while before the user decides to edit one of the rows.

I see the comment in this post about server-side events. This talks about data which is being submitted being passed in the pre* event handlers.

But truly, when the edit window is opened, the data should be retrieved from the server at that time, to minimize the risk of using old data. I believe https://editor.datatables.net/reference/event/initEdit must be used in this situation, following logic similar to that which is under "Ajax call to lock this row". The new logic would retrieve the current data from the server, and in the success handler apply returned data to the form.

Am I getting this right?

Should there be, or is there, a more "off the shelf" solution to this?

This question has an accepted answers - jump to answer

Answers

  • rf1234rf1234 Posts: 2,801Questions: 85Answers: 406

    "Should there be, or is there, a more "off the shelf" solution to this?"

    I think there definitely should be an "off the shelf" solution for this. But I am not aware of any ...
    @allan, @colin could you update us on this please.

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    I've actually got exactly this topic noted down to write up as a blog post. I'll try to get it done next week, but I've got a few other things (accounts...) that need to be dealt with next week as well.

    Allan

  • loukinglouking Posts: 259Questions: 52Answers: 0

    Hi @allan - understand you're busy and didn't get to the blog last week. Any guidance on the topic in the interim? -thanks

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin
    Answer ✓

    Sorry - yes. Basically what you need to do is use a custom button rather then edit (or similar). Have that button's action make an Ajax call to the server to get the latest data for the selected row and draw that into the table using row().data(). Finally, use edit() to trigger editing on that row (which is basically all edit does anyway).

    Allan

  • loukinglouking Posts: 259Questions: 52Answers: 0
    edited April 2019

    Finally circling back to this. Thanks for https://datatables.net/blog/2019-04-15 -- this looks great. One question: In editRefresh(), is there a reason you left out action key in the data sent to the server? My post handler is currently looking for action, and it'd be convenient to see 'refresh' there. I know right now I can update my version of editRefresh(), but if you make this part of a future release, my code would be future-safe.

    UPDATE: hmm, maybe I'm mistaken -- I guess the action is sent outside of the data? So will the action be 'edit' in this case?

  • loukinglouking Posts: 259Questions: 52Answers: 0

    Sorry for the stream of consciousness here, but yes it looks like I have to add 'action' to the "form" which is being sent.

    But now I'm stuck at the call to .ids(), which returns undefined for me. I suspect (without evidence) this is because I use 'idSrc` option. Will try to recreate for easier debug.

  • loukinglouking Posts: 259Questions: 52Answers: 0

    bleh - having trouble just reproducing your example from the blog. I'm not sure I can get there. see http://live.datatables.net/sozuroqo/1/edit

  • loukinglouking Posts: 259Questions: 52Answers: 0

    one clue is I'm using jquery, and noticed rows().ids() is handled within jquery.dataTables.js. Still debugging but trying to capture what I've done so far.

  • loukinglouking Posts: 259Questions: 52Answers: 0
    edited April 2019

    Ah yes, that's the culprit. rowIdFn returns data[mSource] and mSource is 'DT_RowId', but DT_RowId is not defined within my data.

    This is also within jquery.dataTables.js.

    Any suggestions for a workaround? I'm kinda stuck at this point.

  • loukinglouking Posts: 259Questions: 52Answers: 0

    Ah. Oops. Seems like I haven't been setting the rowId dataTables option. Interesting that this hasn't caused any problems until now, as I've been using the package for years.

    Thanks for your patience.

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    That would do it - great to hear you've got it working now :).

    Allan

  • loukinglouking Posts: 259Questions: 52Answers: 0

    There were some tweaks required to the code published in https://datatables.net/blog/2019-04-15, some generic some because of my application requirements. Should I also post this on the blog entry?

    See comments on lines 25 and 36 in particular, but you might also consider line 17 when you bring this into the standard offering.

    $.fn.dataTable.ext.buttons.editRefresh = {
        extend: 'edit',
        text: 'Edit',
        action: function (e, dt, node, config) {
            this.processing( true );
    
            // Get currently selected row ids
            var selectedRows = dt.rows({selected:true}).ids();
            var that = this;
    
            // Ajax request to refresh the data for those ids
            $.ajax( {
                url: config.editor.ajax().editRefresh.url,
                type: 'post',
                dataType: 'json',
                data: {
                    // application specific: my application wants 'action' in the POST method data
                    action: 'refresh',
                    refresh: 'rows',
                    ids: selectedRows.toArray().join(',')
                },
                success: function ( json ) {
                    // Update the rows we get data back for
                    for ( var i=0 ; i<json.data.length ; i++ ) {
                        // shouldn't use DT_RowId because of rowId configuration possibility
                        dt.row( '#'+json.data[i][dt.init().rowId] ).data( json.data[i] );
                    }
                    dt.draw(false);
    
                    // Trigger the original edit button's action
                    $.fn.dataTable.ext.buttons.edit.action.call(that, e, dt, node, config);
    
                    // if error, display message - application specific
                    if (json.error) {
                        // this is application specific
                        // not sure if there's a generic way to find the current editor instance
                        editor.error('ERROR retrieving row from server:<br>' + json.error);
                    }
                }
            } );
        }
    };
    
    
  • loukinglouking Posts: 259Questions: 52Answers: 0

    ...almost forgot about line 13, also modified because I have different url's for the various ajax calls

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    All good points - thanks! Yes, if you would be happy to post that across on the blog that would be great. And yes, they do need to be considered when including in the main library.

    Allan

  • loukinglouking Posts: 259Questions: 52Answers: 0

    Thanks, done. Although I posted when I was trying to hit preview, so it's a little abrupt.

    One last question (I hope). On line 37 above, is there any generic way to find the current editor instance? The code I posted expects the editor instance to be in a specific global variable.

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    Not really. You can use editor() to get an Editor instance that is assigned to a DataTable, but the issue there is that multiple instances could actually be assigned.

    However, you can in this case just use config.editor inside the button's event handler since it is extending edit and that has a editor property that gets assigned to the Editor instance the button is controlling.

    Allan

This discussion has been closed.