How to adapt Editor REST to pass params to Rails 5?

How to adapt Editor REST to pass params to Rails 5?

matissgmatissg Posts: 63Questions: 15Answers: 0

I'm trying to adapt Editor REST interface to my Rails app and I'm stuck in passing params to Rails 5, so it can do create. By default Editor is passing params like this:

Processing by Strongbolt::UserGroupsController#create as JSON
  Parameters: {"data"=>{"0"=>{"name"=>"testing", "description"=>"test", 
"users"=>{"0"=>{"id"=>"3"}, "1"=>{"id"=>"2"}, "2"=>{"id"=>"5"}}, 
"users-many-count"=>"3", "roles"=>{"0"=>{"id"=>"1"}}, "roles-many-count"=>"1"}}}

However I need them to be passed like this in order to Rails 5 to do Create action:

Processing by Strongbolt::UserGroupsController#create as JSON
  Parameters: {"strongbolt_user_group"=>{"name"=>"this is my test group", 
"description"=>"this is my test description", "user_ids"=>["2", "5"], "role_ids"=>["1"]}}

In my JS the Editor part looks like this, where in Create action I've hard-coded example values:

editor = new $.fn.dataTable.Editor( {
      ajax: {
          create: {
              type: 'POST',
              url:  '/strongbolt/user_groups',
              data: {"strongbolt_user_group":{
                "name": "this is my test group",
                "description": "this is my test description",
                "user_ids": [2,5], 
                "role_ids": [1]}
              }
          },
          edit: {
              type: 'PATCH',
              url:  '/user_groups/', //Not final implementation
          },
          remove: {
              type: 'DELETE',
              url:  '/strongbolt/user_group'
          }
      },
      table: "#user_groups_table",
      template: '#user_groups_form',
      display: "details",
      idSrc: "id",
      fields: [ {
              name: "name"
          }, {
              name: "description"
          }, {
              type: "checkbox",
              name: "users[].id",
              optionsPair: {
                label: 'name',
                value: 'id'
              }
            }, {
              type: "checkbox",
              name: "roles[].id",
              optionsPair: {
                label: 'name',
                value: 'id'
              }
            }
      ]
    } );

I believe I should somehow define variables and then insert them into data in my Create action, but I don't know how to do it. My idea of variables is like this:

var fname = editor.field( 'name' );
var fdescription = editor.field( 'description' );
var fusers = editor.field( 'users[].id' );
var froles = editor.field( 'roles[].id' );

How do I implement those variables to pass so Rails can do Create action, please?

