Parent / child editing with Editor Blog Example

Parent / child editing with Editor Blog Example

cpshartcpshart Posts: 246Questions: 49Answers: 5

I have replicated your Blog example on my system as defined on your blog post (https://datatables.net/blog/2016-03-25 )

I need to be able to join tables to retrieve other information into the parent datatable, so in your replicated example I have added another table country (columns, id, name)

I have included the original working scripts below and also changes in an attempt to add country data and the results, any help in fixing this issue would be much appreciated. Thanks Colin

Table country (new table)
id, name

Table sites (addition country_id)
id, name, country_id

Table users (no change)
id, first_name, last_name, phone, site

the following system works, so selecting the parent row, results in output of corresponding child rows, as per your blog post

additional code to add country name to datatable results in errors and the child rows are no longer output

sites.php, sectional changes

before
...
Editor::inst( $db, 'sites' )
    ->fields(
        Field::inst( 'id' )->set( false ),
        Field::inst( 'sites.name' )->validator( 'Validate::notEmpty' )
    )
...
after
...
Editor::inst( $db, 'sites' )
    ->fields(
        Field::inst( 'sites.id' )->set( false ),
        Field::inst( 'sites.name' )->validator( 'Validate::notEmpty' ),
        Field::inst( 'country.name' )
    )
...
    ->leftJoin( 'country', 'country.id', '=', 'sites.country_id' )

Client File

before
...
        <thead>
            <tr>
                <th>Name</th>
                <th>Users</th>
            </tr>
        </thead>
after
...
        <thead>
            <tr>
                <th>Name</th>
                <th>Users</th>
                <th>Country</th>
            </tr>
        </thead>

before
...
foreach ($rows as $row ){
    echo "<tr>";
    echo "<td>$row->site</td>";
    echo "<td>$row->users</td>";
    echo "</tr>";
}
...
after
before
...
foreach ($rows as $row ){
    echo "<tr>";
    echo "<td>$row->site</td>";
    echo "<td>$row->users</td>";
    echo "<td>$row->country</td>";
    echo "</tr>";
}
...
before
...
        columns: [
            { data: 'name' },
            { data: 'users', render: function ( data ) {
                return data.length;
            } }
        ],
...
after
        columns: [
            { data: 'name' },
            { data: 'users', render: function ( data ) {
                return data.length;
            } },
            { data: 'country' }
        ],

Errors
If I run the new client file (addition of country coding) with the old server files, selecting the parent row correctly displays the child rows, error is below

DataTables warning: table id=sites - Requested unknown parameter 'country' for row 0, column 2. For more information about this error, please see http://datatables.net/tn/4

and no country data is displayed in datatable

Invoking the new server file sites.php, results in error

DataTables warning: table id=sites - Requested unknown parameter 'name' for row 0, column 0. For more information about this error, please see http://datatables.net/tn/4

Name displays no row data
Country displays [object Object] in cell

Working Files (pre country change)
Client File

<head>
<title>Sites Users</title>
.... libraries here ...
</head>

<table id="sites" class="display">
        <thead>
            <tr>
                <th>Name</th>
                <th>Users</th>
            </tr>
        </thead>
<tbody>     
<?php
global $wpdb;    
global $current_user;
get_currentuserinfo();
$user_id = $current_user->ID;
    
$rows = $wpdb->get_results("
SELECT 
sites.name AS site,
'1' AS users,
country.name AS country,
first_name AS firstname,
last_name AS lastname,
phone AS phone,
sites.name AS location
FROM
users
INNER JOIN sites ON (sites.id = users.site) 
INNER JOIN country ON (country.id = sites.country_id)
");
        
foreach ($rows as $row ){
    echo "<tr>";
    echo "<td>$row->site</td>";
    echo "<td>$row->users</td>";
    echo "</tr>";
}
?>
</tbody>
</table>

... users section here all works ok ...

<input type='hidden' id='passuserid' value='<?php echo $current_user->ID; ?>'>
    
<script type="text/javascript">
(function($) {
var editor; // use a global for the submit and return data rendering in the examples
 
$(document).ready(function() {
    var siteEditor = new $.fn.dataTable.Editor( {
        ajax: "../../Editor-PHP-1.9.0/controllers/sites.php",
        table: "#sites",
        fields: [ {
                label: "Site name:",
                name: "name"
            }
        ]
    } );
    window.editor = siteEditor; // for demo only!
 
    var siteTable = $('#sites').DataTable( {
        dom: "Bfrtip",
        ajax: "../../Editor-PHP-1.9.0/controllers/sites.php",
        columns: [
            { data: 'name' },
            { data: 'users', render: function ( data ) {
                return data.length;
            } }
        ],
        select: {
            style: 'single'
        },
        buttons: [
            { extend: "create", editor: siteEditor },
            { extend: "edit",   editor: siteEditor },
            { extend: "remove", editor: siteEditor }
        ]
    } );

    
    var usersEditor = new $.fn.dataTable.Editor( {
        ajax: {
            url: '../../Editor-PHP-1.9.0/controllers/users.php',
            data: function ( d ) {
                var selected = siteTable.row( { selected: true } );
                if ( selected.any() ) {
                    d.site = selected.data().id;
                }
            }
        },
        table: '#users',
        fields: [ {
                label: "First name:",
                name: "users.first_name"
            }, {
                label: "Last name:",
                name: "users.last_name"
            }, {
                label: "Phone #:",
                name: "users.phone"
            }, {
                label: "Site:",
                name: "users.site",
                type: "select",
                placeholder: "Select a location"
            }
        ]
    } );
 
    var usersTable = $('#users').DataTable( {
        dom: 'Bfrtip',
        ajax: {
            url: '../../Editor-PHP-1.9.0/controllers/users.php',
            type: 'post',
            data: function ( d ) { /* this code displays child rows matching id of selected parent row */
                var selected = siteTable.row( { selected: true } );
                if ( selected.any() ) {
                    d.site = selected.data().id;
                }
            }
        },
        columns: [
            { data: 'users.first_name' },
            { data: 'users.last_name' },
            { data: 'users.phone' },
            { data: 'sites.name' }
        ],
        select: true,
        buttons: [
            { extend: 'create', editor: usersEditor },
            { extend: 'edit',   editor: usersEditor },
            { extend: 'remove', editor: usersEditor }
        ]
    } );
     
/* This writes the users data to the sites JSON when Parent Row is Selected */
    siteTable.on( 'select', function (e) {
        usersTable.ajax.reload();
         usersEditor
            .field( 'users.site' )
            .def( siteTable.row( { selected: true } ).data().id );
    } );
/* This writes the users data to the sites JSON when Parent Row is Selected */
 
    siteTable.on( 'deselect', function () {
        usersTable.ajax.reload();
    } );
     
    usersEditor.on( 'submitSuccess', function () {
        siteTable.ajax.reload();
    } );
 
    siteEditor.on( 'submitSuccess', function () {
        usersTable.ajax.reload();
    } );
} );    
    
    
}(jQuery));</script>

sites.php

// DataTables PHP library
include( "../lib/DataTables.php" );

// Alias Editor classes so they are easy to use
use
    DataTables\Editor,
    DataTables\Editor\Field,
    DataTables\Editor\Format,
    DataTables\Editor\Mjoin,
    DataTables\Editor\Options,
    DataTables\Editor\Upload,
    DataTables\Editor\Validate,
    DataTables\Editor\ValidateOptions;

Editor::inst( $db, 'sites' )
    ->fields(
        Field::inst( 'id' )->set( false ),
        Field::inst( 'name' )->validator( 'Validate::notEmpty' )
    )

    ->join(
        Mjoin::inst( 'users' )
            ->link( 'sites.id', 'users.site' )
            ->fields(
                Field::inst( 'id' )
            )
    )

    ->process( $_POST )
    ->json();
?>

users.php

<?php
// DataTables PHP library
include( "../lib/DataTables.php" );

// Alias Editor classes so they are easy to use
use
    DataTables\Editor,
    DataTables\Editor\Field,
    DataTables\Editor\Format,
    DataTables\Editor\Mjoin,
    DataTables\Editor\Options,
    DataTables\Editor\Upload,
    DataTables\Editor\Validate,
    DataTables\Editor\ValidateOptions;

if ( ! isset($_POST['site']) || ! is_numeric($_POST['site']) ) {
    echo json_encode( [ "data" => [] ] );
}
else {
    Editor::inst( $db, 'users' )
        ->field(
            Field::inst( 'users.first_name' ),
            Field::inst( 'users.last_name' ),
            Field::inst( 'users.phone' ),
            Field::inst( 'users.site' )
                ->options( 'sites', 'id', 'name' )
                ->validator( 'Validate::dbValues' ),
            Field::inst( 'sites.name' )
        )
        ->leftJoin( 'sites', 'sites.id', '=', 'users.site' )
        ->where( 'site', $_POST['site'] )
        ->process($_POST)
        ->json();
}
?>

Link to test case:
Debugger code (debug.datatables.net):
Error messages shown:
Description of problem:

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 61,665Questions: 1Answers: 10,096 Site admin
    Answer ✓

    In the "after" state, could you use the debugger to give me a trace please - click the Upload button and then let me know what the debug code is please/

    Thanks,
    Allan

  • cpshartcpshart Posts: 246Questions: 49Answers: 5

    Hi Allan

    Thanks for coming back to me, I have made changes according to the "after" state and the effect is that the parent datatable is populated as expected, but on selecting a parent row no child rows are displayed, whereas previous to the after change I could replicate your blog behaviour on selection of a parent row.

    I have run debug as suggested and I will update my libraries as recommended by the debug results (I have not been developing for sometime, so I have not applied the recent updates)

    Any ideas why the selection is now failing on adding a very simple joined table column expression would be much appreciated, as unfortunately this is an essential requirement of my site.

    Here are the results of the debug below

    Table information
    Summary information about the DataTables on this page.
    Information about 2 tables available
    #sites
    Data source:    Ajax
    Processing mode:    Client-side
    Draws:  2
    Columns:    3
    Rows - total:   7
    Rows - after search:    7
    Display start:  0
    Display length: 10
    #users
    Data source:    Ajax
    Processing mode:    Client-side
    Draws:  2
    Columns:    4
    Rows - total:   0
    Rows - after search:    0
    Display start:  0
    Display length: 10
    
    Version check
    Check to see if your page is running the latest DataTables software.
    LibraryInfoInstalledLatest
    DataTablesNew version available1.10.191.10.21
    AutoFill-2.3.5
    ButtonsNew version available1.5.41.6.2
    ColReorder-1.5.2
    EditorNew version available1.9.01.9.4
    FixedColumns-3.3.1
    FixedHeader-3.1.7
    KeyTable-2.5.2
    ResponsiveNew version available2.2.32.2.5
    RowGroup-1.1.2
    RowReorder-1.2.7
    Scroller-2.0.2
    SelectNew version available1.3.01.3.1
    
    Check for common issues
    Run automated tests to check for common and previously reported issues.
    15 tests complete. No failures or warnings found!
    
    If you are having problems with your DataTables, please upload a data profile using the Upload option below, and post a support request in DataTables forums, with a link to a page showing the issue so we can help to debug and investigate the issue.
    Upload configuration data
    Upload your table's configuration and data to allow for further analysis.
    It can often greatly assist in debugging a table if we can see the configuration and data in the table. This feature of the debugger will read your local DataTables configuration and upload it to debug.datatables.net for inspection.
    
    Important: The data uploaded to the server can only be viewed by SpryMedia employees will be automatically deleted after two weeks. The data will never be sold or otherwise published. It is used for debugging any issues you are experiencing with DataTables only.
    Upload complete - erudex
    Your debug code is shown above. Please include this in any support requests.
    

    Many Thanks Colin

  • cpshartcpshart Posts: 246Questions: 49Answers: 5

    Hi Allan

    I have sent you a pm with access to my system to look into the problem, with thanks Colin

  • cpshartcpshart Posts: 246Questions: 49Answers: 5

    Hi

    If anyone offer any suggestions on how I can add a joined table value to the parent table without disabling the ability to select a parent row and display the corresponding child rows.

    The Parent Child rows editor only works if I reference values from the same table in the parent datatable.

    I am very keen to get this working so I can apply the working example to my site.

    Many Thanks Colin

  • allanallan Posts: 61,665Questions: 1Answers: 10,096 Site admin

    Thanks for the details - I've replied to your PM.

    Allan

  • cpshartcpshart Posts: 246Questions: 49Answers: 5

    Thanks, Allan I have sent you a PM.

  • cpshartcpshart Posts: 246Questions: 49Answers: 5

    I have solved the problem of being able to display the site and country name from another table whilst maintaining the selection of parent row and display associated child rows, changes to the scripts are shown below

    Client Script

    before
    ...
        var usersTable = $('#users').DataTable( {
            dom: 'Bfrtip',
            ajax: {
                url: '../../Editor-PHP-1.9.0/controllers/users.php',
                type: 'post',
                data: function ( d ) { 
                    var selected = siteTable.row( { selected: true } );
                    if ( selected.any() ) {
                        d.site = selected.data().id;
                    }
                }
            },
    ...
    after
        var usersTable = $('#users').DataTable( {
            dom: 'Bfrtip',
            ajax: {
                url: '../../Editor-PHP-1.9.0/controllers/users.php',
                type: 'post',
                data: function ( d ) { 
                    var selected = siteTable.row( { selected: true } );
                    if ( selected.any() ) {
                        d.site = selected.data().sites.id;
                    }
                }
            },
    

    the reason the selection failed on inclusion of another table.column was this line needed to incorporate the tablename sites in sites.id

    before
                        d.site = selected.data().id;
    
    after
                        d.site = selected.data().sites.id;
    

    Server file sites.php extract

    ...
    Editor::inst( $db, 'sites', 'id' )
        ->fields(
                Field::inst( 'sites.id' )->set( false )
               ,Field::inst( 'sites.name' )->validator( 'Validate::notEmpty' )
               ,Field::inst( 'sites.country_id' )
                ->options( Options::inst()
                    ->table( 'country' )
                    ->value( 'id' )
                    ->label( array('name') )
                )
                ->validator( Validate::notEmpty( ValidateOptions::inst()
                    ->message( 'Please select country ..' )
                ) ),    
            Field::inst( 'country.name' )
        )
    
        ->join(
            Mjoin::inst( 'users' )
                ->link( 'sites.id', 'users.site' )
                ->fields(
                    Field::inst( 'id' )
                )
        )
       ->leftJoin( 'country', 'country.id', '=', 'sites.country_id' )
    
        ->debug(true)
        ->process( $_POST )
        ->json(); 
    ?>
    
    server file changes to sites.php 
    were
    adding tablename to prefix columns in Editor Fields
    
    

    Thanks for assistance

    Colin

  • cpshartcpshart Posts: 246Questions: 49Answers: 5

    Unfortunately the previous post is not a complete solution, as the changes outlined above although fixing the display of joined table data compromise the behaviour of the editor of the child table, so I will continue to search for a solution and post when done.

    Allan I have sent you a PM

    Thanks Colin

This discussion has been closed.