Difficulty passing plain object data to edit()

Difficulty passing plain object data to edit()

Loren MaxwellLoren Maxwell Posts: 387Questions: 94Answers: 10
edited February 2022 in Editor

I have a table that shows two different types of items (say cats and dogs) with mostly common fields. When a user clicks the Edit button, I want the editor to open based on the type of item (cat or dog) that is selected.

Using this (somewhat pseudo-code) example: (the edit button for the table is the part I'm working on)

var editor_for_cats = new $.fn.dataTable.Editor({
    ...
    fields: [{
            label: "Id",
            name: "id",
        }, {
            label: "Pet type",
            name: "pet_type"
        }, {
            label: "Name",
            name: "name"
        }, {
            label: "Description",
            name: "description"
        }]
    ...
})

var editor_for_dogs = new $.fn.dataTable.Editor({
    ...
    fields: [{
            label: "Id",
            name: "id",
        }, {
            label: "Pet type",
            name: "pet_type"
        }, {
            label: "Name",
            name: "name"
        }, {
            label: "Description",
            name: "description"
        }]
    ...
})

var table = table.DataTable({
    ...
    buttons: {
        ...
        buttons: [{
            extend: "create",
            editor: editor
        }, {
            text: "Edit pet",
            action: function(e, dt, node, config) {

                var row = dt.row({ selected: true }).row()
                var data = row.data()

                if (data.pet_type == "cat") {
                    editor_for_cats.edit(row, {  <-- passing the row node
                        title: "Edit record",
                        buttons: "Update"
                    })
                } else {
                    editor_for_dogs edit(row, {  <-- passing the row node
                        title: "Edit record",
                        buttons: "Update"
                    })
                }
            }
        }]
    },
    columns: [{
            title: "Id",
            name: "id",
            data: "id"
        }, {
            title: "Pet type",
            name: "pet_type",
            data: "pet_type"
        }, {
            title: "Name",
            name: "name",
            data: "name"
        }, {
            title: "Description",
            name: "description",
            data: "description"
        }]
    ...
})

The problem I'm having is that the edit() call to the editor isn't passing along the row data:

var row = dt.row({ selected: true }).row()
...
editor_for_cats.edit(row, {  <-- passing the row node
    ...
})

This page on the edit(): https://editor.datatables.net/reference/api/edit()

states:
"Rows: This is the default mode of operation and if anything other than a plain object is passed in, the value is used as a row-selector to select the rows to edit. This can be table row nodes, a jQuery selector or row indexes. Please refer to the DataTables row-selector for full information on this data type."

I've tried passing the passing along the data as a plain object:

var row = $(dt.row({ selected: true }).row())
var data = row.data()
...
editor_for_cats.edit(data , {  <-- passing the data as an object
    ...
})

And even tried passing along the jQuery version of the node:

var row = dt.row({ selected: true }).row()
var jQrow = $(row)
...
editor_for_cats.edit(jQrow, {  <-- passing the row node as jQuery
    ...
})

I can get the data to populate using field().set():

var row = dt.row({ selected: true }).row()
var data = row.data()
...
editor_for_cats.edit(null, {  <-- passing null and then setting individual fields
    ...
})
.field("id").set(7)
.field("pet_type").set(data.pet_type)
.field("name").set(data.name)
.field("description").set(data.description)

But then the json that is sent to the server is: (notice [object Object] where the id normally is)

data[[object Object]][id]: 7
data[[object Object]][pet_type]: cat
data[[object Object]][name]: Fernando
data[[object Object]][description]: Nothing special

Although I'm looking for any point in the right direction, it's not clear to me why the plain object approach wouldn't work unless it's expecting something additional with the object, such as:

{
    data: {
        row data here
    }
}

Which I also tried, although it didn't work :-(

This question has an accepted answers - jump to answer

Answers

  • kthorngrenkthorngren Posts: 20,302Questions: 26Answers: 4,769

    The key I believe is you need to pass in a valid row-selector. You are trying to pass in the data or the row API. See the duplicate button example which shows how to pass the row index. For your case with just one row you would use dt.row({ selected: true }).row().index().

    Kevin

  • Loren MaxwellLoren Maxwell Posts: 387Questions: 94Answers: 10
    edited February 2022

    Thanks, Kevin (@kthorngren) -- I've tried that as well, but it seems that because I'm not setting the table option for the editors it doesn't know which table to pull the data from:

    var editor_for_cats = new $.fn.dataTable.Editor({
        ...
    //    table: "#cat_and_dog_table", <-- this is not set
        fields: [{
                label: "Id",
                name: "id",
            }, {
                label: "Pet type",
                name: "pet_type"
            }, {
                label: "Name",
                name: "name"
            }, {
                label: "Description",
                name: "description"
            }]
        ...
    })
     
    var editor_for_dogs = new $.fn.dataTable.Editor({
        ...
    //    table: "#cat_and_dog_table", <-- this is not set
        fields: [{
                label: "Id",
                name: "id",
            }, {
                label: "Pet type",
                name: "pet_type"
            }, {
                label: "Name",
                name: "name"
            }, {
                label: "Description",
                name: "description"
            }]
        ...
    })
    

    Of course I can set the table option but then I get problems later with using something like:

    table.editor().destroy()
    

    Using this example: https://editor.datatables.net/examples/simple/inTableControls.html

    it looks like just a row node is passed:

        // Edit record
        $('#example').on('click', 'td.editor-edit', function (e) {
            e.preventDefault();
     
            editor.edit( $(this).closest('tr'), {
                title: 'Edit record',
                buttons: 'Update'
            } );
        } );
    
  • kthorngrenkthorngren Posts: 20,302Questions: 26Answers: 4,769

    I might be confused - aren't you using a single table but want two different editor instances depending on the pet type?

    Kevin

  • kthorngrenkthorngren Posts: 20,302Questions: 26Answers: 4,769

    I put together a basic example of what you described and it seems to work by passing dt.row({ selected: true }).index():
    http://live.datatables.net/guwafemu/249/edit

    If you are having difficulties with table.editor().destroy() or something else pleas update the test case to show the issues.

    Kevin

  • kthorngrenkthorngren Posts: 20,302Questions: 26Answers: 4,769

    var row = dt.row({ selected: true }).row()

    This is not doing what you think. First its returning the select row (dt.row({ selected: true })). Then its returning the row with index 0 (.row()). Make sure to remove the .row().

    Kevin

  • Loren MaxwellLoren Maxwell Posts: 387Questions: 94Answers: 10
    edited February 2022

    Dang it, Kevin -- you've given a perfect example based on my explanation!

    Unfortunately I have oversimplified the explanation of what I'm trying to do so that it didn't become a doctoral thesis!

    What I'm actually trying to do is make a file directory using DataTables and child rows containing more DataTables.

    The initial list of folders for the root directory are rows in a DataTable.

    - root
      -- Folder 1
      -- Folder 2
      -- Folder 3
    

    Those rows can be expanded with child rows to show the folder contents in more DataTables, which can be either more folders (that can also expand) or files.

    - root
      -- Folder 1
         --- Folder 1.1
         --- Folder 1.2
         --- File A
         --- File B
      -- Folder 2
         --- Folder 2.1
         --- Folder 2.2
         --- File C
         --- File D
      -- Folder 3
    

    In the end, there could be many open tables, each representing the contents of a folder.

    The two editors I have are one for folders and one for files.

    The basic structure is:

    var editor_for_folders = definition w/o table option
    
    var editor_for_files = definition w/o table option
    
    function create_child(row) {
       var parent_id = row.data().id
    
       - Open the child row code
       - Create/insert the child DataTable w/ contents of the parent folder
       - Includes a button to edit the row as either a folder or file
    }
    
    function destroy_child(row) {
       - Close the child row and destroy the table
    }
    
    var root_table = definition of root table
       - Calls create_child(null) to show the first indenture of files
    

    Using this structure I could have any number of DataTables but still just the two editors without any specific table specified.

    It still seems to me that using the dt parameter it should work, since the dt parameter is dependent on which particular Edit button was pushed:

              if (data.content_type== "folder") {
                editor_for_folders.edit(dt.row({ selected: true }).index(), { 
                  title: "Edit record",
                  buttons: "Update"
                });
              } else {
                editor_for_files.edit(dt.row({ selected: true }).index(), {  
                  title: "Edit record",
                  buttons: "Update"
                });
              }
    

    However this only works if I specify a table for each editor.

    I realize the dt.row({ selected: true }).index() won't work because the editor has only an index to go off of and doesn't know which table to reference.

    However it would seem that I could pass something like dt.row({ selected: true }).node() or $(dt.row({ selected: true }).node()) or $(dt.row({ selected: true }).data()) and the editor would have the information to populate the fields.

    In the case of the "In table form controls": https://editor.datatables.net/examples/simple/inTableControls.html

    All that's passed along is $(this).closest('tr'), but of course it does have the table specified, so that's obviously helping the editor to figure out which specific row.

    Any thoughts?

  • Loren MaxwellLoren Maxwell Posts: 387Questions: 94Answers: 10

    Ah, and ignore that var row = dt.row({ selected: true }).row().

    That was a typo from my pseudo-code.

    I was using just var row = dt.row({ selected: true })

  • kthorngrenkthorngren Posts: 20,302Questions: 26Answers: 4,769
    Answer ✓

    Have you seen this blog about using Editor with child detail rows as Datatables?

    Looks like the intention is to pass the child Datatbles API into the table option.

    Kevin

  • Loren MaxwellLoren Maxwell Posts: 387Questions: 94Answers: 10
    edited February 2022

    I have seen that . It was the original basis for my page, although I've changed it around significantly.

    The main difference is the blog creates a separate editor for each child row whereas I'm using the same editor(s) for all the tables.

    I can't remember now why I changed that, but I might need to go back to that.

  • Loren MaxwellLoren Maxwell Posts: 387Questions: 94Answers: 10

    @kthorngren Kevin -- just following up. I put the editors inside the create_child(row) function and passed along the table, like what is shown in the blog post, and everything works fine, except . . .

    It appears multiples editors cannot use the same template, which I remember now is why I moved the editors outside the function to use just two editors (one for folders and one for files) for all the DataTables.

    I suppose I could create local versions of the template in each create_child(row) function or perhaps using the template() to specify it each time might work, but for now I'm just using the standard editor form, which is sufficient.

    Anyway, as always -- thanks for the quick and persistent assistance!

  • Loren MaxwellLoren Maxwell Posts: 387Questions: 94Answers: 10

    So actually -- let me follow up -- I cannot duplicate the issue with using the template, so I'm not sure what I might have had incorrect.

    Anyway, it's all working now like I would expect!!!

  • kthorngrenkthorngren Posts: 20,302Questions: 26Answers: 4,769

    Fantastic! Glad its working now.

    Kevin

Sign In or Register to comment.