Griddle

Customization

Customization is the most compelling use-case for Griddle. There are a number of datagrid libraries and many of them are quite good! With Griddle, we wanted to create a datagrid that is useful out of the box but doesn't get in your way if you need something different. To that end, just about everything in Griddle is able to be composed / overriden through customization options in the API.

(Side note: While similar to customization, styling is in its own section)

Custom columns

In Griddle we can custom columns or column headings through the ColumnDefinitions object. Lets say we want to add a custom column where we make the text blue for name but make the heading text red on another column -- We would achieve this with CustomColumn / CustomColumnHeadings.

  const CustomColumn = ({value}) => <span style={{ color: '#0000AA' }}>{value}</span>;
  const CustomHeading = ({title}) => <span style={{ color: '#AA0000' }}>{title}</span>;

  <Griddle data={fakeData}>
    <RowDefinition>
      <ColumnDefinition id="name" customComponent={CustomColumn} />
      <ColumnDefinition id="state" customHeadingComponent={CustomHeading} />
      <ColumnDefinition id="company" />
    </RowDefinition>
  </Griddle>
namestatecompany
Mayer LeonardHawaiiOvolo
Koch BeckerNew JerseyEventage
Lowery HopkinsArizonaComtext
Walters MaysIllinoisCorporana
Shaw LoweWyomingIsologica
Ola FernandezDelawarePawnagra
Park CarrKentuckyCosmetex
Laverne JohnsonNew MexicoHousedown
Lizzie NelsonMontanaEverest
Clarke ClemonsRhode IslandApexia

Component Customization

Griddle exists as a series of container and view components. Container components are specifically responsible for getting data from griddle's store, where as view components are responsible for displaying data (see architecture for more on this). If we wanted to change the Filter component to be a dropdown to look for only a couple of specified option we could do so through the customizing Griddle's components.

Griddle receives a components prop where any component that is passed in with a matching name will override the default in Griddle.

class Filter extends Component {
  onChange(e) {
    this.props.onChange(e.target.value);
  }

  render() {
    return (
      <select onChange={this.onChange}>
        <option value="">All</option>
        <option value="Michigan">Michigan</option>
        <option value="Ohio">Ohio</option>
        <option value="Indiana">Indiana</option>
      </select>
    );
  }
}
...
<Griddle
  ...
  components={{
    Filter
  }}
/>
idnamecitystatecountrycompanyfavoriteNumber
0Mayer LeonardKapowsinHawaiiUnited KingdomOvolo7
1Koch BeckerJohnsonburgNew JerseyMadagascarEventage2
2Lowery HopkinsBlancoArizonaUkraineComtext3
3Walters MaysGlendaleIllinoisNew ZealandCorporana6
4Shaw LoweCoultervillleWyomingEcuadorIsologica2

This type of component overriding works with any of the components.

Container customization

Griddle containers can also be customized. Containers are higher order components that wrap a given 'OriginalComponent'. If we wanted to change how a view component received its data, we would do so by overriding the container component -- in fact, this is exactly how the plugin for managing data works. Lets take a look at one of the core containers versus one in the plugin.

Core Component

import {
  hasNextSelector,
  classNamesForComponentSelector,
  stylesForComponentSelector
} from '../selectors/dataSelectors';

const enhance = OriginalComponent => compose(
  getContext({
    events: PropTypes.object
  }),
  connect((state, props) => ({
    hasNext: hasNextSelector(state, props),
    className: classNamesForComponentSelector(state, 'NextButton'),
    style: stylesForComponentSelector(state, 'NextButton'),
  })),
  mapProps(({ events: { onNext }, ...props }) => ({
    onClick: onNext,
    text: 'Next'
    ...props }))
)((props) => <OriginalComponent {...props} text= "Next" />)

Local Component

  import {
    hasNextSelector,
    classNamesForComponentSelector,
    stylesForComponentSelector
  } from '../selectors/localSelectors';

  import { getNext } from '../../../actions';

  const enhance = OriginalComponent => connect(state => ({
    hasNext: hasNextSelector(state),
    className: classNamesForComponentSelector(state, 'NextButton'),
    style: stylesForComponentSelector(state, 'NextButton'),
  }),
    {
      getNext
    }
  )(props => <OriginalComponent {...props} onClick={props.getNext} text="Next" />);

