How to retrieve row data without submitting in inline mode?

How to retrieve row data without submitting in inline mode?

pisislerpisisler Posts: 106Questions: 21Answers: 1

Hi.

I am doing some kind of cross calculation and cross validation with a complex structure and it works fine. But there is a problem with retrieving the row data in inline mode.

In create mode, editor sends all the data as expected and no fancy things needed. On the other hand in inline mode, editor submits only the value of the cell that is being edited. For cross validation to work, I needed to set formOptions to send "allIfChanged".

While this lets the cross validation work, it also causes all fields' validation functions to be called (because it submits the data whether it's altered or not), although those cell values are not changed; which is a great performance issue.

Is is not possible to retrieve the row data without submitting it?

For example a renderer like function ($data, $row) is not receiving the row here, in inline mode. (Because the other values are not submitted)

If, it's technically not possible; then is it also not possible for the editor to check the actual "changed" data? I mean when submit option is set to "allIfChanged", would'nt the editor be able to submit all values but update the database only if the value is really altered?

This question has an accepted answers - jump to answer

Answers

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

    Is is not possible to retrieve the row data without submitting it?

    Where are your validation options? It sounds like they are on the server-side - if that is the case, then they would have to be submitted to the server in order for them to be available there.

    Perhaps one option would be to use ajax.data to get the data from the row being edited (table.row( editor.modifier().parentNode ).data() - depending on exactly how you trigger the editing!) and submit the data for the row in a custom parameter that the server-side libraries won't check for? Then you could use that data for your cross calculation.

    Allan

  • pisislerpisisler Posts: 106Questions: 21Answers: 1
    edited May 2018

    Thanks Allan. Yes, I do the validation in server side script, adding a validator into the chain like;

            Field::inst( 'price' )
                ->validator( Validate::minNum(0) )
                ->setFormatter( Format::ifEmpty(0) )
                ->validator('update_price_soap'),
    

    I do this in here because if something goes wrong and the update_price_soap() cannot update the SOAP service, then it will return an error not letting the DataTables store the new value. That's why this function needs the row data to know which product's price is going to be updated in the SOAP service. But the problem is, this and all other similar functions repeatedly work with other cells also changed. I mean the price is not altered but my SOAP function is called nevertheless, because the price is submitted too.

    As for its nature, I know that they have to be submitted. What I mean is, submitting happens in two parts here. First, editor submits the data as an actual form to the server. Second, PHP part takes this submitted data and inserts/updates into the database. So I thought maybe the PHP part would give up updating the database for that cell if the cell value is not really altered. If that is possible, then the editor would have changed only the altered values, although all the values are submitted.

    Perhaps one option would be to use ajax.data to get the data from the row being edited

    With this method, I think I will have to move my validation functions to some custom file and do some extra coding; because this way I understand that I won't be able to use DataTables internal API.

    Maybe another workaround could be sending the edited cell name as a parameter; so that the custom validator would always return true if this is not the actual cell that was edited inline?

    Like this dirty code for example;

    function update_price_soap($data, $row, $current_cell) {
        if ($current_cell != 'price')
            return true; // We don't need to validate, because price hasn't changed.
        // Or you can do other cross validation, like "although the price hasn't changed
        // some other data might need to remain in a specific range in accordance with current price".
    
  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin

    So I thought maybe the PHP part would give up updating the database for that cell if the cell value is not really altered.

    No - if Editor submits it from the client-side, then the server-side libraries will act upon it. They don't currently read the data back from the database to check if anything has changed. A write is normally just as fast, or faster if you need to then also write after the read.

    Maybe another workaround could be sending the edited cell name as a parameter

    Agreed! That's what I was thinking while reading your follow up there.

    This recent thread I think will be useful here. You can store the values as they are when the editing is started, then get the values on submit and check to see if any have changed. If so, add those field names to the data being submitted so your custom validators can see that and act upon it.

    Allan

  • pisislerpisisler Posts: 106Questions: 21Answers: 1
    edited May 2018

    No - if Editor submits it from the client-side, then the server-side libraries will act upon it. They don't currently read the data back from the database to check if anything has changed. A write is normally just as fast, or faster if you need to then also write after the read.

    What I ment was, the client side could have submitted both old and new values to the server side. So that it wouldn't need to read from database and compare if it has changed. Like maybe;

    function price_validator($data, $row, $old_values) {  }
    

    Also a quick note; there's no need to send the cell value as a seperate parameter ($data) in my opinion. Because no matter the option you set for "what to submit"; that cell's value will always be stored in $row array anyway. Like;

    price_validator($data = 3.45, $row = array('price' => 3.45))`
    

    So what's the point in sending one extra parameter?

    This recent thread I think will be useful here. You can store the values as they are when the editing is started, then get the values on submit and check to see if any have changed.

    I couldn't make use of it well; or maybe I couldn't figure out what was really pointed out in that thread :/

    As far as I see, he doesn't trigger a PHP script as he suggested and his method didn't seem to be compatible with DataTables API to me. In that method; I believe this is what's gonna happen;

    With this method, I think I will have to move my validation functions to some custom file and do some extra coding; because this way I understand that I won't be able to use DataTables internal API.

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

    So what's the point in sending one extra parameter?

    Simplification only. You are right it isn't required, but it means that you don't need to know the name of the field in the validator. That makes it much easier to write generic validators for simple scalar values.

    As far as I see, he doesn't trigger a PHP script as he suggested and his method didn't seem to be compatible with DataTables API to me.

    My point with linking to that thread was that you would be able to stored the values of the row when editing is triggered, and then check to see which ones have changed at submit time. That would be client-side checking.

    From your description it sounds like you want server-side checking. Which is fine - for that, use my suggestion above of ajax.data and table.row( editor.modifier().parentNode ).data() to get the original, unmodified data, for the row. Then you can add that to the object to be submitted and do whatever server-side check it is that you need.

    Allan

  • pisislerpisisler Posts: 106Questions: 21Answers: 1
    edited May 2018

    Just to test ajax.data, I tried to extend data with a new variable like this;

            ajax: {
                url: "datav0.3.php?p=<?=$position;?>",
                type: 'POST',
                data: function (d) {
                    return $.extend( {}, d,
                        {'test': 'something' }
                    )
                }
            },
    

    But I can't seem to reach this "test" variable by any chance within the data.php file (server-side). I can read it from $_GET array if the ajax.type is set to GET; but it's not the way it's supposed to work is it?

    I tried the other methods as well; like adding a scalar value.. I even tried to return an arbitrary string instead of the actual data. No result. At the server side, data is received as always it is. Always having the new row object with the new values.

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

    Remove {},. That is creating a new object - in this case you actually want to mutate the d object.

    Allan

  • pisislerpisisler Posts: 106Questions: 21Answers: 1
    edited May 2018

    I did it per the reference examples in here;
    https://datatables.net/reference/option/ajax.data

    I think I don't get how to remove the new object notation from that code. Just removing the parameter? Because if so, it doesn't work either.

    I also tried to add a new parameter like;

        return d.test = 'something new';
    

    I cannot get to read this "test" variable from server side either.

  • allanallan Posts: 61,446Questions: 1Answers: 10,054 Site admin
    ajax: {
        url: "datav0.3.php?p=<?=$position;?>",
        type: 'POST',
        data: function (d) {
             d.test = 'something';
        }
    },
    

    is what I would normally use for that myself. And then $_POST['test'] should be populated in the PHP script. If that isn't the case, can you link to the page so I can take a look into it please?

    Thanks,
    Allan

  • pisislerpisisler Posts: 106Questions: 21Answers: 1

    Yes, this way it works already; I just thought one of the validator parameters was going to include this new addition.

    But then again, if we are supposed to read the variable from $_POST, then what is the reference examples are referring to? Like this one;

    Add data to the request (returning an object):

        "data": function ( d ) {
          return $.extend( {}, d, {
            "extra_search": $('#extra').val()
          } );
    

    So "extra_search" variable in this example is also needed to be read from $_POST? I am asking because the explanations of those examples suggest something different. It says, "it will manipulate the data that is submitted". But the d parameter is definitely NOT the submitted data and now I don't see a way to really manipulate the data.

    From the expression "manipulate the submitted data", I understand that d should have been containing the data that will be sent to the server-side and you can do anything with it before submission.

    By the way I was going to ask about the other example too, but seems like there's a bug in markdown here. Because I cannot quote another example like the one above; everything in the post breaks if I do

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

    if we are supposed to read the variable from $_POST, then what is the reference examples are referring to?

    $_POST['extra_search'] would be how you read it on the server-side. You don't have to read it, but it will be there if you need it.

    Can you give me a link to the page that you are working on so I can take a look and see what is going wrong?

    Thanks,
    Allan

  • pisislerpisisler Posts: 106Questions: 21Answers: 1
    edited May 2018

    Thank you for your effort Allan, there's nothing going wrong right now, as I said the variable is already in $_POST, there is no problem with it. I am developing an intranet application which contains confidential data; so I didn't put it online.

    I was just discussing the logic. The reference manual says that you can manipulate the data that is being sent; but in fact you cannot. Because you can't reach out to data using ajax.data. You can just add some variables; which are also NOT added to the actual data object, in contrast to what manual explains.

  • pisislerpisisler Posts: 106Questions: 21Answers: 1

    Instead of table.row( editor.modifier().parentNode ).data(), I needed to use table.row( editor.modifier() ).data(); beucase the other one sometimes returns the first row's data instead of the one that is being edited.

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

    The reference manual says that you can manipulate the data that is being sent; but in fact you cannot

    Yes you can:

    ajax: {
      url: ...,
      data: function ( d ) {
        d.myCustomParameter = 1;
      },
      type: 'POST'
    }
    

    That will POST a request with myCustomParameter set to be 1. This example shows that in practice.

    Allan

  • pisislerpisisler Posts: 106Questions: 21Answers: 1

    Yes you can send custom vars; but don't get to be manipulating the existing data I ment. But then again, of course there are other methods to achieve that. Allan, what about the other thing I mentioned;

    I needed to use table.row( editor.modifier() ).data() instead of what you suggested; table.row( editor.modifier().parentNode ).data(). Is that normal?

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

    It entirely depends upon what modifier() is returning. In your case it sounds like it is returning the tr element, which is absolutely fine. In my example above it was returning td.

    modifier() will return whatever is used to trigger the editing. For inline editing that it usually the cell, for row editing that is normally the row.

    1.7.4 is going to introduce an ids() method in Editor to help resolve this (i.e. always return the row ids regardless of how editing was triggered).

    Allan

  • pisislerpisisler Posts: 106Questions: 21Answers: 1

    Might "allIfChanged" option be effecting what is returned? Because in my case, cell (td) is actually triggering the edit, because it is inline; but full row is returned with modifier(). Maybe it's beause I have set to submit allIfChanged?

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

    It shouldn't - no. That only effects the data submitted to the server.

    Using this example, if I click a cell to trigger editing and then in the console use editor.modifier() it shows a td cell.

    Allan

This discussion has been closed.