Search code examples
tabulator

Is it possible to change the formatter for a single cell in tabulator?


I have a table that has one column that tends to be long, the user wants this to display normally (i.e. as text and have it truncated with elipsis) when the table first loads. If they click on this notes cell, they would like it to expand and show the entire field contents. I have this working by removing the column and adding a "new" one with the same definition, just adding a specification of formatter: 'textarea' on the new column. This almost does what I want, the only thing I'm running into is that this causes all of the rows to expand, what I really want is only the one they clicked on. Is this possible to do with tabulator, if so how?

Here's a code snippet, not sure if it's needed here or not:

    ctrl.activities = [
  {
    "Completed": false,
    "Notes": "Pork loin strip steak andouille, kevin cow porchetta spare ribs rump. Leberkas capicola jerky cow. Shank pork loin bacon fatback boudin t-bone flank. Porchetta filet mignon brisket, pork loin boudin short loin burgdoggen chuck beef short ribs fatback ham chicken prosciutto biltong. Shoulder buffalo pork andouille, doner ground round sausage porchetta chicken beef ribs spare ribs. Prosciutto bresaola doner ham bacon drumstick ground round shankle kielbasa. 1"
  },
  {
    "Completed": false,
    "Notes": "followup future"
  },
  {
    "Completed": false,
    "Notes": "dac"
  },
  {
    "Completed": false,
    "Notes": "dac"
  },
  {
    "Completed": false,
    "Notes": "Spare ribs cupim turducken pastrami. Alcatra ground round venison jowl chuck meatball turducken hamburger shoulder fatback frankfurter tenderloin ham. Short ribs spare ribs pig flank, frankfurter turkey biltong pork chop hamburger alcatra ball tip. Turkey filet mignon cupim shankle sirloin kielbasa brisket pork fatback ham pig turducken jerky bacon."
  }
];

    el.tabulator({
        layout: 'fitColumns'
        , responsiveLayout: 'hide'
        , placeholder: 'No activities'
        , data: ctrl.activities
        , columns: [{{
                title: 'Notes'
                , field: 'Notes'
                , minWidth: 100
                , cellDblTap: notesClick
                , cellClick: notesClick
            }, {
                title: 'Toggle'
                , headerSort: false
                , field: 'Completed'
            }]

    function notesClick(e, cell) {
        $log.debug({type: 'tabulator cell click', e, cell});
        tabActivities.tabulator('deleteColumn', 'Notes');
        tabActivities.tabulator('addColumn', {
            title: 'Notes'
            , field: 'Notes'
            , formatter: 'textarea'
            , variableHeight: true
            , cellDblTap: expandedNotesClick
            , cellTap: expandedNotesClick
            , cellClick: expandedNotesClick
        }, true, 'Completed');
    }

    function expandedNotesClick(e, cell) {
        $log.debug({type: 'tabulator cell click', e, cell});
        tabActivities.tabulator('deleteColumn', 'Notes');
        tabActivities.tabulator('addColumn', {
            title: 'Notes'
            , field: 'Notes'
            , minWidth: 100
            , cellDblTap: notesClick
            , cellTap: notesClick
            , cellClick: notesClick
        }, true, 'Completed');
    }

Solution

  • The only difference between the normal text formatter and text area formatter built into tabulator is that the text area formatter sets the css white-space value to pre-wrap

    so actually you wouldn't need to change the formatter at all, you would just need to toggle the cells white-space property between pre-wrap and normal and then call the normalizeHeight function on the row component to reset the height of that one row.

    cellClick(e, cell){
        var el = cell.getElement();
    
        el.css("white-space",  el.css("white-space") === "pre-wrap" ? "normal" : "pre-wrap");
        cell.getRow().normalizeHeight();
    }
    

    Here's what I ended up with that did the trick:

        if(el.css('white-space') === 'pre-wrap') {
            el.css('white-space', 'nowrap');
            cell.getRow().reformat();
        } else {
            el.css('white-space', 'pre-wrap');
            cell.getRow().normalizeHeight();
        }