The main difference between the two components is where they are getting their data. The core container is using dataSelectors where the localContainer is getting data from localSelectors -- this ability to change out the container component while leaving the view as-is has been a powerful abstraction for customizing Griddle.

Layout

Using the component overriding discussed above, we can override Griddle's layout component to change how Griddle renders its internal components.

The layout component receives Table, Pagination, Filter, SettingsWrapper as props.

By default, this renders as follows:

<div>
  <Filter />
  <SettingsWrapper />
  <Table />
  <Pagination />
</div>

If we wanted to change the pagination to be above the table (and drop table settings), we could achieve that by making our own Layout component:

const NewLayout = ({ Table, Pagination, Filter, SettingsWrapper }) => (
  <div>
    <Filter />
    <Pagination />
    <Table />
  </div>
);
...
<Griddle
  ...
  components={{
    Layout: NewLayout
  }}
/>
idnamecitystatecountrycompanyfavoriteNumber
0Mayer LeonardKapowsinHawaiiUnited KingdomOvolo7
1Koch BeckerJohnsonburgNew JerseyMadagascarEventage2
2Lowery HopkinsBlancoArizonaUkraineComtext3
3Walters MaysGlendaleIllinoisNew ZealandCorporana6
4Shaw LoweCoultervillleWyomingEcuadorIsologica2
5Ola FernandezDeltavilleDelawareVirgin Islands (US)Pawnagra7
6Park CarrWeldaKentuckySri LankaCosmetex7
7Laverne JohnsonRosburgNew MexicoCroatiaHousedown9
8Lizzie NelsonChumucklaMontanaTurks &amp; CaicosEverest2
9Clarke ClemonsInkermanRhode IslandCambodiaApexia3

While you can customize just about anything in Griddle using these mechanisms, a more powerful option exists for creating reusable customizations through plugins. Learn more about plugins

Topics:

Customization

Customization is the most compelling use-case for Griddle. There are a number of datagrid libraries and many of them are quite good! With Griddle, we wanted to create a datagrid that is useful out of the box but doesn't get in your way if you need something different. To that end, just about everything in Griddle is able to be composed / overriden through customization options in the API.

(Side note: While similar to customization, styling is in its own section)

Custom columns

In Griddle we can custom columns or column headings through the ColumnDefinitions object. Lets say we want to add a custom column where we make the text blue for name but make the heading text red on another column -- We would achieve this with CustomColumn / CustomColumnHeadings.

  const CustomColumn = ({value}) => <span style={{ color: '#0000AA' }}>{value}</span>;
  const CustomHeading = ({title}) => <span style={{ color: '#AA0000' }}>{title}</span>;

  <Griddle data={fakeData}>
    <RowDefinition>
      <ColumnDefinition id="name" customComponent={CustomColumn} />
      <ColumnDefinition id="state" customHeadingComponent={CustomHeading} />
      <ColumnDefinition id="company" />
    </RowDefinition>
  </Griddle>
namestatecompany
Mayer LeonardHawaiiOvolo
Koch BeckerNew JerseyEventage
Lowery HopkinsArizonaComtext
Walters MaysIllinoisCorporana
Shaw LoweWyomingIsologica
Ola FernandezDelawarePawnagra
Park CarrKentuckyCosmetex
Laverne JohnsonNew MexicoHousedown
Lizzie NelsonMontanaEverest
Clarke ClemonsRhode IslandApexia

Component Customization

Griddle exists as a series of container and view components. Container components are specifically responsible for getting data from griddle's store, where as view components are responsible for displaying data (see architecture for more on this). If we wanted to change the Filter component to be a dropdown to look for only a couple of specified option we could do so through the customizing Griddle's components.

Griddle receives a components prop where any component that is passed in with a matching name will override the default in Griddle.

class Filter extends Component {
  onChange(e) {
    this.props.onChange(e.target.value);
  }

