Creating an editor to View a record with a custom template

Creating an editor to View a record with a custom template

Peter BurtonPeter Burton Posts: 3Questions: 1Answers: 0

I have a standard "edit" button which pops up the default editor form for my datatable.

I also have a "viewer" which is an editor instance I created in code that is read only. It has its own button "view" that pops up the "viewer". Easy enough.

Then, we got a requirement to use a custom template for the form. Also easy enough. Added the template. Works on the "edit" editor.

(At this point, both the standard editor and the new "view" editor have the "template" property set to "#customForm" which is the id of my template div in the dom)

But... it only works for the "edit" form, not for the "view" form, which is a different editor instance.

I walked the code in dataTables.editor.js, and found the problem.

My custom template is getting detached in initialization of the first editor (the "edit" editor).

When the second editor (the "view" editor) is initialized, the template is not there anymore (it seems). The "view" editor still tries to use a template, so the form pops up blank.

I solved it by updating the dataTables.editor.js to not "detach()" the template in initialization, and not "put it back" in the dom when the editor is destroyed.

Obviously, I don't want to be editing dataTables.editor.js.

Do you have another way to address this problem?

Thanks,

Peter

Answers

  • Peter BurtonPeter Burton Posts: 3Questions: 1Answers: 0

    Hi,
    So I came up with a solution to my own problem. It seems like not a terrible way to handle the requirement. Not ideal, but livable.

    I created two template divs for the two editor instances (the default "edit" editor and my added "view" editor which extends the defaut one).

    I then pointed the "template" property of the "edit" editor to one, and the template property of the "view" editor to the other.

    The template divs are identical, except for their id property, so that I can point one editor to one, and the other editor to the other.

    Then I had to make sure the styling was done by class not by id, since they don't have the same id

    And that worked! And didn't require me to change any code in dataTables.editor.js.

    Thanks. If there is a better way, let me know, but I am satisfied with this solution.

    Peter

  • allanallan Posts: 56,819Questions: 1Answers: 9,029 Site admin

    Hi Peter,

    That sounds like a good workaround for now! I've often wondered how we can offer a "View" mode for Editor, but it could potentially be so different from the form, that I've never managed to come up with a nice modular way of doing it.

    One possibility is that we expose the modal API that we have in Editor to make it usable outside of Editor, then everything displayed inside it would be up to the author (i.e. yourself :)).

    Allan

  • sinfuljoshsinfuljosh Posts: 25Questions: 0Answers: 5
    edited December 2021

    If you look as some of my past replies (I only have like 6 of them) back in 2018 I was working on custom templates and I had posted screenshots of my template as well as a base custom template html that can be called up by editor.

    The work around I came up with was converting the fields from form fields to read only inputs and altered the css so you never see the browser inputs boxes.

  • Peter BurtonPeter Burton Posts: 3Questions: 1Answers: 0

    FYI, here was my (partial) code to create a generic viewer with the same custom form template I use for the generic editor:

    First, I add a couple of divs to the body. One is a custom template for the editor, and the other is a custom template for the viewer. They are identical, except for the id. I use a naming convention of adding "-viewer" to the end of the editor template id. (later I will use .disable() on the "viewer" editor to make it read-only)

    I am using a config to represent the data I need to create the data table generically. This way, I can use this code for any datatable I want. I just create the config, and get generic editors and viewers for any row. I wanted my template to group the fields together, so I added "fieldgroup" property to the columns so I can group them in my custom template. The result is each group gets a header, and a list of fields underneath it.

    (Note: the groupBy is just a javascript function I copied to group an array by an attribute of each element in the array)

    var groupBy = function (array, key) {
        return array.reduce(function (rv, x) {
            (rv[x[key]] = rv[x[key]] || []).push(x);
            return rv;
        }, {});
    };
    
    function createEditorTemplate() {
        // if the editor has a custom template, create the template
        if (config.EditorTemplate != null) {
            var editorTemplate = document.createElement('div');
            editorTemplate.classList.add(config.EditorTemplate);
            var fieldGroups = groupBy(config.Columns, 'fieldgroup');
            for (var fieldGroup in fieldGroups) {
                var fieldSet = document.createElement('fieldset');
                fieldSet.classList.add('name');
                editorTemplate.appendChild(fieldSet);
                var legend = document.createElement('legend');
                legend.innerHTML = fieldGroup;
                fieldSet.appendChild(legend);
                for (var f = 0; f < fieldGroups[fieldGroup].length; f++) {
                    var field = fieldGroups[fieldGroup][f];
                    var editorField = document.createElement('editor-field');
                    editorField.setAttribute('name', field.data);
                    fieldSet.appendChild(editorField);
                }
            }
    
            // make a copy of the template for the viewer (datatables.editor detaches the template when initializing the first editor, so we can't reference that anymore for the second (viewer) editor).
            var viewerTemplate = editorTemplate.cloneNode(true);
            editorTemplate.id = config.EditorTemplate;
            viewerTemplate.id = config.EditorTemplate + '-viewer';
            document.body.appendChild(editorTemplate);
            document.body.appendChild(viewerTemplate);
        }
    }
    
    
    

    then I create the viewer:

        viewer = new $.fn.dataTable.Editor({
            table: tableName,
            idSrc: config.IdSrc,
            template: config.EditorTemplate == null ? '' : '#' + config.EditorTemplate + '-viewer',
            fields: config.Fields,
        }).disable();
    
    

    I add a "view" button to my collection of buttons to pop up the viewer.

        buttons.push({
            extend: "edit",
            text: "View",
            className: "buttons-view",
            action: function (e, dt, node, config) {
                viewer
                    .edit(getSelectedRowIndex(),
                    {
                        title: 'View entry',
                    })
                    .disable();
            }
    

    The getSelectedRowIndex()... well... gets the selected row index from the datatable.

    I'm not sure if the .disable() in both the button action and the viewer creation is redundant. Haven't tested that... but it works as is with both.

    I add some css to style the template (piggybacking off datatables.net's sample css for the custom forms sample), and it looks pretty good!

    This works nicely to provide a generic viewer to go along with a generic editor, both sharing a custom form. The only difference is, one is editable, one is not.

  • allanallan Posts: 56,819Questions: 1Answers: 9,029 Site admin

    That's awesome - thanks for sharing that with us.

    Allan

Sign In or Register to comment.