Editor: different template for "Add new" record action

Editor: different template for "Add new" record action

matissgmatissg Posts: 63Questions: 15Answers: 0

I have this piece of code where I try to implement form template change when "New" record button is clicked:

var editor; // use a global for the submit and return data rendering in forms

(function() {
  var Editor = $.fn.dataTable.Editor;
  Editor.display.details = $.extend(true, {}, Editor.models.displayController, {
    init: function(editor) {
      // Setup the lightbox - we'll use it for new entries
      Editor.display.bootstrap.init(editor);
      return Editor.display.details;
    },

    open: function(editor, append, callback) {
      var table = $(editor.s.table).DataTable();
      var row = editor.s.modifier;

      // Close any rows which are already open
      Editor.display.details.close(editor);

      if (editor.mode() === 'create') {
        // No row being edited - its a new row. Use Editor's lightbox
        Editor.display.bootstrap.open(editor, append, callback);
      } else {
        // Open the child row on the DataTable
        table.row(row).child(append).show();

        $('div.DTE input:not([type=checkbox]):not([type=radio]), div.DTE select, div.DTE textarea').addClass('form-control');

        $(table.row(row).node()).addClass('shown');

        if (callback) {
          callback();
        }
      }
    },

    close: function(editor, callback) {
      if ($('div.modal div.DTE').length) {
        Editor.display.bootstrap.close(editor, callback);
      } else {
        var table = $(editor.s.table).DataTable();

        table.rows().every(function() {
          if (this.child.isShown()) {
            this.child.hide();
            $(this.node()).removeClass('shown');
          }
        });

        if (callback) {
          callback();
        }
      }
    }
  });
})();

