Key entered - get "Unable to automatically determine field from source"

Key entered - get "Unable to automatically determine field from source"

rprobinsonrprobinson Posts: 14Questions: 3Answers: 0

I'm using the Editor with my datatable to handle inline edits of various cells in my table. The table column change based on values selected by the user in a drop down. I basically have to then get the data from the database, figure out some things with columns, then refresh the table (along with creating an editor instance). The user can change a cell - that's were I'm having problems.

I’ve added these two statements to my code:

        $('#example').on('click', 'tbody td:not(:first-child)', function (e) {
            // debugger;
            crntCell = table.cell(this);

            crntColumnHandle = crntCell[0];
            crntColumnNbr = crntColumnHandle[0].column;
            crntRowNbr = crntColumnHandle[0].row;
            editor.inline(this, crntColumnNbr.toString());
        });

        // Inline editing on tab focus
        table.on('key-focus', function (e, datatable, cell) {
            // debugger;
            var myCell = cell.index();
            crntColumnNbr = myCell.column;
            crntRowNbr = myCell.row;
            editor.inline(cell.index(), crntColumnNbr.toString());
        });

The above code solved the “Unable to automatically determine field from source” error I was getting initially. This is using approach 2 described for the inline api, specify the field name.

Note, I’m using an array, hence the column number is my field name (correct me if I’m wrong). I've like to avoid having to assign an editor to each column since at run-time I'd have to figure out how to do this.

