5

I'm using Tabulator.js to create an interactive table. I have a dropdown cell (editor type: select) and have found out how to show different labels when selecting from the list (instructions can be found here, the third way).

When I select something, the stored value is shown, but not the label (which is shown when you click on the list). I'd like the stored value to be the ID from the database, and I don't want the user to see it at all, just the label text.

Here is some example code:

var table = new Tabulator("#example-table", {
    data:tabledata,           //load row data from array
    layout:"fitColumns",      //fit columns to width of table
    responsiveLayout:"hide",  //hide columns that dont fit on the table
    tooltips:true,            //show tool tips on cells
    addRowPos:"top",          //when adding a new row, add it to the top of the table
    history:true,             //allow undo and redo actions on the table
    pagination:"local",       //paginate the data
    paginationSize:7,         //allow 7 rows per page of data
    movableColumns:true,      //allow column order to be changed
    resizableRows:true,       //allow row order to be changed
    initialSort:[             //set the initial sort order of the data
        {column:"name", dir:"asc"},
    ],
    columns:[                 //define the table columns
        {title:"Name", field:"name", editor:"select", editorParams:{
    values:{
        "steve":"Steve Boberson",
        "bob":"Bob Jimmerson",
        "jim":"Jim Stevenson",
    }
}},
    ],
});
Ginkgo
  • 155
  • 3
  • 10

4 Answers4

2

In similar situation like you, but I used a custom select or native dropdown. Here are the code to explain all: (uses formatters, keeping the real value...) Tabulator 4.6.3 DataList and DisplayList Demo for select editor

var userData = [{
  "FullName": "",
  "LoginName": "none"
}, {
  "FullName": "Steve Boberson",
  "LoginName": "steve"
}, {
  "FullName": "Bob Jimmerson",
  "LoginName": "bob"
}, {
  "FullName": "Jim Stevenson",
  "LoginName": "jim"
}];

var customNativeSelect = function(cell, onRendered, success, cancel) {
  var cellRealValue = cell.getElement().dataset.loginName;
  cellRealValue = (typeof cellRealValue === "undefined") ? "none" : cellRealValue;

  //Create and append select list
  var selectList = document.createElement("select");

  selectList.style.width = "100%";
  selectList.style.boxSizing = "border-box";

  onRendered(function() {
    selectList.focus();
    selectList.style.height = "100%";
  });

  function onChange() {
    if (selectList.selectedOptions[0].value != cellRealValue) {
      success(selectList.selectedOptions[0].value);
      // Store value to cell dataset; will be done by formatter
      /* cell.getElement().dataset.loginName = selectList.selectedOptions[0].value */
      alert("Here is what the actual looks like: " + JSON.stringify(cell.getTable().getData()))
    } else { // No change
      cancel();
    }
  }

  //submit new value on blur or change
  selectList.addEventListener("blur", onChange);

  //submit new value on enter
  selectList.addEventListener("keydown", function(e) {
    if (e.keyCode == 13) {
      onChange();
    }

    if (e.keyCode == 27) {
      cancel();
    }
  });

  //Create and append the options
  for (var i = 0; i < userData.length; i++) {
    var option = document.createElement("option");
    option.value = userData[i].LoginName;
    option.text = userData[i].FullName;

    if (userData[i].LoginName === cellRealValue) {
      option.selected = "selected";
    }
    selectList.appendChild(option);
  }

  return selectList;
};

var filterState = false;

var tabledata = [{
    itemId: '3423'
  },
  {
    name: 'steve'
  },
  {
    lastDate: '34/56/0000'

  },
  {
    completed: 'yes'
  }
];

var table = new Tabulator("#html-table", {
  data: tabledata, //assign data to table
  layout: "fitColumns",
  tooltips: true,
  tooltipsHeader: true,
  placeholder: "No Data Available", //display message to user on empty table
  height: "300px",
  columns: [{
    title: "ID",
    field: "itemId",
    headerFilter: false
  }, {
    title: "Name",
    field: "name",
    headerFilter: false,
    editor: customNativeSelect,
    formatter: function(cell) {
      var value = cell.getValue();

      for (var i = 0; i < userData.length; i++) {
        if (userData[i].LoginName === value) {
          // Store value to cell dataset
      cell.getElement().dataset.loginName = value;
      value = userData[i].FullName;
          break;
        }
      }
      return value;
    }
  }, {
    title: "Last Date",
    field: "lastDate",
    headerFilter: false
  }, {
    title: "Completed",
    field: "completed",
    headerFilter: false
  }, ]
});