// We start table with launching Editor
$(document).ready(function() {
  editor = new $.fn.dataTable.Editor({
    ajax: {
      create: {
        type: 'POST',
        url: '/ratecard/ratecards'
      },
      edit: {
        type: 'PATCH',
        url: '/ratecard/ratecards/_id_'
      },
      remove: {
        type: 'DELETE',
        url: '/ratecard/ratecards/_id_'
      }
    },
    table: "#ratecards-table",
    idSrc: "id",
    fields: [{
      label: "Name:",
      name: "name"
    }, {
      label: "Type:",
      type: "select",
      name: "status",
      "options": [{
          "label": "Ratecard",
          "value": "ratecard"
        },
        {
          "label": "Deal",
          "value": "deal"
        },
        {
          "label": "Inactive",
          "value": "inactive"
        }
      ]
    }]
  });

  // Here we render ratecards table
  var table = $('#ratecards-table').DataTable({
    dom: "<'row'<'col-sm-6'B>>" +
      "<'row'<'col-sm-12'tr>>" +
      "<'row'<'col-sm-5'l><'col-sm-7'p>>",
    ajax: $('#ratecards-table').data('source'),
    rowId: 'id',
    columns: [{
        className: 'details-control',
        orderable: false,
        data: null,
        defaultContent: '',
        width: 30
      },
      {
        data: "name"
      },
      {
        data: "status"
      },
      {
        data: "id"
      }
    ],
    columnDefs: [{
      targets: [-1],
      visible: false
    }],
    order: [
      [1, 'asc']
    ],
    buttons: [{
      extend: 'create',
      text: 'Add new',
      editor: editor,
      formButtons: [{
          label: 'Cancel',
          fn: function() {
            this.close();
          }
        },
        'Create',
      ]
    }, {
      extend: 'collection',
      text: 'Export',
      buttons: ['copy', 'excel', 'csv', 'print']
    }, {
      extend: 'colvis',
      columns: ':gt(0)'
    }]
  });  // more code follow here...

So far I've been looking to this example and tried to add to my code these lines:

  editor.on('preOpen', function(e, data, action) {
    if ( action === 'edit' ) {
      editor.template( '#ratecards-form' );
      editor.display ("details");
    }
    else if ( action === 'create' ) {
      editor.template( '#new_ratecard-form' );
    }
  });

however no luck so far. I get modal window for "New" record, which is OK, however for "Edit" I get an error: jquery-3.3.1.min.self-8...0e9.js?body=1:3 Uncaught RangeError: Maximum call stack size exceeded
When I close modal, then click any of "New/Edit" buttons, strange things happen - some empty modal, etc. It looks like I'm doing something wrong here.

How do I make for "New record" modal to show different template than for "Edit record", please?

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 63,500Questions: 1Answers: 10,471 Site admin

    Thanks for the details - I think I see the issue. The problem is that the display option which controls which display controller is used, does not equate with the display() method. The method will tell you what mode (if any) editing is being performed (or open the main editing form).

    If you want to have a details only form (the details display controller above), you'd need to have a second Editor instance configured for that display controller. At the moment each Editor instance can only have a single display controller and that can't be modified.

    Allan

  • matissgmatissg Posts: 63Questions: 15Answers: 0

    @allan Thank you for explaining.

    If I understand correctly, I have to create another instance something like new_record_editor = new $.fn.dataTable.Editor and another function something like

    (function() {
      var newRecordEditor = $.fn.dataTable.Editor;
       // more code for init, open, close
    })();
    

    Please, comment, if I have to do it differently.

  • allanallan Posts: 63,500Questions: 1Answers: 10,471 Site admin

    In essence yes - although you need to create a new instance using new as in your comment:

    var newRecordEditor = new $.fn.dataTable.Editor( {
      // options
    } );
    

    Allan

  • matissgmatissg Posts: 63Questions: 15Answers: 0
    edited June 2018

    @allan
    I have two Editor instances like this:

      new_record_editor = new $.fn.dataTable.Editor({
        ajax: {
          create: {
            type: 'POST',
            url: '/ratecard/ratecards'
          }
        },
        table: "#ratecards-table",
        // more code follow...
      });
    
      editor = new $.fn.dataTable.Editor({
        ajax: {
          edit: {
            type: 'PATCH',
            url: '/ratecard/ratecards/_id_'
          },
          remove: {
            type: 'DELETE',
            url: '/ratecard/ratecards/_id_'
          }
        },
        table: "#ratecards-table",
        // more code follow
      });
    

    So far I understood I have to create 2 functions - one for each instance. It seems to me that this one for "Edit" action is working:

    var editor; // use a global for the submit and return data rendering in forms
    (function() {
      var Editor = $.fn.dataTable.Editor;
      Editor.display.details = $.extend(true, {}, Editor.models.displayController, {
    
        init: function(editor) {
          return Editor.display.details;
        },
    
        open: function(editor, append, callback) {
          var table = $(editor.s.table).DataTable();
          var row = editor.s.modifier;
    
          // Close any rows which are already open
          Editor.display.details.close(editor);
    
          if (editor.mode() === 'edit') {
            // Open the child row on the DataTable
            table.row(row).child(append).show();
    
            $('div.DTE input:not([type=checkbox]):not([type=radio]), div.DTE select, div.DTE textarea').addClass('form-control');
    
            $(table.row(row).node()).addClass('shown');
    
            if (callback) {
              callback();
            }
          }
        },
    
        close: function(editor, callback) {
            var table = $(editor.s.table).DataTable();
    
            table.rows().every(function() {
              if (this.child.isShown()) {
                this.child.hide();
                $(this.node()).removeClass('shown');
              }
            });
    
            if (callback) {
              callback();
            }
        }
      });
    })();
    

    However second one for "Add New" is not working as it does not show my modal at all + there are no errors in my console:

    var new_record_editor;
    (function() {
      var newRecordEditor = $.fn.dataTable.Editor;
    
      newRecordEditor.display.details = $.extend(true, {}, newRecordEditor.models.displayController, {
        init: function(new_record_editor) {
          // Setup the lightbox - we'll use it for new entries
          newRecordEditor.display.bootstrap.init(new_record_editor);
        },
    
        open: function(new_record_editor, append, callback) {
          if (new_record_editor.mode() === 'create') {
            // No row being edited - its a new row. Use Editor's lightbox
            newRecordEditor.display.bootstrap.open(new_record_editor, append, callback);
          }
        },
    
        close: function(new_record_editor, callback) {
          if ($('div.modal div.DTE').length) {
            newRecordEditor.display.bootstrap.close(new_record_editor, callback);
          }
        }
      });
    })();
    

    What am I missing here, please?

  • allanallan Posts: 63,500Questions: 1Answers: 10,471 Site admin
    Answer ✓

    You shouldn't need that last block of code (newRecordEditor.display.details stuff). You've already defined the display.details option using the second block in your above code. So what I would expect is something like:

    new_record_editor = new $.fn.dataTable.Editor({
      ajax: {
        create: {
          type: 'POST',
          url: '/ratecard/ratecards'
        }
      },
      table: "#ratecards-table",
      display: 'details',
      // more code follow...
    });
     
    editor = new $.fn.dataTable.Editor({
      ajax: {
        edit: {
          type: 'PATCH',
          url: '/ratecard/ratecards/_id_'
        },
        remove: {
          type: 'DELETE',
          url: '/ratecard/ratecards/_id_'
        }
      },
      table: "#ratecards-table"
      // more code follow
    });
    

    In for the buttons for the table:

            buttons: [
                { extend: "create", editor: new_record_editor },
                { extend: "edit",   editor: editor },
                { extend: "remove", editor: editor }
            ]
    

    Allan

  • matissgmatissg Posts: 63Questions: 15Answers: 0

    @allan Oh, my bad - I missed I need to change in my buttons to { extend: "create", editor: new_record_editor }
    Now it works, thank you!

This discussion has been closed.