Multiple Select in Tabulator - tabulator

Is it possible to have one select field depend on the previous one?
Users select one value from select_1 then accordingly the value in select_2 change. Maybe a custom formatter?
const newCol = {//create column group
title: oldRow.title,
field: oldRow.field,
columns: [
{
title: rowData.select1.title, field: rowData.select2.name, editor: 'select',
editorParams: {values: rowData.select1.values}
},
{
title: rowData.select2.title, field: rowData.select2.name, editor: 'select',
editorParams: function (cell) {
console.log(cell)
return {values: [1, 2, 3]}
}
},
],
}
From above I need select1 selected value.

Would this work Editors?:
"If you want to generate the options when the select editor is triggered, then you can pass a function into the editorParams, that must return the option list in one of the two formats outlined above"
{title:"Name", field:"name", editor:"select", editorParams:function(cell){
//create a options list of all values from another column in the table
var rows = table.getRows();
var values = {};
rows.forEach(function(row){
var data = row.getData();
values[data.fullname] = data.fullname;
});
return {values:values};
}
Instead of fetching the all the rows, just fetch the cell value of the previous select column and use that to build the choices for the current select. This sort of depends on the specifics of how the two columns relate to each other. More information on that would be helpful.

Related

SUBSTITUTE based on a table of replacement strings

I have a list of business names and addresses in A, and shortened versions of just the business names with an added store # shown in B,
I would like to be able to paste a set of data into column D and have the file automatically find and substitute based on the info in the table, and output to column E.
The total number of potential substitutions is >200, so a nested SUBSTITUTE function would very quickly get too messy.
The sheet must handle multiples of the same entries in column D. i.e. The same business can appear multiple times in the raw data, and I want each entry to be subbed.
A4 and A5 represent the same location for my purposes, so the output needs to be the same between them.
A9 include a comma after "Sobeys", so the data formatting is not reliable enough to find the first comma and erase everything after.
This is currently being handled in Google Sheets, but if a more accessible solution exists in Excel I'd be willing to work there just for the substitutions. I've seen similar questions answered using QUERY or ARRAYFORMULA, but I'm out of my depth to try and adjust those answers to suit my needs here. Thank you!
To replace a big amount of data, try this (you have to enable the service Google Sheets API )
function replacements() {
const ar = [
{ text: "Example 1", newText: 'text1' },
{ text: "Example 2", newText: 'text2' },
{ text: "Example 3", newText: 'text3' },
];
const requests = ar.map(({ text, newText }) => ({ findReplace: { allSheets: true, find: text, replacement: newText, matchEntireCell: true, matchCase: true } }));
Sheets.Spreadsheets.batchUpdate({ requests }, SpreadsheetApp.getActive().getId());
}
You can construct the ar matrix based on your sheet in a separate spreadsheet (otherwise your table will also update). For instance
function replacements() {
var ar = []
var data = SpreadsheetApp.openById('id of the spreadsheet that contains the table').getSheets()[0].getDataRange().getValues()
data.forEach(function(r) {
var prov = {}
prov['text']=r[0]
prov['newText']=r[1]
ar.push(prov)
})
const requests = ar.map(({ text, newText }) => ({ findReplace: { allSheets: true, find: text, replacement: newText, matchEntireCell: true, matchCase: true } }));
Sheets.Spreadsheets.batchUpdate({ requests }, SpreadsheetApp.getActive().getId());
}

Copying Tabulator data from one table to multiple tables using the setData() function produces unpredictable results

I am using Tabulator for client-side entry and editing of tabular data. In my application I have need to copy the data from a single [Crew Leader] table to one or more [Crew Member] tables. After data for the [Crew Leader] is entered I am making use of a button to trigger the copying process to the [Crew Member] tables. This is accomplished using the Tabulator setData() function which works as expected.
After data has been copied to the [Crew Member] tables it is necessary to edit each row with information pertinent to the individual [Crew Member]. The on-screen editing process works as expected.
My problem arises when I go to export the data. Note, the data in my JSON string:
is not the same as what appears on-screen; and
is the same for all [Crew Member] tables.
It appears the changes being applied to one [Crew Member] table are being applied (in the virtual DOM) to all [Crew Member] tables. Stated differently, with two "cloned" tables the changes applied to table one are applied to table two in the virtual DOM but not on-screen (and vice versa).
Client-side script which does the copying from the [Crew Leader] table to the [Crew Member] table(s):
function CloneTable() {
var tableCrewLeader = Tabulator.prototype.findTable('#CrewLeaderTable')[0];
var dataCrewLeader = tableCrewLeader.getData();
if (tableCrewLeader.getDataCount() > 0) {
// Verify a Tabulator table is present for each selected [Crew Member] by
// looping through each <div> element with the class "crew-member-card".
$(".crew-member-card").each(function () {
if ($(this).attr('id').length > 0) {
const divId = "#" + $(this).attr('id').replace('Card', 'Table');
const tableMember = Tabulator.prototype.findTable(divId);
if (tableMember.length > 0) {
const tableCrewMember = Tabulator.prototype.findTable(divId)[0];
tableCrewMember.setData(dataCrewLeader);
}
else {
console.log("The Tabulator table " + divId+ " was not found.");
}
}
});
}
}
It is also worth noting, these anomalies do not occur when the data for the [Crew Member] tables is entered directly (no setData() method is used). On-screen edits/changes are not reflected in other tables when data was not copied to the table originally.
For what it's worth, the following is the loop I use to verify the contents of each [Crew Member] table row (using Firefox Web Console to view the log):
var dataCrewMember = tableCrewMember.getData();
$(dataCrewMember).each(function () {
console.log(this);
});
EDIT
I have eliminated the disparity between the on-screen data and the exported data by setting the reactiveData attribute in my Tabulator constructor, as follows:
var table = new Tabulator(divid, {
height: "100%",
layout: "fitDataFill",
reactiveData: true, //enable reactive data
movableRows: true,
tabEndNewRow: true,
rowContextMenu: myActionContextMenu,
keybindings: {
"navUp": true,
"navDown": true,
},
columns: [
{ title: "Phase Code", field: "Phasecode", width: 144, editor: "select", editorParams: { values: function (cell) { return window.laborPhaseCodes; } } },
{ title: "Date Worked", field: "DateComp", hozAlign: "center", sorter: "date", editor: dateEditor },
{ title: "Start Time", field: "TimeStart", hozAlign: "center", sorter: "time", editor: timeEditor },
{ title: "Finish Time", field: "TimeFinish", hozAlign: "center", sorter: "time", editor: timeEditor },
{ title: "Memo", field: "Memo", width: 144, hozAlign: "left", editor: "input" },
{ title: cloneString, headerSort: false, headerClick: CloneTable, rowHandle: true, formatter: "handle" }
],
});
Note, however, I am still experiencing the issue wherein a change made in one [Crew Member] table is automatically replicated within the other [Crew Member] tables. This only happens when the data in the [Crew Member] tables has been populated using the setData() method.
Any assistance is greatly appreciated.
Inside of your cloneTables function, you set dataCrewLeader = tableCrewLeader.getData(). Then you use dataCrewLeader as the value in each of the newly created tables. I can only assume that these are being passed as a reference because they are objects. So, changing one changes them all. (I don't know if this is a bug or if it is expected that tabulator create copies when calling setData().)
To fix this, instead of setting a variable to the value. You want to call .getData() multiple times. So, you could do tableCrewMember.setData(tableCrewMember.getData()) and it will work as expected.
You can comment/uncomment the lines inside of the copyData function from the below example to see the issue.
Edited the example, so that it works without changing anything.
https://jsfiddle.net/nrayburn/85ecbvys/36/

SuiteScript2.0 Getting values from a saved search formula column

I am trying to get the value from a formula field in a saved search. I am getting all the results and then looping through them as such.
for(key in itemReplenishResults){
log.debug("Single Data", JSON.stringify(itemReplenishResults[key]));
var thisNumber = Number(itemReplenishResults[key].getValue("formulanumeric_1"))
}
The log for the single data read as I would expect;
{
"recordType": "inventoryitem",
"id": "2131",
"values": {
"itemid": "ITEMCODE",
"displayname": "DISPLAYNAME",
"salesdescription": "SALESDESCRIPTION",
"type": [
{
"value": "InvtPart",
"text": "Inventory Item"
}
],
"location": [],
"locationquantityonhand": "",
"locationreorderpoint": "0",
"locationpreferredstocklevel": "1",
"formulatext": "Yes",
"formulanumeric": "1",
"locationquantityonorder": "",
"formulanumeric_1": "1",
"formulatext_1": "Yes"
}
}
But the value of thisNumber is returned as 0. I do not understand why this is not working?
The reason thisNumber is 0 is because the column formulanumeric_1 actually doesn't exist, so Number() is converting a null value to 0.
The problem
Formula columns are all named the same internally, which is why you can't directly get their values individually. For instance, if you have two Formula (Numeric) columns in your search, both internal column names will be "formulanumeric". Therefore, using getValue('formulanumeric') will get only the first formula value.
Logging a Result object will output the incorrect names as you have seen. If you log Result.columns you will see that the column names are actually the same.
Your choices
Directly get columns using indexes (if you care about ordering).
require(['N/search'], function(search) {
// A saved search containing multiple formula result columns
var s = search.load(1234);
s.run().each(function(result) {
log.debug(result.getValue(result.columns[5]));
log.debug(result.getValue(result.columns[1]));
log.debug(result.getValue(result.columns[3]));
});
});
Loop through each column (if you don't care about ordering).
require(['N/search'], function(search) {
// A saved search containing multiple formula result columns
var s = search.load(1234);
s.run().each(function(result) {
for (var i = 0; i < result.columns.length; i++) {
// Log each column's value in order
log.debug(result.getValue(result.columns[i]));
}
});
});
Manually define columns and reference them (the most versatile option). Column names must start with "formula[type]" and can be appended with anything else.
require(['N/search'], function(search) {
var s = search.create({
type: 'salesorder',
columns: [{
name: 'formulanumeric1',
formula: 'CASE WHEN 100 > 10 THEN 100 END'
}, {
name: 'formulanumeric2',
formula: 'CASE WHEN 30 > 20 THEN 30 END'
}]
});
s.run().each(function(result) {
log.debug(result.getValue('formulanumeric2')); // 30
log.debug(result.getValue('formulanumeric1')); // 100
});
});
NOTE: If you go with the first option, you'll have to be careful about reordering the columns in your initial search, as that will affect the indexing in the results.
When I'm working with formula fields, I always use the column index values. An example of one that I have is below. This matches up with the fifth column I created (starting at 0, of course). Hope that helps.
transactionSearch.run().each(function(r){
var var1=r.getValue(r.columns[5]);
var var2=r.getValue(r.columns[6]);
var var3=r.getValue(r.columns[7]);
var var4=r.getValue(r.columns[8]);
var var5=r.getValue(r.columns[9]);
return true;
});

React-Bootstrap-Table-Next Only One Row of Data in Table

I am trying to create a table for my website and for some reason it is only showing the first row of data.
This is how I am formatting the columns of the data:
const { items } = this.props.item;
// console.log({ items });
// react - bootstrap - table - next
const columns = [{
dataField: 'team',
text: 'Team',
sort: true,
formatter: (cellContent, row, rowIndex) => (
Object.values(row.team)[rowIndex]
)
}, {
dataField: 'current_Rank',
text: 'Current Rank',
sort: true,
formatter: (cellContent, row, rowIndex) => (
Object.values(row.current_Rank)[rowIndex]
)
}, {
dataField: 'new_Rank',
text: '321 Rank',
sort: true,
formatter: (cellContent, row, rowIndex) => (
Object.values(row.new_Rank)[rowIndex]
)
}];
This is how I am returning the table so that it renders the table:
return (
<BootstrapTable
keyField="team"
data={items}
columns={columns}
striped
hover />
)
}
}
The data:
Picture from the console
Live site: https://nhl-321-pointsystem.herokuapp.com/
I looked up your network response for /api/items API call, and found out that the data contains only one item. This being one of the reason you're seeing a single row when the table is rendered.
Please note the, another reason for the issue is, react-bootstrap-table-next key
data accepts a single Array object. And not array of single object.
You should re-arrange your data so that key 'team' will be present for all items in the array. And rest of the column header values (e.g. current_Rank) are available for each like.
Something like a reformat function I created in the sandbox available here.
Plus point - After you apply the reformat function, you won't need formatter for each column unlike your previous solution.
Alternate but recommended solution would be to send the formatted response from the API endpoint only, instead of re-parsing and creating new object to fit the needs of UI.
Sandbox link - https://codesandbox.io/embed/32vl4x4oj6

Kendo UI Grid search as type example

I would like to search datagrid in Kendo UI during typing into input field above the grid.
How can I do it?
Thanks for any advice.
Here is example of columns:
$("#grid").kendoGrid({
dataSource: dataPacket,
filterable: true,
pageSize: 10,
pageable: true,
sortable: true,
reorderable: true,
resizable: true,
columnMenu: true,
height: 550,
toolbar: ["create", "save", "cancel"],
columns: ["id",
"username",
"name",
"surname",
"email",
{
field :"created",
title : "Created at",
format: "{0:M/d/yyyy}",
parseFormats: ["dd-MM-yyyy"],
type: "date"
},
Kendo make this thing really easy for you, what is needed is to create a filter and pass it to the DataSource.
http://docs.telerik.com/kendo-ui/api/framework/datasource#methods-filter
However, this problem must be divided into two different tasks:
a) Capture the key events in the search box, throttle it and start the search "operation".
b) Build a filter and pass it to the DataSource.
So for throttling the keyboard events, we need a timeout. Or use the throttle function from underscorejs. Why? We don't wanna trigger a search operation on each key press. Only 250 milliseconds (this number is up to you) after the last keystroke.
Here is your sample HTML
<input type="text" id="search" />
Here is your sample script. I wrap everything as a self calling function as you don't wanna create a mess declaring global variables.
(function($, kendo){
// ID of the timeout "timer" created in the last key-press
var timeout = 0;
// Our search function
var performSearch = function(){
// Our filter, an empty array mean "no filter"
var filter = [];
// Get the DataSource
var dataSource = $('#grid').data('kendoGrid').dataSource;
// Get and clean the search text.
var searchText = $.trim($('#search').val());
// Build the filter in case the user actually enter some text in the search field
if(searchText){
// In this case I wanna make a multiple column search so the filter that I want to apply will be an array of filters, with an OR logic.
filter.push({
logic: 'or',
filters:[
{ field: 'username', operator: 'contains', value: searchText },
{ field: 'name', operator: 'contains', value: searchText },
{ field: 'surname', operator: 'contains', value: searchText },
{ field: 'email', operator: 'contains', value: searchText }
]
});
}
// Apply the filter.
dataSource.filter(filter);
};
// Bind all the keyboard events that we wanna listen to the search field.
$('#search').on('keyup, keypress, change, blur', function(){
clearTimeout(timeout);
timeout = setTimeout(performSearch, 250);
});
})(window.jQuery, window.kendo);
Bottom-line: Make sure you are using the right DataSource configuration.
If you configured serverFiltering = true, this filtering logic will be part of your Ajax request, so your server will have to interpret and perform the filtering on server-side.
In case you configured serverFiltering = false all this filtering logic will be evaluated on client side using JavaScript (damn fast!). And in this case, the schema (what data-type is expected on each column) must be also well-configured.

Resources