function showHideFilters() {
  if (filterState == false) {
    table.updateColumnDefinition("itemId", {
      headerFilter: true
    });
    table.updateColumnDefinition("name", {
      headerFilter: true
    });
    table.updateColumnDefinition("lastDate", {
      headerFilter: true
    });
    table.updateColumnDefinition("completed", {
      headerFilter: true
    });
    filterState = true;
  } else {
    table.updateColumnDefinition("itemId", {
      headerFilter: false
    });
    table.updateColumnDefinition("name", {
      headerFilter: false
    });
    table.updateColumnDefinition("lastDate", {
      headerFilter: false
    });
    table.updateColumnDefinition("completed", {
      headerFilter: false
    });
    filterState = false;
  }

}
<link href="https://cdnjs.cloudflare.com/ajax/libs/tabulator/4.6.3/css/tabulator.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tabulator/4.6.3/js/tabulator.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>

<body>
  <button onClick="showHideFilters()">
    Show/Hide Filters
    </button>
  <div id="html-table">
  </div>
</body>

</html>
BirukTes
  • 45
  • 10
0

Just swap the values then

const tabledata = [{
    name: 'Steve Stevenson'
  },
  {
    name: 'Bob Boberson'
  },
  {
    name: 'Tim Timmersonn'

  },
  {
    name: 'Steve Boberson'
  }
];


const table = new Tabulator("#example-table", {
  data: tabledata, //load row data from array
  layout: "fitColumns", //fit columns to width of table
  responsiveLayout: "hide", //hide columns that dont fit on the table
  tooltips: true, //show tool tips on cells
  addRowPos: "top", //when adding a new row, add it to the top of the table
  history: true, //allow undo and redo actions on the table
  pagination: "local", //paginate the data
  paginationSize: 7, //allow 7 rows per page of data
  movableColumns: true, //allow column order to be changed
  resizableRows: true, //allow row order to be changed
  initialSort: [ //set the initial sort order of the data
    {
      column: "name",
      dir: "asc"
    },
  ],
  columns: [ //define the table columns
    {
      title: "Name",
      field: "name",
      editor: "select",

  
  editorParams: {
  
    values: {
      "Steve Boberson": "steve",
      "Bob Jimmerson": "bob",
      "Jim Stevenson": "jim"
    }
    
  }
    


    },
  ],
});
<!DOCTYPE html>

<html>

<head>

  <link href="https://unpkg.com/tabulator-tables@4.2.7/dist/css/tabulator.min.css" rel="stylesheet">
  <script type="text/javascript" src="https://unpkg.com/tabulator-tables@4.2.7/dist/js/tabulator.min.js"></script>


</head>

<body>
  <div id="example-table"></div>

</body>

</html>
dota2pro
  • 7,220
  • 7
  • 44
  • 79
  • Thanks for the answer. I know that I can reverse them, but I want to show 'Bob Boberson' in the list _and_ in the dropdown when you click, while retaining the stored value. Any idea on how to do that? – Ginkgo May 22 '19 at 12:44
  • What do you mean by **retaining the stored value** – dota2pro May 22 '19 at 14:20
  • I mean what is the use case of the value are you sending it some where or something ? – dota2pro May 22 '19 at 16:58
0

I encountered the same issue and I found simpler walkaround than creating custom select control. You can create a Map collection or Record which will map select keys on select values and then set up formatter function on a specific select column definition in which you can override the default display value.

composeSelectFormatter(dictionary) {
    return (cell) => {
        const value = cell.getValue();
        if (!value) return value;

        return dictionary[value];
}

}

And then in your column definition:

  columns: [ //define the table columns
    {
      title: "Name",
      field: "name",
      editor: "select",
      formatter: composeSelectFormatter(YOUR_DICTIONARY_RECORD_GOES_HERE),
      values: [ ... ]
  }
lukbrt
  • 308
  • 3
  • 8
0

I just found myself in the same scenario.

I used a formatter function and tracked down the values in the list created in the column definition with the editorParams: {values:{1: "xxxx", 2:"xxxx"}},.

    formatter: function(cell) {
        let cgv = cell.getValue();
        let values = cell?._cell?.column?.definition?.editorParams?.values;

        console.dir(values);

        if (cgv && values && values[cgv]) { return values[cgv]; }

        //If you are using the combo {label: "", value: ""} you need to loop through the object
        /*if (cgv && values && values.length) {    
            for (const v of values) {
                if (v?.value == cgv && v?.label) { return v.label;}
            }
        }*/

        return '';
    }
Puerto AGP
  • 393
  • 5
  • 11