Custom widget: How to get values of columns?

Hello Grist Team,

I’m studying the custom widgets with the Minimal example. I can make the widget showing JSON of selected record as the instructions. Now I want to extract values of single columns, e.g. Name to display in the HTML. Please help me find a way to do.
Thanks.

Hi @huyluong82, welcome! Glad you were able to get the minimal custom widget example working. If you have code that looks like this:

grist.onRecord(function(record) {
   document.getElementById('readout').innerHTML = JSON.stringify(record, null, 2);
});

then record contains everything you need. If the table contains a column called Name, you can access it as record.Name:

grist.onRecord(function(record) {
   document.getElementById('readout').innerHTML = record.Name;
});

You can get a list of the columns available using Object.keys(record).

1 Like

Hi Paul,
Thank you for the swift reply. Yes, it works now!!! :hugs:

1 Like

Hi @paul-grist

My custom widget is now working great, yet the exported documents consist of many pages with different formats, therefore I have to look for a better approach utilizing components of ReactJS.

Currently, I can’t fetch data from grist-plugin-api as the below code.

<!DOCTYPE html>
<html>
  <head>
    <title>reactjs</title>
    <script src="https://docs.getgrist.com/grist-plugin-api.js"></script>
    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script type="text/babel">
      function App() {
        grist.ready();
        const data = async() => {
          grist.onRecord((record) => record);
        };
        return (         
            <p>Hello {data.Name}</p>
        );
      }
      ReactDOM.render(<App />, document.getElementById("root"));
    </script>
  </body>
</html>

Hi @huyluong82! The call to grist.onRecord is setting a callback to a function that will accept records, it doesn’t itself return a record. I don’t know React, but I was able to tweak that code to work as follows:

let gristSetData;  // this will be a method to ingest data from Grist to React
grist.ready();
grist.onRecord((record) => {
  if (gristSetData) { gristSetData(record); }
});
function App() {
  const [data, setData] = React.useState({});
  gristSetData = setData;
  return (         
     <p>Hello {data.Name}</p>
  );
}
ReactDOM.render(<App />, document.getElementById("root"));

Not sure if this is sane React code, apologies if not. The main trick will be to have the onRecord callback provide data via whatever state management mechanism makes React most happy.

1 Like

@paul-grist I think your code is ok. But React has some great tools to handle intializing states that makes code a little nicer.
Please allow me to share how I would do it in React:

function App() {
  const [data, setData] = React.useState({});
  React.useEffect(() => { 
    grist.onRecord((record) => setData(record));
    grist.ready();
  }, []);
  return (          
     <p>Hello {data.Name}</p>
  );
}
ReactDOM.render(<App />, document.getElementById("root"));
2 Likes

Hi @paul-grist , I’m also new to React, thus there are many things to learn. I really appreciate your support. I’m considering move the database of my small business to Grist, and so far so good.

Hi @cpind , thank you for your help. It works beautifully.