Using Shopify Polaris components with Gadget
This page contains some code samples that can be used to integrate Shopify Polaris components with Gadget.
Polaris Data Table
Use the following template to take data from a Gadget app and place it in a Polaris Data Table. Copy-pasting it into the frontend/ShopPage.jsx
file that is generated when a new Gadget app is connected to Shopify will render a table containing the data from the shopifyShop
model.
frontend/ShopPage.jsxReact1import { useFindMany } from "@gadgetinc/react";2import { AlphaCard, DataTable, Page, Pagination, Text, VerticalStack } from "@shopify/polaris";3import { api } from "./api";4import { useState, useCallback, useEffect } from "react";56// helper functions used to capitalize headings7function toCapitalizedWords(name) {8 var words = name.match(/[A-Za-z][a-z]*/g) || [];9 return words.map(capitalize).join(" ");10}1112function capitalize(word) {13 return word.charAt(0).toUpperCase() + word.substring(1);14}1516const ShopPage = () => {17 /**18 * CHANGE NUM_RECORDS TO MODIFY THE NUMBER OF RECORDS FETCHED AT A SINGLE TIME19 */20 const NUM_RECORDS = 10;2122 // React state to manage table data and settings, as well as pagination cursor23 const [cursor, setCursor] = useState({ first: NUM_RECORDS });24 const [rows, setRows] = useState([]);25 const [headings, setHeadings] = useState([]);26 const [columnContentTypes, setColumnContentTypes] = useState([]);2728 /**29 * CHANGE shopifyShop TO YOUR GADGET MODEL'S API IDENTIFIER TO FETCH DIFFERENT DATA30 */31 const [{ data, fetching, error }] = useFindMany(api.shopifyShop, {32 ...cursor,33 });3435 // set all data to state values36 useEffect(() => {37 if (data) {38 // get JSON format for returned data39 const jsonData = data.toJSON();4041 // loop through returned data to stringify objects42 // this may not be necessary, depending on the shape of your displayed data model (see commented out line below)43 // this can also be optimized if you know what columns need to be transformed (use column indexes instead of looping with Object.values(d))44 setRows(45 jsonData?.map((d) =>46 Object.values(d).map((value) => {47 // make sure objects are able to be rendered in table48 if (value instanceof Object) {49 /**50 * YOU MAY NEED TO CHANGE THIS IF YOU NEED SPECIFIC TRANSFORMS FOR OBJECTS51 */52 return JSON.stringify(value);53 }54 return value;55 })56 )57 );5859 // an alternative way to set rows if data transforms are not required60 // setRows(jsonData.map(d => Object.values(d)))6162 // create readable headings and get column types63 if (headings.length === 0 || headings.length !== Object.keys(jsonData[0]).length) {64 const row = jsonData[0];65 let headings = Object.keys(row);66 setHeadings(headings.map((key) => toCapitalizedWords(key)));6768 let values = Object.values(row);69 setColumnContentTypes(values.map((value) => (isNaN(value) ? "text" : "number")));70 }71 }72 }, [data]);7374 // handle pagination75 const pageForward = useCallback(() => {76 setCursor({ after: data.endCursor, first: NUM_RECORDS });77 }, [data]);78 const pageBackward = useCallback(() => {79 setCursor({ before: data.startCursor, last: NUM_RECORDS });80 }, [data]);8182 // display any request errors83 if (error) {84 return (85 <Page title="Error">86 <Text variant="bodyMd" as="p">87 Error: {error.toString()}88 </Text>89 </Page>90 );91 }9293 // draw the page and data table94 return (95 <Page title="Gadget + Polaris data table" fullWidth>96 <AlphaCard>97 <VerticalStack gap="5">98 <Text>99 For DataTable component details, see the{" "}100 <a href="https://polaris.shopify.com/components/tables/data-table" target="_blank">101 Polaris docs102 </a>103 .104 </Text>105 <Pagination106 label="Use to paginate"107 hasPrevious={data?.hasPreviousPage}108 onPrevious={pageBackward}109 hasNext={data?.hasNextPage}110 onNext={pageForward}111 />112 {data && (113 <DataTable columnContentTypes={columnContentTypes} headings={headings} rows={rows} hasZebraStripingOnData stickyHeader />114 )}115 </VerticalStack>116 </AlphaCard>117 </Page>118 );119};120121export default ShopPage;
There are a couple of things that can be changed to customize the table:
- Displayed data model - change
api.shopifyShop
inside theuseFindMany
hook to the API identifier of the model displayed - Included columns - by default, all columns are displayed. This can be changed by adding a
select
condition to theuseFindMany
hook
frontend/ShopPage.jsxReact1// for example: only include the shop id and name in the table2const [{ data, fetching, error }] = useFindMany(api.shopifyShop, {3 ...cursor,4 select: {5 id: true,6 name: true,7 },8});
NUM_RECORDS
- the number of records to fetch and display at a time. Pagination is built-in, and this is the way to set the page size