@adaptabletools/adaptable
Version:
Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
201 lines (200 loc) • 8.11 kB
JavaScript
import { ApiBase } from '../Implementation/ApiBase';
export class RowFormInternalApi extends ApiBase {
// Row Form Methods
buildRowEditForm(rowNode) {
return this.buildRowForm('rowEdited', rowNode);
}
buildRowCreateForm(clonedRowNode) {
return this.buildRowForm('rowCreated', clonedRowNode);
}
buildRowForm(type, rowNode) {
const formFields = this.buildRowFormFields(type, rowNode);
const formButtons = this.buidRowFormButtons(type, rowNode, formFields);
const formTitle = this.getFormTitle(type, rowNode);
const formDescription = this.getFormDescription(type, rowNode);
const rowForm = {
title: formTitle,
description: formDescription,
fields: formFields,
buttons: formButtons,
};
return rowForm;
}
getFormTitle(type, rowNode) {
const rowFormOptions = this.getRowFormOptions();
if (rowFormOptions.rowFormTitle == undefined) {
return type === 'rowCreated' ? 'Create New Row' : 'Edit Row';
}
return typeof rowFormOptions.rowFormTitle === 'function'
? rowFormOptions.rowFormTitle(this.buildFormParamContext(type, rowNode))
: rowFormOptions.rowFormTitle;
}
buildFormParamContext(type, rowNode) {
return {
rowNode,
...this.getAdaptableInternalApi().buildBaseContext(),
type: type,
};
}
getFormDescription(type, rowNode) {
const rowFormOptions = this.getRowFormOptions();
return typeof rowFormOptions.rowFormDescription === 'function'
? rowFormOptions.rowFormDescription(this.buildFormParamContext(type, rowNode))
: rowFormOptions.rowFormDescription;
}
buidRowFormButtons(type, rowNode, formFields) {
// 1. check if there are custom user provided buttons
if (Array.isArray(this.getRowFormOptions().rowFormButtons)) {
return this.getRowFormOptions().rowFormButtons;
}
// 2. else return the standard ones
const cancelButton = {
label: 'Cancel',
buttonStyle: {
variant: 'raised',
tone: 'neutral',
},
};
const saveButton = {
label: 'Save',
buttonStyle: {
variant: 'raised',
tone: 'success',
},
onClick: (button, context) => {
// textOutput should not be saved, their values are set to display values
// we need to filter out the textOutput fields and add the primaryKey
const eventInfo = type === 'rowCreated'
? {
type: 'rowCreated',
formData: this.prepareCreateData(formFields, context),
...this.getAdaptableInternalApi().buildBaseContext(),
clonedRowNode: rowNode,
}
: {
type: 'rowEdited',
formData: this.prepareEditData(formFields, context),
rowNode: rowNode,
...this.getAdaptableInternalApi().buildBaseContext(),
};
this.getEventApi().internalApi.fireRowFormSubmittedEvent(eventInfo);
this.getRowFormOptions()?.onRowFormSubmit?.(eventInfo);
},
};
return [cancelButton, saveButton];
}
prepareCreateData(formFields, context) {
// when creating we just omit values that are not set
const dataToSave = { ...context.formData };
for (const formField of formFields) {
if (dataToSave[formField.name] === '') {
delete dataToSave[formField.name];
}
}
return dataToSave;
}
prepareEditData(formFields, context) {
const dataToSave = { ...context.formData };
for (const formField of formFields) {
if (formField.fieldType === 'textOutput') {
delete dataToSave[formField.name];
}
}
const pkValue = this.getGridApi().getPrimaryKeyValueForRowNode(context.rowNode);
dataToSave[this.getOptions().primaryKey] = pkValue;
return dataToSave;
}
buildRowFormFields(rowFormType, rowNode) {
const relevantColumns = this.getColumnApi()
.getColumns()
.filter((column) => {
// if there is NO rowNode, do NOT display the non-editable fields as they will be empty
return !!rowNode || this.isCellEditable(column, rowNode);
})
.filter((column) => this.showColumnInRowForm(column, rowFormType));
return relevantColumns.map((column) => this.buildRowFormField(rowFormType, column, rowNode));
}
showColumnInRowForm(adaptableColumn, rowFormType) {
const showColumnFn = this.getRowFormOptions()?.includeColumnInRowForm;
if (typeof showColumnFn === 'function') {
return showColumnFn({
...this.getAdaptableInternalApi().buildBaseContext(),
adaptableColumn,
rowFormType: rowFormType,
});
}
return true;
}
isCellEditable(column, rowNode) {
if (!rowNode) {
return !column.readOnly;
}
const gridCell = this.getGridApi().getGridCellFromRowNode(rowNode, column.columnId);
return this.getGridApi().isCellEditable(gridCell);
}
buildRowFormField(type, column, rowNode) {
const isCellEditable = this.isCellEditable(column, rowNode);
const fieldValueOptions = this.getFieldValueOptions(column, rowNode);
const fieldType = isCellEditable
? !!fieldValueOptions?.length
? 'select'
: this.getFieldTypeFromColumnType(column)
: 'textOutput';
const defaultValue = rowNode
? isCellEditable
? this.getGridApi().getRawValueFromRowNode(rowNode, column.columnId)
: this.getGridApi().getDisplayValueFromRowNode(rowNode, column.columnId)
: null;
return {
label: this.getRowFormFieldLabel(type, column, rowNode),
name: column.columnId,
defaultValue,
fieldType,
options: fieldValueOptions,
};
}
getRowFormFieldLabel(type, column, rowNode) {
const customFieldLabel = typeof this.getRowFormOptions().rowFormFieldLabel === 'function'
? this.getRowFormOptions().rowFormFieldLabel(this.buildFormFieldLabelContext(type, column, rowNode))
: undefined;
return customFieldLabel ?? column.friendlyName;
}
buildFormFieldLabelContext(type, column, rowNode) {
return {
rowNode,
column,
...this.getAdaptableInternalApi().buildBaseContext(),
type: type,
};
}
getFieldTypeFromColumnType(column) {
switch (column.dataType) {
case 'boolean':
return 'checkbox';
case 'date':
return 'date';
case 'number':
return 'number';
default:
// everything else is a plain text input
return 'text';
}
}
getFieldValueOptions(column, rowNode) {
const shouldShowSelectCellEditor = this.getUserInterfaceApi().internalApi.shouldShowSelectCellEditor(column);
if (!shouldShowSelectCellEditor) {
return;
}
const returnValues = this.getGridApi().internalApi.getDistinctDisplayValuesForColumnOld(column.columnId);
// FIXME add support for asynchronous custom select cell editor values
// it involves refactoring the AdaptableForm & adaptableFormComponent
// await this.getSelectCellEditorValuesForColumn(
// column,
// gridCell
// );
return returnValues?.map((value) => ({
value,
label: value,
}));
}
}