Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for binding selectToggle to form states #894

Open
stephenh opened this issue Jul 5, 2023 · 0 comments
Open

Support for binding selectToggle to form states #894

stephenh opened this issue Jul 5, 2023 · 0 comments

Comments

@stephenh
Copy link
Contributor

stephenh commented Jul 5, 2023

Currently, GridTable internally controls "which rows are selected", which is nice insofar as it provides out-of-the-box select/select-all/parent/child percolation/etc.

This works particularly well when the table rows are dumb POJOs that don't care about their selected-ness.

However, if there is other business logic that cares about "row selected-ness", having the GridTable solely / internally own selected-ness becomes cumbersome, i.e. when "selected-ness" would be better owned by something like a "form line item" model, b/c then the rest of the business logic could reactive to "form line model is selected" and be agnostic / unaware about the GridTable implementation detail.

For an example of a pain point, see this code in BP:

https://github.com/homebound-team/internal-frontend/blob/main/src/routes/projects/expenses/components/ExpensesTable.tsx#L212

  // Initialize the checkboxes
  let rowInitialized = false;
  useComputed(() => {
    if (tableApi.getSelectedRowIds("projectItem").nonEmpty) {
      rowInitialized = true;
    } else if (!rowInitialized && expense.allocations.nonEmpty) {
      expense.allocations.forEach((a) => tableApi.selectRow(a.projectItem.id, true));
    }
  }, [tableApi]);

  const [selectedExpenseRows, selectedAmountInCents, expenseRemainingInCents] = useComputed(() => {
    const selectedProjectItemIds = tableApi.getSelectedRowIds("projectItem");
    const selectedRows = formState.expenseAllocations.rows.filter((r) =>
      selectedProjectItemIds.includes(r.projectItemId.value!),
    );
    const selectedAmount = selectedRows.sum((pi) => pi.amountInCents.value || 0);

    return [selectedRows, selectedAmount, expense.amountInCents - selectedAmount];
  }, [formState, tableApi, expense]);

That is basically writing glue code between tableApi.getSelectedRows and expense.allocations.

It seems like ideally we could ask GridTable to just do this binding for us, i.e. something like:

function createColumns(...
): GridColumn<ExpenseAllocationRow>[] {
  return [
    selectColumn<ExpenseAllocationRow>({
      w: "32px",
      costCode: (data) => data.checked
    })

Where instead of returning the full SelectToggle, we'd return just a FieldState<boolean>, which SelectToggle would then internally use to:

  1. Use the initial FieldState value to initial GridTables internal selected state
  2. Keep any GridTable selection changes in sync with the FieldState value

We could probably pilot this w/o a selectColumn change by just adding a field= prop to SelectToggle and seeing if it could keep things in sync.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant