RelationshipInHtmlTable
The RelationshipInHtmlTable
component renders the contents of the two Tables
linked by a Relationship
as an HTML <table> element, and registers a listener so that any changes to that result will cause a re-render.
RelationshipInHtmlTable(props: RelationshipInHtmlTableProps & HtmlTableProps): ComponentReturnType
Type | Description | |
---|---|---|
props | RelationshipInHtmlTableProps & HtmlTableProps | The props for this component. |
returns | ComponentReturnType | A rendering of the two |
See the <RelationshipInHtmlTable /> demo for this component in action.
The component's props identify which Relationship
to render based on Relationship
Id
and Relationships
object (which is either the default context Relationships
object, a named context Relationships
object, or an explicit reference).
This component renders the two Table
objects by iterating over their related Row
objects. By default the Cells are in turn rendered with the CellView
component, but you can override this behavior by providing a component
for each Cell
in the customCells
prop. You can pass additional props to that custom component with the getComponentProps
callback. See the CustomCell
type for more details.
Note the use of dotted 'tableId.cellId' string pairs when specifying custom rendering for the cells in this table, since Cells from both the relationship's 'local' and 'remote' Table
objects can be rendered and need to be distinguished.
This component uses the useRowIds and useRemoteRowId
hooks under the covers, which means that any changes to the structure of either Table
resulting in a change to the relationship will cause a re-render.
You can use the headerRow
and idColumn
props to control whether labels and Ids
appear in a <th> element at the top of the table, and the start of each row.
Examples
This example creates a Provider context into which a default Relationships
object is provided. The RelationshipInHtmlTable
component within it then renders the two Tables
linked by a relationship in a <table> element with a CSS class. Note the dotted pairs that are used as column headings.
import {createRelationships, createStore} from 'tinybase';
import {Provider} from 'tinybase/ui-react';
import React from 'react';
import {RelationshipInHtmlTable} from 'tinybase/ui-react-dom';
import {createRoot} from 'react-dom/client';
const App = ({relationships}) => (
<Provider relationships={relationships}>
<Pane />
</Provider>
);
const Pane = () => (
<RelationshipInHtmlTable
relationshipId="petSpecies"
className="relationship"
/>
);
const relationships = createRelationships(
createStore()
.setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'dog'}})
.setTable('species', {wolf: {price: 10}, dog: {price: 5}}),
).setRelationshipDefinition('petSpecies', 'pets', 'species', 'species');
const app = document.createElement('div');
const root = createRoot(app);
root.render(<App relationships={relationships} />);
console.log(app.innerHTML);
// ->
`
<table class="relationship">
<thead>
<tr>
<th>pets.Id</th>
<th>species.Id</th>
<th>pets.species</th>
<th>species.price</th>
</tr>
</thead>
<tbody>
<tr>
<th>fido</th>
<th>dog</th>
<td>dog</td>
<td>5</td>
</tr>
<tr>
<th>cujo</th>
<th>dog</th>
<td>dog</td>
<td>5</td>
</tr>
</tbody>
</table>
`;
This example creates a Provider context into which a default Relationships
object is provided. The RelationshipInHtmlTable
component within it then renders the two Tables
linked by a relationship with a custom component and a custom props callback for the species
Cell
. The header row at the top of the table and the Id
column at the start of each row is removed.
import {CellView, Provider} from 'tinybase/ui-react';
import {createRelationships, createStore} from 'tinybase';
import React from 'react';
import {RelationshipInHtmlTable} from 'tinybase/ui-react-dom';
import {createRoot} from 'react-dom/client';
const App = ({relationships}) => (
<Provider relationships={relationships}>
<Pane />
</Provider>
);
const Pane = () => (
<RelationshipInHtmlTable
relationshipId="petSpecies"
customCells={customCells}
idColumn={false}
headerRow={false}
/>
);
const FormattedCellView = ({tableId, rowId, cellId, store, bold}) => (
<>
{bold ? <b>{rowId}</b> : rowId}:
<CellView
tableId={tableId}
rowId={rowId}
cellId={cellId}
store={store}
/>
</>
);
const customCells = {
'species.price': {
component: FormattedCellView,
getComponentProps: (rowId) => ({bold: rowId == 'dog'}),
},
};
const relationships = createRelationships(
createStore()
.setTable('pets', {fido: {species: 'dog'}, cujo: {species: 'wolf'}})
.setTable('species', {wolf: {price: 10}, dog: {price: 5}}),
).setRelationshipDefinition('petSpecies', 'pets', 'species', 'species');
const app = document.createElement('div');
const root = createRoot(app);
root.render(<App relationships={relationships} />);
console.log(app.innerHTML);
// ->
`
<table>
<tbody>
<tr>
<td><b>dog</b>:5</td>
</tr>
<tr>
<td>wolf:10</td>
</tr>
</tbody>
</table>
`;
Since
v4.1.0