  render() {
    return (
      <select onChange={this.onChange}>
        <option value="">All</option>
        <option value="Michigan">Michigan</option>
        <option value="Ohio">Ohio</option>
        <option value="Indiana">Indiana</option>
      </select>
    );
  }
}
...
<Griddle
  ...
  components={{
    Filter
  }}
/>
idnamecitystatecountrycompanyfavoriteNumber
0Mayer LeonardKapowsinHawaiiUnited KingdomOvolo7
1Koch BeckerJohnsonburgNew JerseyMadagascarEventage2
2Lowery HopkinsBlancoArizonaUkraineComtext3
3Walters MaysGlendaleIllinoisNew ZealandCorporana6
4Shaw LoweCoultervillleWyomingEcuadorIsologica2

This type of component overriding works with any of the components.

Container customization

Griddle containers can also be customized. Containers are higher order components that wrap a given 'OriginalComponent'. If we wanted to change how a view component received its data, we would do so by overriding the container component -- in fact, this is exactly how the plugin for managing data works. Lets take a look at one of the core containers versus one in the plugin.

Core Component

import {
  hasNextSelector,
  classNamesForComponentSelector,
  stylesForComponentSelector
} from '../selectors/dataSelectors';

const enhance = OriginalComponent => compose(
  getContext({
    events: PropTypes.object
  }),
  connect((state, props) => ({
    hasNext: hasNextSelector(state, props),
    className: classNamesForComponentSelector(state, 'NextButton'),
    style: stylesForComponentSelector(state, 'NextButton'),
  })),
  mapProps(({ events: { onNext }, ...props }) => ({
    onClick: onNext,
    text: 'Next'
    ...props }))
)((props) => <OriginalComponent {...props} text= "Next" />)

Local Component

  import {
    hasNextSelector,
    classNamesForComponentSelector,
    stylesForComponentSelector
  } from '../selectors/localSelectors';

  import { getNext } from '../../../actions';

  const enhance = OriginalComponent => connect(state => ({
    hasNext: hasNextSelector(state),
    className: classNamesForComponentSelector(state, 'NextButton'),
    style: stylesForComponentSelector(state, 'NextButton'),
  }),
    {
      getNext
    }
  )(props => <OriginalComponent {...props} onClick={props.getNext} text="Next" />);

The main difference between the two components is where they are getting their data. The core container is using dataSelectors where the localContainer is getting data from localSelectors -- this ability to change out the container component while leaving the view as-is has been a powerful abstraction for customizing Griddle.

Layout

Using the component overriding discussed above, we can override Griddle's layout component to change how Griddle renders its internal components.

The layout component receives Table, Pagination, Filter, SettingsWrapper as props.

By default, this renders as follows:

<div>
  <Filter />
  <SettingsWrapper />
  <Table />
  <Pagination />
</div>

If we wanted to change the pagination to be above the table (and drop table settings), we could achieve that by making our own Layout component:

const NewLayout = ({ Table, Pagination, Filter, SettingsWrapper }) => (
  <div>
    <Filter />
    <Pagination />
    <Table />
  </div>
);
...
<Griddle
  ...
  components={{
    Layout: NewLayout
  }}
/>
idnamecitystatecountrycompanyfavoriteNumber
0Mayer LeonardKapowsinHawaiiUnited KingdomOvolo7
1Koch BeckerJohnsonburgNew JerseyMadagascarEventage2
2Lowery HopkinsBlancoArizonaUkraineComtext3
3Walters MaysGlendaleIllinoisNew ZealandCorporana6
4Shaw LoweCoultervillleWyomingEcuadorIsologica2
5Ola FernandezDeltavilleDelawareVirgin Islands (US)Pawnagra7
6Park CarrWeldaKentuckySri LankaCosmetex7
7Laverne JohnsonRosburgNew MexicoCroatiaHousedown9
8Lizzie NelsonChumucklaMontanaTurks &amp; CaicosEverest2
9Clarke ClemonsInkermanRhode IslandCambodiaApexia3

While you can customize just about anything in Griddle using these mechanisms, a more powerful option exists for creating reusable customizations through plugins. Learn more about plugins