CrowdStrike / ember-headless-table

https://ember-headless-table.pages.dev
MIT License
23 stars 7 forks source link

Since the return value of `value` must be a ContentValue, how do I pass custom content to a custom Cell? #105

Closed NullVoxPopuli closed 1 year ago

NullVoxPopuli commented 1 year ago

in a column config:

const MyCell = <template>
  do something with `@row` or `@data`
</template>

// ...
{
  Cell: MyCell,
  key: 'foo'
}

the more a person would like to make MyCell generic, the more likely it is that they'll want to massage the inputs to that component. Presently, a person would want to have some cached array.map, such as what you could do with: https://ember-resources.pages.dev/funcs/util_map.map

// pass this to the table instead of sourceData
mappedData = map(this, {
  data: () => this.sourceData,
  map: (datum) => {
    return new WrapperObject(datum); // where wrappedObject has @tracked / @cached stuff, etc
  }
});

this is a lot of ceremony (if value is not a type from ContentValue (a renderable type)).

I propose a new config option to be added to help with discovery around passing config-driven functions to evaluate to pass to the custom Cell. maybe, the above could be:

{
  Cell: MyCell,
  cellValue: ({ row, data, column }) => ArgsFor<typeof MyCell> // could be any complex shape, such as object or array
  key: 'foo',
}

and a sample implementation could include something like:

{{#if config.cellValue}}
  <config.Cell @value={{ (config.cellValue (hash row=row data=data column=column)) }} />
{{/if}}
NullVoxPopuli commented 1 year ago

I think the path forward here will probably be to use the options argument for custom cells and pass @options in your DOM.

that would look like this:

const MyCell = <template>
  do something with `@row` or `@data`
</template>

headlessTable({
  // ...
  columns: () => 
  // ...
  {
    Cell: MyCell,
    key: 'foo'
    options: (context) => {
      return {  
        your: 'data here',
      },
    },
  }

This already exists, and provides a good semantic escape from built-in rendering intent.

Another option that's possible is to make very custom components for each column / property configuration:

const FooCell = <template>
  do something with `@row` or `@data`
</template>

const BarCell = <template>
  Access your data is a special way that is relevant to the "bar" property
  <FooCell ... />
</template>

headlessTable({
  // ...
  columns: () => 
  // ...
  {
    Cell: FooCell,
    key: 'foo'
  },
  {
    Cell: BarCell,
    key: 'bar'
  }