Replies

  • allanallan Posts: 61,697Questions: 1Answers: 10,102 Site admin

    Hi,

    You can use the preSubmit event to modify the data that is being send to the server. Editor's default format is documented here, but you can modify the object as you need.

    For example

    editor.on( 'preSubmit', function ( e, data, action ) {
      if ( action === 'create' ) {
        $.extend( data, data.data[0] );
        delete data.data;
      }
    } );
    

    That will effectively flatten the object so the parameters are at the top level. You will need to modify it a bit to suit your needs exactly, but that's the basic idea.

    Regards,
    Allan

  • matissgmatissg Posts: 63Questions: 15Answers: 0

    @allan Thank you! As I understand it should be something like this in my case:

        editor.on( 'preSubmit', function ( e, data, action ) {
          if ( action === 'create' ) {
            $.extend( data, data.data[0] );
            delete data.data;
            data.strongbolt_user_group = {
                "name": fname,
                "description": fdescription,
                "user_ids": fusers,
                "role_ids": froles
            };
          }
        } );
    
    

    Where do I place my variables, please?

    var fname = editor.field( 'name' );
    var fdescription = editor.field( 'description' );
    var fusers = editor.field( 'users[].id' );
    var froles = editor.field( 'roles[].id' );
    

    At the moment when I place them just before preSubmit, it does not work. Sorry for naive question - I just start learning to code and particularly JS.

  • allanallan Posts: 61,697Questions: 1Answers: 10,102 Site admin

    Don't use the Editor API methods in the preSubmit callback. Technically you can, but it is a surefire way of tying yourself in knots since it has already got the data to submit to the server - i.e. you can't use the API to set different values.

    It sounds like you might want to do something like this:

    editor.on( 'preSubmit', function ( e, data, action ) {
      if ( action === 'create' ) {
        data.strongbolt_user_group = {
            "name": data.data[0].fname,
            "description": data.data[0].fdescription,
            "user_ids": data.data[0].fusers,
            "role_ids": data.data[0].froles
        };
        delete data.data;
      }
    } );
    

    The code could be tidier with $.extend(), but that perhaps shows what is happening a little clearer.

    Out of interest, if you want to submit the field as name, why initialise the Editor field as fname? Could you not just use the same name and make things a little easier?

    Allan

  • matissgmatissg Posts: 63Questions: 15Answers: 0

    @allan Thank you, seems to be working now.
    fname was if I used those variables above. As I understand, now I directly manipulate with fields, so it is name or description, users, roles.
    Now I have to figure out how do I convert this param hash to array:
    "user_ids"=>{"0"=>{"id"=>"2"}, "1"=>{"id"=>"5"}}
    Editor gives me hash, however I need array for Rails to save user_ids. This is different story though.

  • allanallan Posts: 61,697Questions: 1Answers: 10,102 Site admin

    Your best bet might be to loop over the object that Editor gives you and create a new object in the format you want. Then attach that object to the data object that will be sent to the server.

    I've been trying to think of ages now how I could provide some kind of templating for the data format to submit, but still haven't thought of a good way that is generic enough to handle most use cases. A transformation function is frustrating to have to write, but its still the best way to keep things generic.

    Allan

  • matissgmatissg Posts: 63Questions: 15Answers: 0

    @allan Thank you! Probably I just need to learn a bit more of JS and I will definitely do so. Meanwhile it seems like this is solution in my case:

    "user_ids": data.data[0].users.map(function(o) { return o.id; }),
    "role_ids": data.data[0].roles.map(function(o) { return o.id; }),
    

    If anyone needs, here is SO answer to my question.

  • matissgmatissg Posts: 63Questions: 15Answers: 0

    @allan I'm trying to add edit action and my code looks like this now:

        editor.on( 'preSubmit', function ( e, data, action ) {
          if ( action === 'create' ) {
            data.strongbolt_user_group = {
                "name": data.data[0].name,
                "description": data.data[0].description,
                "user_ids": data.data[0].users.map(function(o) { return o.id; }),
                "role_ids": data.data[0].roles.map(function(o) { return o.id; }),
            };
            delete data.data;
          } else if ( action === 'edit' ) {
            data.strongbolt_user_group = {
              "name": data.data[0].name,
              "description": data.data[0].description,
              "user_ids": data.data[0].users.map(function(o) { return o.id; }),
              "role_ids": data.data[0].roles.map(function(o) { return o.id; }),
            };
            delete data.data;
          }
        } );
    

    At the moment when I do "Update row" nothing happens and I get this error in my console:
    TypeError: data.data[0] is undefined + my debugger is pointing to this line in edit action: "name": data.data[0].name,

    Do you have some idea, what's wrong, please? So far I thought I just copy+paste it from create and it should be working. When I change edit action data to some hard-coded values it works though.

  • allanallan Posts: 61,697Questions: 1Answers: 10,102 Site admin

    When submitting an edit the data parameter is not a simple indexed array. Rather the indexes are based on the primary key value - the documentation details the format being used.

    To get it working you'll need to use foreach or perhaps easier jQuery.each() to loop over the object, getting the options and the primary key value.

    You are very close with that, but it needs a little tweaking.

    See also this example which uses jQuery.each() for exactly that.

    Allan

  • matissgmatissg Posts: 63Questions: 15Answers: 0

    @allan I just tested for record with ID=90, this would work:
    "name": data.data[90].name,
    I'm thinking is there some easy way to pass that ID to data.data[ID].name or I still have to check that jQuery.each() function?

  • matissgmatissg Posts: 63Questions: 15Answers: 0

    @allan It seems to me this is working:

            var myID = 90;
            data.strongbolt_user_group = {
              "name": data.data[myID].name,
              "description": data.data[myID].description,
              "user_ids": data.data[myID].users.map(function(o) { return o.id; }),
              "role_ids": data.data[myID].roles.map(function(o) { return o.id; }),
    

    Can I get my record ID for var myID without any iteration thing?

  • allanallan Posts: 61,697Questions: 1Answers: 10,102 Site admin

    That works - but only if you ever edit id 90. If you ever edit any other row, it would fail. Using a loop to get the key / value pair would be the way to do this, like in the example.

    Allan

  • matissgmatissg Posts: 63Questions: 15Answers: 0

    @allan As I understand It appears to be this simple:

    else if ( action === 'edit' ) {
      $.each( data.data, function (id, value) {
        data.strongbolt_user_group = {
          "name": data.data[id].name,
          "description": data.data[id].description,
          "user_ids": data.data[id].users.map(function(o) { return o.id; }),
          "role_ids": data.data[id].roles.map(function(o) { return o.id; }),
          };
        });
      delete data.data;
    }
    

    Now I have to figure out last thing - how to add id to my edit url to be it something like this:

    edit: {
        type: 'PATCH',
        url:  '/user_groups/' + id
    },
    
  • allanallan Posts: 61,697Questions: 1Answers: 10,102 Site admin

    Yup - that will do it :).

    To add the id, use: _id_ in the URL string where you want the id to appear. See this part of the documentation for details.

    Allan

  • matissgmatissg Posts: 63Questions: 15Answers: 0

    Ah, so simple :) I should be searching your docs more carefully. Thank you, now my url is working as expected.

  • strohy1210strohy1210 Posts: 1Questions: 0Answers: 0

    Hi Matissg, Do you have an example of your final implementation of this, including handling the response from the rails server? Thank you

This discussion has been closed.