diff --git a/packages/iris-grid/src/IrisGrid.tsx b/packages/iris-grid/src/IrisGrid.tsx index 3bdf4edce9..6299f53c03 100644 --- a/packages/iris-grid/src/IrisGrid.tsx +++ b/packages/iris-grid/src/IrisGrid.tsx @@ -2062,7 +2062,11 @@ class IrisGrid extends Component { return; } const row = data.rows[0]; - const values = keyTable.columns.map(column => row.get(column)); + // Core JSAPI returns undefined for null table values, IrisGridPartitionSelector expects null + // https://github.com/deephaven/deephaven-core/issues/5400 + const values = keyTable.columns.map( + column => row.get(column) ?? null + ); const newPartition: PartitionConfig = { partitions: values, mode: 'partition', diff --git a/packages/iris-grid/src/IrisGridPartitionSelector.tsx b/packages/iris-grid/src/IrisGridPartitionSelector.tsx index f8acc810d7..cd7df309f3 100644 --- a/packages/iris-grid/src/IrisGridPartitionSelector.tsx +++ b/packages/iris-grid/src/IrisGridPartitionSelector.tsx @@ -172,20 +172,19 @@ class IrisGridPartitionSelector extends Component< .slice(0, index + 1) .map((partition, i) => { const partitionColumn = t.columns[i]; - return partitionColumn - .filter() - .eq( - this.tableUtils.makeFilterRawValue( - partitionColumn.type, - partition - ) - ); + return this.tableUtils.makeNullableEqFilter( + partitionColumn, + partition + ); }); t.applyFilter(partitionFilters); t.setViewport(0, 0, t.columns); const data = await this.pending.add(t.getViewportData()); const newConfig: PartitionConfig = { - partitions: t.columns.map(column => data.rows[0].get(column)), + // Core JSAPI returns undefined for null table values, + // coalesce with null to differentiate null from no selection in the dropdown + // https://github.com/deephaven/deephaven-core/issues/5400 + partitions: t.columns.map(column => data.rows[0].get(column) ?? null), mode: 'partition', }; t.close(); @@ -214,7 +213,11 @@ class IrisGridPartitionSelector extends Component< getDisplayValue(index: number, value: unknown): string { const { model } = this.props; - if (value == null || value === '') { + if (value === null) { + return '(null)'; + } + + if (value === undefined || value === '') { return ''; } const column = model.partitionColumns[index]; @@ -267,14 +270,10 @@ class IrisGridPartitionSelector extends Component< const previousColumn = model.partitionColumns[i - 1]; const partitionFilter = [ ...previousFilter, - previousColumn - .filter() - .eq( - this.tableUtils.makeFilterRawValue( - previousColumn.type, - previousPartition - ) - ), + this.tableUtils.makeNullableEqFilter( + previousColumn, + previousPartition + ), ]; partitionFilters.push(partitionFilter); } diff --git a/packages/iris-grid/src/IrisGridTableModel.ts b/packages/iris-grid/src/IrisGridTableModel.ts index 277a7d868d..54593e2868 100644 --- a/packages/iris-grid/src/IrisGridTableModel.ts +++ b/packages/iris-grid/src/IrisGridTableModel.ts @@ -206,12 +206,11 @@ class IrisGridTableModel for (let i = 0; i < this.partitionColumns.length; i += 1) { const partition = partitions[i]; const partitionColumn = this.partitionColumns[i]; - - const partitionFilter = this.tableUtils.makeFilterRawValue( - partitionColumn.type, + const partitionFilter = this.tableUtils.makeNullableEqFilter( + partitionColumn, partition ); - partitionFilters.push(partitionColumn.filter().eq(partitionFilter)); + partitionFilters.push(partitionFilter); } const t = await this.table.copy(); diff --git a/packages/jsapi-components/src/TableDropdown.tsx b/packages/jsapi-components/src/TableDropdown.tsx index d9762e3766..2e8e342abc 100644 --- a/packages/jsapi-components/src/TableDropdown.tsx +++ b/packages/jsapi-components/src/TableDropdown.tsx @@ -82,7 +82,10 @@ export function TableDropdown({ dh.Table.EVENT_UPDATED, (event: CustomEvent) => { const { detail } = event; - const newValues = detail.rows.map(row => row.get(tableColumn)); + // Core JSAPI returns undefined for null table values, + // coalesce with null to differentiate null from no selection in the dropdown + // https://github.com/deephaven/deephaven-core/issues/5400 + const newValues = detail.rows.map(row => row.get(tableColumn) ?? null); setValues(newValues); } ); diff --git a/packages/jsapi-utils/src/TableUtils.ts b/packages/jsapi-utils/src/TableUtils.ts index 06d28f6b52..7d7fde3d2a 100644 --- a/packages/jsapi-utils/src/TableUtils.ts +++ b/packages/jsapi-utils/src/TableUtils.ts @@ -1859,6 +1859,22 @@ export class TableUtils { return dh.FilterValue.ofNumber(rawValue as number); } + /** + * Creates an Eq filter for the given column and raw value + * @param column The column to set the filter on + * @param rawValue The nullable value to filter on + * @returns The filter for this column/value combination + */ + makeNullableEqFilter( + column: DhType.Column, + rawValue: unknown + ): DhType.FilterCondition { + if (rawValue == null) { + return column.filter().isNull(); + } + return column.filter().eq(this.makeFilterRawValue(column.type, rawValue)); + } + /** * Converts a string value to a value appropriate for the column * @param columnType The column type to make the value for