Skip to content

Commit

Permalink
🐛 - fix: fix minor bugs in DataGrid component
Browse files Browse the repository at this point in the history
  • Loading branch information
svenvandescheur committed Oct 18, 2024
1 parent 4e82ee3 commit 8cab271
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 16 deletions.
9 changes: 9 additions & 0 deletions src/components/data/datagrid/datagrid.scss
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,18 @@

.mykn-form-control {
gap: 0;
width: 100%;
}

.mykn-stackctx,
.mykn-input,
.mykn-select {
width: 100%;
}

.mykn-checkbox {
align-self: flex-end;
}
}

&__thead &__cell {
Expand Down Expand Up @@ -126,6 +131,10 @@
border: none;
}

&__cell--editable#{&}__cell--type-boolean .mykn-form-control {
align-items: flex-end;
}

&__cell--editable:not(#{&}__cell--type-boolean) .mykn-form-control {
height: 100%;
left: var(--spacing-h);
Expand Down
45 changes: 32 additions & 13 deletions src/components/data/datagrid/datagridfilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,25 @@ export const DataGridFilter: React.FC = () => {
onFilterTimeoutRef.current = setTimeout(handler, 300);
}, [filterState]);

/**
* Gets called when a filter is changed.
* @param e
*/
const handleFilter: React.EventHandler<
React.SyntheticEvent<HTMLInputElement>
> = (e) => {
const input = e.target as HTMLInputElement;
if (input.type !== "checkbox") {
e.preventDefault();
}

const data = serializeForm(input.form as HTMLFormElement) as AttributeData;
const _data = filterTransform ? filterTransform(data) : data;

// Reset page on filter (length of dataset may change).
setFilterState(_data);
};

return (
<tr className="mykn-datagrid__row mykn-datagrid__row--filter" role="row">
{selectable && (
Expand Down Expand Up @@ -79,6 +98,7 @@ export const DataGridFilter: React.FC = () => {
aria-label={_labelFilterField}
icon={
!field.options &&
field.type !== "boolean" &&
field.type !== "daterange" && <Outline.MagnifyingGlassIcon />
}
form={`${dataGridId}-filter-form`}
Expand All @@ -87,20 +107,19 @@ export const DataGridFilter: React.FC = () => {
min={!field.options && field.type === "number" ? 0 : undefined}
pad={field.type === "daterange" ? "v" : undefined}
placeholder={placeholder}
type={field.type}
type={field.type === "boolean" ? "checkbox" : field.type}
value={field.filterValue}
onChange={(
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>,
) => {
e.preventDefault();
const data = serializeForm(
e.target.form as HTMLFormElement,
) as AttributeData;
const _data = filterTransform ? filterTransform(data) : data;

// Reset page on filter (length of dataset may change).
setFilterState(_data);
}}
onChange={
field.type !== "boolean"
? (e: React.ChangeEvent<HTMLInputElement>) =>
handleFilter(e)
: undefined
}
onClick={
field.type === "boolean"
? (e: React.MouseEvent<HTMLInputElement>) => handleFilter(e)
: undefined
}
/>
)}
</th>
Expand Down
27 changes: 24 additions & 3 deletions src/lib/form/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,29 @@ export const serializeForm = (
const typeSerializedFormData = (
form: HTMLFormElement,
data: SerializedFormData,
) =>
Object.fromEntries(
Object.entries(data).map(([key, value]) => {
) => {
// Work around for edge case where checkbox is not present in `data` when unchecked.
// This builds an object with all form fields keys (including unchecked checkbox)
// set to `undefined`, we can merge this with `data` later on to get a complete
// data collection.
//
// TODO: We can possibly leverage `form.element` to optimize serialisation.
const baseData = Object.fromEntries(
Object.values(form.elements)
.map((element) => {
return element instanceof RadioNodeList
? (element[0] as Element | undefined)?.getAttribute("name")
: element.getAttribute("name");
})
.filter((name): name is string => Boolean(name))
.map((name): [string, undefined] => [name, undefined]),
);

// Merge `data` and baseData into `completeData`.
const completeData: SerializedFormData = Object.assign(baseData, data);

return Object.fromEntries(
Object.entries(completeData).map(([key, value]) => {
if (Array.isArray(value)) {
const values = value.map((v, index) => {
const constructor = getInputTypeConstructor(form, key, value, index);
Expand All @@ -81,6 +101,7 @@ const typeSerializedFormData = (
return [key, _value];
}),
);
};

/**
* Returns a Function providing a constructor for a typed value (e.g. input[type="number"] -> Number) at the `index`
Expand Down

0 comments on commit 8cab271

Please sign in to comment.