Pre-populate an edit forn for editor.create()

Pre-populate an edit forn for editor.create()

obrienjobrienj Posts: 93Questions: 38Answers: 0

I am planning to provide a "copy" button to the right of every row on the list screen. ("edit" and "delete" are a;ready there).

What "copy" is to do is create a new row with the data from the row where the "copy" button was clicked.

So what is the best solution to bring up the "create" editor window with the data pre-populated from the existing row?

Once the "create" editor window is displayed, all else will be as it is for my current "create" editor window.

Regards,
Jim

Answers

  • allanallan Posts: 63,192Questions: 1Answers: 10,412 Site admin

    Hi Jim,

    It sounds like this example is what you are looking for.

    Allan

  • rf1234rf1234 Posts: 2,941Questions: 87Answers: 415

    No need to show the Editor window to the user I guess. I mean if it is a simple copy?!
    I do something similar: Read data from a cookie fill an Editor instance invisible for the user and submit the data.

    So you would take the values from the copied record by selecting the record once the button is being clicked. Fill the Editor instance subsequently with the selected data and submit.

    This is part of my code for illustration. Since this Editor instance is never shown to the user it doesn't need any formatting or labels etc.

    var proposalCredEditorShort = new $.fn.dataTable.Editor( {
            ajax: {
                url: 'actions.php?action=tblProposalCred'
            },
            table: "#tblProposalCred",
            fields: [   { name:  "proposal.govdept_id" },
                        { name:  "proposal.instrument" }, 
                        { name:  "proposal.type"       },
                        { name:  "proposal.derivative" }
                    ]
        } );
    
    ck = '';
    ck = Cookies.getJSON('row');
    if (ck > '') {
        Cookies.remove('row');
        proposalCredEditorShort //short version of Editor without select etc.
            .create( false ) 
            .set( { 'proposal.govdept_id': ck.govdept.id,
                    'proposal.instrument': ck.rfp.instrument,
                    'proposal.type': ck.rfp.type,
                    'proposal.derivative': ck.rfp.derivative } )
            .submit();
    }
    

    Of course you can also show it to the user and ask for manual submission. Another example also based on a cookie.. But it is more work because you have to worry about Editor titles, buttons, language and what have you ...

    // if user comes from inbox offer and wants to create a new rfp the respective
    // department is being selected and a new RfP is initialized with the values
    // from the offer cookie
    ck = '';
        ck = Cookies.getJSON('row');
        if (ck > '') {
            Cookies.remove('row');
            rfpGovDeptTable.rows().every( function ( rowIdx, tableLoop, rowLoop ) {
                var data = this.data();
                if (data.govdept_has_user.govdept_id === ck.offer_has_govdeptview.govdept_id) {
                    rfpGovDeptTable.row(this).select();
                    rfpGovEditor
                        .title($.fn.dataTable.Editor.defaults.i18n.create.title)
                        .buttons( {
                            label: $.fn.dataTable.Editor.defaults.i18n.create.submit,
                            className: 'btn-showall-color',
                            fn: function () {
                                this.submit();
                            }
                        } )
                        .create()
                        .set( { 'rfp.instrument': ck.offer.instrument,
                                'rfp.type': ck.offer.type,
                                'rfp.derivative': ck.offer.derivative,
                                'rfp.amount': ck.offer.min_amount,
                                'rfp.currency': ck.offer.currency,
                                'rfp.repayment_method': ck.offer.repayment_method,
                                'rfp.ref_rate': ck.offer.ref_rate,
                                'rfp.ref_rate_period': ck.offer.ref_rate_period,
                                'rfp.negative_allowed': ck.offer.negative_allowed } );
                }
            });
        }
    
  • rf1234rf1234 Posts: 2,941Questions: 87Answers: 415

    @allan: that is certainly more elegant than my stuff :smile:

  • obrienjobrienj Posts: 93Questions: 38Answers: 0

    rf1234: My thanks for your input.

    allan: My requirement is that I pre-populate some fields in the new edit window from the columns of the selected row in the datatables list.

    The user is required (1) to complete the rest of the fields or (2) change the copied ones in the new row via the edit window.

    I can't tell from a quick look, but does the example you pointed to allow for that or is the example a "blind" copy?

    Regards,
    Jim

  • rf1234rf1234 Posts: 2,941Questions: 87Answers: 415

    My second example does exactly that. Some, but not all fields are pre-populated, the missing fields can be completed and all fields can be changed by the user.

  • allanallan Posts: 63,192Questions: 1Answers: 10,412 Site admin

    The example I linked to will copy the data from the selected row for all fields. But you could use the method @rf1234 highlighted, which is just to copy the values you want, if that is how you would prefer to do it.

    Allan

  • mpcleverdonmpcleverdon Posts: 19Questions: 2Answers: 0
    edited October 2019

    This is my solution for a joined table situation where I need the user to make a new record but based on a very similar existing record, just saving would cause a unique key error on the database so the user is reminded that something must change:

    Note: that the table id #mytable is reference inside the function also apart from the jquery select.

    //
    // "Duplicate" is clicked
    //
    $('#mytable').on('click', 'input.duplicate', function (e) {
       editor.create('You must change at least one field in order to copy this row.',
        {
            "label": "Create new row with this data",
            "fn": function () { this.submit(); }
        });
        var fieldlist = editor.fields();
        var dataTableObject = $('#mytable').dataTable();
        var data = dataTableObject.fnGetData($(this).parents('tr')[0]);
        var map = new Map(Object.entries(data));
        for (var [key, value] of map) {
                var ndata=map.get(key);
                if (typeof(ndata)=='object') {
                    var nmap = new Map(Object.entries(ndata));
                    for (var [nkey, nvalue] of nmap) {
                        if ($.inArray(key+"."+nkey, fieldlist) >= 0) {
                            editor.set(key+"."+nkey, nvalue);
                        }
                    }
                } 
            }
        var order=table.order();
        table.sort(order).draw();
    });
    

    The inline button in the first column in the table definition is as follows:

    rowCallback: function ( row, data ) {
        var ID=Object.values(data)[1]['PropertyID'];                
        $('td:eq(0)',row).html('<input type="image" class="duplicate" src="images/copy.png" />');
    }
    

    The table column is as follows, remember to stop _search _an _order _on null data:

    columns: [
        {
            "data": null,
            searchable: false,
            orderable: false
        },
    .
    .
    .
    

    It could very likely be neater but it works.

    Allan has the following simpler solution But I need the inline buttons:
    https://editor.datatables.net/examples/api/duplicateButton.html

    Mark

This discussion has been closed.