When I press a key to change the cell, I get “Unable to automatically determine field from source”
What basic step have I missed? Or what else do I need to add?

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 63,498Questions: 1Answers: 10,470 Site admin

    Hi,

    Thanks for your question. With the above you should be able to simply use:

    table.on('key-focus', function (e, datatable, cell) {
        editor.inline(cell.index());
    });
    

    The key-focus event will trigger when you click on a focusable cell.

    I've also dropped the second argument to inline() as that shouldn't be needed if the columns.editField property is used. That property is also what would need to be used to resolve the "Unable to automatically..." issue.

    Basically what is happening is that the columns.data property for a field is not exactly matching up with a field in the Editor (fields.name) - therefore Editor doesn't know which field it should be editing.

    You can see that effect in the final column in this example where sites.name is the data shown in the column but users.site is the field to be edited.

    Regards,
    Allan

  • rprobinsonrprobinson Posts: 14Questions: 3Answers: 0

    I don’t think it will be easy to add a column.editField option property.

    A subset of the columns for the table on my web page change dynamically, based on a value they select in a drop down that pulls data for the table.

    Also, the columns they can edit is controlled by a setup page. And on top of everything, they control the column name.

    We also have authorization to, some end user can edit; others can not. At run time I determine the edit state of the web page. If can’t edit, I don’t need the editor. If can edit, we enable an edit button – when selected, I need to enable columns according to what they defined as “edit”. When they are done with the edit, i'll need to update calculated columns and persist the changes to the database.

    On initial display of the table I need to sum columns (which also are user controlled to specify). Once I have the edit capability working, the algorithm will need to execute again.

    The code is working for the initial displaying of data. I’m adding the edit capability now. Right or wrong, I get the data and work with the column heading then the actual data contained in an array; check some things, then create the Editor instance and table instance.

    Conclusion, I don't see an easy way to add and editor property to the columns. I will attempt to post another comment with code snippets of interest.

  • rprobinsonrprobinson Posts: 14Questions: 3Answers: 0
        function populateView()
        {
    
            // Now get the data
            $.ajax({
                "url": getPlanningData,
                data: { "costCenter": costCenter },
                async: false,
                "success": function (json) {
    
                    // debugger;
                    var columnOff = ["{'bSortable': false}"]
                    planningHeadings = buildColumnHeaders(json.dataColumnHeaders, costCenter);  <-- this figures out columns of interest and return a bunch of column indexes
                    planningData = json.rawData;
    
                    drawCallbackCounter = 0;        // reset our counter.  Temp work around until we can figure out why callback is getting called
                                                    // multiple times
    
                    // In theory, the editor is created first, then the table
    
                    setupEditor(json.dataColumnHeaders, planningHeadings.columnHdrs);  <-- this sets up the editor.  I'll post the code below
    
                    debugger;
                    table = $('#example').DataTable({
                        // dom: "Bfrtip", lfrtip
                        dom: "lrtip",
                        data: planningData,
                        columns: planningHeadings.columnHdrs,  <-- this is where i'd have to make major changes to add the editor property
                        columnDefs: [
                            { "asSorting": [] },
                            {
                                "createdCell": function (td, cellData, rowData, row, col) {
                                    var color;
                                    if (cellData <= 0 || cellData == '') {
                                        color = holidayBGColor;
                                        $(td).css('background', color);
                                    }
                                },
                                "targets": [planningHeadings.forecastColumnIdx]
                            },
    
                            {   // Total Demand calculated column
                                "createdCell": function (td, cellData, rowData, row, col) {
                                    // debugger;
                                    var breakoutTotal = 0;
                                    var demandTotal = 0;
    
    
                                    for (var i = planningHeadings.startBreakOutColumnIdx; i <= planningHeadings.endBreakoutColumnIdx; i++) {
                                        breakoutTotal = breakoutTotal + parseInt(rowData[i]);
                                    }
                                    //                 (FC% * FC Column Qty)                                                                                                                 + (TD% * Total demand quantity by date)
                                    demandTotal = Math.ceil((Number(rowData[planningHeadings.percentageFCColumnIdx]) * Number(rowData[planningHeadings.forecastColumnIdx])) + (Number(rowData[planningHeadings.percentageDemandColumnIdx]) * breakoutTotal));
                                    rowData[planningHeadings.totalDemandColumnIdx] = demandTotal.toString();
                                    $(td).html(demandTotal);
                                },
                                "targets": [planningHeadings.totalDemandColumnIdx]
                            },
                            {   // Balance calculated column
                                "createdCell": function (td, cellData, rowData, row, col) {
                                    // debugger;
                                    var balance = 0;
                                    var previousDayBalance = 0;
                                    var crntRowIdx = parseInt(rowData[planningHeadings.displayRowIdx]);        // Actual displayed value, not the true idx
    
    
                                    // The very first balance record ever for a cost center the formula = “today’s” capacity – “today’s” total demand
                                    // Otherwise Formula = previous day’s balance + “today’s” capacity – “today’s” total demand
                                    if (crntRowIdx == 0) {
                                        balance = parseInt(rowData[planningHeadings.capacityColumnIdx]) - parseInt(rowData[planningHeadings.totalDemandColumnIdx]);
                                        previousRowData = rowData;
    
                                    } else if (crntRowIdx > 0) {
                                        previousDayBalance = parseInt(previousRowData[planningHeadings.balanceColumnIdx]);
                                        balance = previousDayBalance + parseInt(rowData[planningHeadings.capacityColumnIdx]) - parseInt(rowData[planningHeadings.totalDemandColumnIdx]);
                                        previousRowData = rowData;
                                    }
                                    rowData[planningHeadings.balanceColumnIdx] = balance.toString();
                                    $(td).html(balance);
                                },
                                "targets": [planningHeadings.balanceColumnIdx]
                            },
                            {
                                "targets": [planningHeadings.rowIdx],
                                "visible": false
                            },
    
    
                             { "orderable": false, "targets": '_all' }
                        ],
                        rowId: '0',
                        ordering: false,
                        paging: false,
                        fixedHeader: {
                            header: true,
                            footer: true
                        },
                        keys: {
                            columns: ':not(:first-child)',
                            editor: editor,
                            editorKeys: 'tab-only'
                        },
                        select: {
                            style: 'os',
                            selector: ':not(readonly)',
                            blurable: true
                        },
    
                        buttons: [
                            { extend: "create", editor: editor },
                            { extend: "edit", editor: editor },
                            { extend: "remove", editor: editor }
                        ],
                        "drawCallback": function (settings) {
                            // debugger;
                            drawCallbackCounter = drawCallbackCounter + 1;
    
                            if (drawCallbackCounter == 4) {
                                var api = this.api();
                                postProcessing(api);
                            }
                        }
                    });
    
    }
    
    
        function setupEditor(dataColumnHeaders, columnHdrs) {
            if (userAuthorization == USER_AUTHORIZATION.UPDATE) {
                // debugger;
                // Build the fields needed by the editor
                var fields = [];
    
                for (var i = 0; i < dataColumnHeaders.length; i++) {
                    fields[i] = {
                        label: columnHdrs[i].title,
                        name: i.toString()
                    }
                }
                debugger;
                editor = new $.fn.dataTable.Editor({
                    // ajax: "../php/staff.php",
                    table: "#example",
                    fields: fields,
                    idSrc: "0"
                });
    
            }
        }
    
    
        $(document).ready(function () {
            var thisWeekSunday = moment().startOf('week');
            var crntWeekTitle = "Current Week - " + thisWeekSunday.format("MM/DD/YY");
            //debugger;
            $('#CurrentWeekLbl').text(crntWeekTitle);
    
            $("#btnEditMainPage").on("click", editMainPage);
            $("#btnCancelMainPageChanges").on("click", cancelChanges);
            $("#btnCancelMainPageChanges1").on("click", cancelChanges);
            $("#btnSaveMainPageChanges").on("click", saveChanges);
            $("#btnSaveMainPageChanges1").on("click", saveChanges);
    
            getUserSettings();
            setUserAuhtorization();
    
    
            $('#demo').html('<table id="example" class="display" cellspacing="0" width="100%"></table>');
            populateddlCostCenter();
            populateView();     <-- this is a common function used on init and when user selects a value from the drop down
            toggleDebugView();
    
    
    
    
            // Inline editing on click
            $('#example').on('click', 'tbody td:not(:first-child)', function (e) {
                // debugger;
                crntCell = table.cell(this);
    
                crntColumnHandle = crntCell[0];
                crntColumnNbr = crntColumnHandle[0].column;
                crntRowNbr = crntColumnHandle[0].row;
                editor.inline(this, crntColumnNbr.toString());
            });
    
            // Inline editing on tab focus
            table.on('key-focus', function (e, datatable, cell) {
                // debugger;
                var myCell = cell.index();
                crntColumnNbr = myCell.column;
                crntRowNbr = myCell.row;
                editor.inline(cell.index(), crntColumnNbr.toString());
            });
    
        });
    
  • allanallan Posts: 63,498Questions: 1Answers: 10,470 Site admin
    Answer ✓

    Perfect - thank you for the code.

    Change:

                    fields[i] = {
                        label: columnHdrs[i].title,
                        name: i.toString()
                    }
    

    to be:

                    fields[i] = {
                        label: columnHdrs[i].title,
                        name: i.toString(),
                        data: i
                    }
    

    I believe that should resolve the issue. You are using column indexes for the data indexes to store the data, so fields.data will also use the index.

    Its the .toString() that is causing the issue - it means that a strict type check (which Editor uses) will fail for column indexes - i.e. 1 === '1' is false.

    Editor has the ability to use a different name from its data point, which is why the above should work.

    Having said that, I think you could also just use:

                    fields[i] = {
                        label: columnHdrs[i].title,
                        name: i
                    }
    

    I haven't tested it, but I can't think off the top of my head why it wouldn't work... :)

    Regards,
    Allan

  • rprobinsonrprobinson Posts: 14Questions: 3Answers: 0

    That did the trick, thanks.

This discussion has been closed.