Getting Started with Bryntum Grid, React, and RxJS
Bryntum
Posted on August 8, 2023
If you have a web application with a lot of data, you need to find a way to display that information in a succinct and organized way, which is where grids can help. Grids are crucial components of user interfaces that tabulate massive volumes of data and make it easy for users to interact with them. Many individuals choose to use premade packages like Bryntum Grid because they are highly functional and speed up the coding process.
Bryntum Grid is an effective and high-performing table component for web applications. It comes with various capabilities, including the ability to rearrange rows and columns or modify individual cells, search and filter data, and scroll through grid portions. The grid's visual appearance is set using the renderer functions, standard CSS, and themes built with Syntactically Awesome Style Sheets (Sass).
Bryntum Grid uses a variety of techniques, including virtual representation, the use of reusable grid elements, and CSS optimizations, to achieve visualization and navigation efficiency. You can modify virtually any portion of the codebase thanks to a robust API. Moreover, custom data formats are an option in addition to JSON, which is how all data is loaded by default. It offers a wide range of customization choices, which include premade or custom themes.
In this article, you'll learn how to build an application using React, Bryntum Grid, and Reactive Extensions for JavaScript (RxJS). You will utilize React Hooks and RxJS for state management and build an interactive grid with built-in features.
Implementing the Application
Before you begin, you'll need Node.js version 14 or newer installed on your operating system (OS). You'll also need a code editor. Here, Visual Studio (VS) Code will be used due to its extensive functionality.
In addition, you'll need a basic understanding of React. For more information, check out the official React documentation and Bryntum React guide.
All the code for this tutorial can be found in this GitHub repo.
Set Up Bryntum Grid
In this tutorial, you'll learn how to get started if you're using the Create React App script. You can obtain a free trial version of Bryntum by signing up for the private npm registry, which is covered in more detail in the following section.
Access the Private npm Registry
To set up Bryntum Grid, you need to access the private registry through your terminal after logging in. Packages for Bryntum are saved in a personal Bryntum registry. Run the following command in your terminal to find the registry:
npm config set "@bryntum:registry=https://npm.bryntum.com"
Then, using your authentication information, you need to log in.
Please note: The specifics vary depending on whether you are using the licensed version or the trial version.
For the trial version, log in with the following command:
npm login --registry=https://npm.bryntum.com
Then enter your username (ie user..yourdomain.com), password (ie trial), and email (ie user@yourdomain.com).
Please note: In your username, make sure that you change the "@" sign to ".." in your email address.
If you want to continue using Bryntum once the trial time has ended, you'll need to purchase a license from the Bryntum website. After that, you will need to connect back into the Bryntum private registry using your client information.
For a licensed version, log in using the same command mentioned earlier (npm login --registry=https://npm.bryntum.com
), then use your Bryntum Customer Zone email as your username (but be sure to replace "@" with ".."), and enter your Bryntum Customer Zone password.
Create the Application
After logging in, you need to utilize the Create React App to create the React app along with the Bryntum Grid package. In this tutorial, you'll be using JavaScript for the project. In your terminal,
navigate to the directory where you want to set up the project and run the following:
npx create-react-app react-bryntum-grid --template @bryntum/cra-template-javascript-grid
Alternatively, if you would like to use TypeScript, use the following code:
npx create-react-app react-bryntum-grid --template @bryntum/cra-template-typescript-grid
Substitute your preferred application name for react-bryntum-grid
.
Please note: A caret (^) may be inserted by Create React App as the version prefix of dependencies. To properly regulate upgrades, you shouldn't use the caret character as a version prefix. Examine
package.json
and replace the dependencies and devDependencies with the following:
For the trial version:
"dependencies": {
"@bryntum/grid": "npm:@bryntum/grid-trial@5.1.1",
"@bryntum/grid-react": "5.1.1",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-scripts": "4.0.3"
},
"devDependencies": {
"babel-preset-react-app": "npm:@bryntum/babel-preset-react-app@10.0.0",
"cross-env": "~7.0.2",
"sass": "~1.42.0"
}
For the licensed version:
"dependencies": {
"@bryntum/grid": "5.1.1",
"@bryntum/grid-react": "5.1.1",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-scripts": "4.0.3"
},
"devDependencies": {
"babel-preset-react-app": "npm:@bryntum/babel-preset-react-app@10.0.0",
"cross-env": "~7.0.2",
"sass": "~1.42.0"
}
Then from the terminal, navigate to your project folder and install all the necessary dependencies using the following code:
cd react-bryntum-grid
npm install
Then start the app using the following command:
npm start
You should see the following page with a sample grid on it:
Set Up the Grid with Functionalities
Now you need to set up the grid with the necessary columns, data, and configuration. To do this, you need to make use of the sample data and columns from the RxJS store. You can also populate data by making an API call.
In the _App.js_
file, you need to import useState
to handle the data, column, and configuration. Then proceed to import Bryntum Grid for React. To set up the grid, pass the parameters to the BryntumGrid element, which are the data, columns, and features used by the Bryntum component:
import React, { useState } from 'react';
import { BryntumGrid } from '@bryntum/grid-react';
function App() {
const [columns, setColumns] = useState(
[
{ text : 'Country Name', field : 'countryName', flex : 2 },
{ text : 'Code', field : 'code', flex: 1},
{ text : 'Capital', field : 'capital', flex : 1 },
{ text : 'Continent', field : 'continent', flex : 1 },
{ text : 'Currency', field : 'currency', flex : 1 },
{ text : 'Languages', field : 'languages', flex : 1 }
] );
const [data, setData] = useState(
[
{
id : 1,
countryName : 'Brasil',
code : 'BR',
capital : 'Brasília',
continent : 'South America',
currency : 'BRL',
languages : 'Portuguese'
},
{
id : 2,
countryName : 'Bahamas',
code : 'BS',
capital : 'Nassau',
continent : 'North America',
currency : 'BSD',
languages : 'English'
},
{
id : 3,
countryName : 'Botswana',
code : 'BW',
capital : 'Gaborone',
continent : 'Africa',
currency : 'BWP',
languages : 'English, Tswana'
},
{
id : 4,
countryName : 'Colombia',
code : 'CO',
capital : 'Bogotá',
continent : 'South America',
currency : 'COP',
languages : 'Spanish'
},
{
id : 5,
countryName : 'Costa Rica',
code : 'CRC',
capital : 'Brasília',
continent : 'North America',
currency : 'CR',
languages : 'Spanish'
},
{
id : 6,
countryName : 'Ecuador',
code : 'EC',
capital : 'Quito',
continent : 'South America',
currency : 'USD',
languages : 'Spanish'
}] );
const [features, setFeatures] = useState({
cellEdit : true,
regionResize : false,
stripe: true
});
return (
<BryntumGrid data={data} columns={columns} features={features} />
);
}
export default App;
Make sure you import the CSS file that handles the styling of Bryntum Grid in the _App.scss_
file, or your grid will be unstyled:
// import bryntum css theme
@import '~@bryntum/grid/grid.stockholm.css';
Currently, there's a renderer setup feature available for Bryntum Grid columns, which is a function that takes parameters as input and output HTML. For the preparation of aesthetically pleasing cell contents, any type of conditional logic can be applied.
You can format the grid by adding more configs in the feature object, and there are many configurations available.
RxJS for Managing App State
RxJS is a package that allows the creation of asynchronous and event-based applications with the help of observable sequences. In a nutshell, the RxJS package enables you to manage and modify data over time. You can read more about RxJS in the official documentation.
The fundamental features of RxJS are as follows:
- Observable: An observable is a data source that contains data that can be shared between various components of your application. The source can operate synchronously or asynchronously, and it can provide numerous values over time.
- Observer: An observer is an object that consumes the information an observable emits. Until the observable is finished or the observer unsubscribes from the observable, the observer continues to receive data from the observable.
- Subscription: This has to do with an observer requesting information from an observable. An observer will only receive data that they subscribe to.
- Subjects: An RxJS subject can function simultaneously as an observer and an observable. Values can be broadcast to numerous observers, allowing every observer who has subscribed to a subject to get any data that is received.
Install RxJS and Create a Store
To install RxJS and create a store, run the following command in your terminal:
npm install rxjs
The best way to interact between components when using RxJS with React Hooks is to utilize an Observable and a Subject.
To contain your store, you need to build a data store directory and _src/store_
in your src
folder.
Navigate to _src/store_
and create a _DataStore.js_
file that will be used for your grid functions. Then you need to import the Subject class and create a variable from it in _DataStore.js_
:
import { Subject } from 'rxjs';
const subject = new Subject();
Now you need to obtain data from the store. The data can be empty, but when an API call is made, it needs to have data in it. In this tutorial, you'll make use of dummy data. In the data-store.js
, after the Subject, add the following:
let data = [
{
id : 1,
countryName : 'Brasil',
code : 'BR',
capital : 'Brasília',
continent : 'South America',
currency : 'BRL',
languages : 'Portuguese'
},
{
id : 2,
countryName : 'Bahamas',
code : 'BS',
capital : 'Nassau',
continent : 'North America',
currency : 'BSD',
languages : 'English'
},
{
id : 3,
countryName : 'Botswana',
code : 'BW',
capital : 'Gaborone',
continent : 'Africa',
currency : 'BWP',
languages : 'English, Tswana'
},
{
id : 4,
countryName : 'Colombia',
code : 'CO',
capital : 'Bogotá',
continent : 'South America',
currency : 'COP',
languages : 'Spanish'
},
{
id : 5,
countryName : 'Costa Rica',
code : 'CRC',
capital : 'Brasília',
continent : 'North America',
currency : 'CR',
languages : 'Spanish'
},
{
id : 6,
countryName : 'Ecuador',
code : 'EC',
capital : 'Quito',
continent : 'South America',
currency : 'USD',
languages : 'Spanish'
}]
Next, create a method for sending and receiving data from the store:
export const DataStore = {
sendData: (data) => { subject.next([...data] ); },
onData: () => subject.asObservable(),
data,
};
The sendData()
method is used when you want to update the data. A data argument will be provided to the sendData()
method, which will be appended to the data set.
Then the onData()
method returns an Observable that you Subscribe to receive recent data. Also, you export the data so that it can be used as initial data. You need to export the store so it can be imported and used elsewhere.
Use Data in Component
In the _App.js_
file, you need to import the DataStore
and obtain data from the store to use in the useState
hook. To do this, you simply update the initial state of _const [data, setData]_
:
import React, { useState } from 'react';
import { DataStore } from './store/DataStore';
function App() {
const [data, setData] = useState(DataStore.data);
}
Then you need to create a useEffect
hook and subscribe to the onData
method to listen for any changes. Import useEffect
so that you can use it:
import React from 'react';
function App() {
React.useEffect(() => {
const subscription = dataStore.onData().subscribe(data => {
setData(data);
});
return () => subscription.unsubscribe();
} , []);
}
Finally, you need to unsubscribe from the Observable when the component unmounts to prevent memory leaks in the application.
Add Data to the Grid
The next thing you need to create is a form that allows you to add additional country data to the grid. Because you subscribed to it in useEffect
, you're notified when a form submission is made, and the grid is updated in real time.
You can proceed to update the code in the _App.js_
file in order to add an informational form for creating a new grid item. Make a button to turn the form on and off. After that, the form is created and styled. Then you need to handle the toggle and form states as seen here:
const [toggleForm, setToggleForm] = useState(false);
const [formData, setFormData] = useState({
id: "",
countryName: "",
code: "",
capital: "",
continent: "",
currency: "",
languages: ""
});
const triggerToggle = () => {
setToggleForm(!toggleForm);
}
return (
<>
<div className='content-container'>
<div className='new-content'>
<button
className='btn-primary'
onClick={triggerToggle}>Add new
</button>
</div>
{ toggleForm && <div>
<form className='form-container'>
<input
type="text"
placeholder="Country Name"
name='countryName'
id='countryName'
className='form-input'
onChange={(e) =>
setFormData({...formData, countryName: e.target.value})}
value={formData.countryName}
/>
<input
type="text"
placeholder="Code"
name='code'
id='code'
className='form-input'
onChange={(e) =>
setFormData({...formData,
code: e.target.value})
}
value={formData.code}
/>
<input
type="text"
placeholder="Capital"
name='capital'
id='capital'
className='form-input'
onChange={(e) =>
setFormData({...formData,
capital: e.target.value})
}
value={formData.capital}
/> <br />
<input
type="text"
placeholder="Continent"
name='continent'
id='continent'
className='form-input'
onChange={(e) =>
setFormData({...formData,
continent: e.target.value})
}
value={formData.continent}
/>
<input
type="text"
placeholder="Currency"
name='currency'
id='currency'
className='form-input'
onChange={(e) =>
setFormData({...formData,
currency: e.target.value})
}
value={formData.currency}
/>
<input
type="text"
placeholder="Languages"
name='languages'
id='languages'
className='form-input'
onChange={(e) =>
setFormData({...formData,
languages: e.target.value})
}
value={formData.languages}
/>
<div>
<button className='btn-primary' >Submit</button>
</div>
<br />
</form>
</div>}
<BryntumGrid data={data} columns={columns} features={features} />
</div>
</>
);
Now add the styles in the _App.scss_ file
:
.content-container {
width: 100%;
}
.btn-primary {
display: inline-block;
font-weight: 400;
text-align: center;
border: 1px solid transparent;
padding: 0.375rem 0.75rem;
font-size: 1rem;
line-height: 1.5;
border-radius: 0.25rem;
color: #fff;
background-color: #007bff;
border-color: #007bff;
cursor: pointer;
}
.new-content {
display: flex;
justify-content: right;
margin: 10px;
}
.form-container {
text-align: center;
}
.form-input {
padding: 0.375rem 0.75rem;
font-size: 1rem;
line-height: 1.5;
color: #495057;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da;
border-radius: 0.25rem;
margin: 5px;
}
In the previous code, the toggleForm
is used to show and hide the form when you select the Add new button. The formData
holds details of the form, which are set onChange
of the form input. Your current form should look like this:
Upon submission of the form, the data is sent to the RxJS store, and the form is reset. Then since you are subscribing to the store, _data_
will be updated, resulting in a rerender of the grid with the new data added to the table.
Add the submit function in the App.js
file:
const handleSubmit = (e) => {
e.preventDefault();
// to increment the id of the new record
formData.id = data.length + 1;
// to add the new record to the data array
dataStore.sendData([...data, formData]);
// to reset the form
setFormData({
id: '',
countryName: '',
code: '',
capital: '',
continent: '',
currency: '',
languages: ''
});
// to close the form
setToggleForm(!toggleForm);
}
Then update it:
<button className='btn-primary' onClick={handleSubmit}>Submit</button>
Now the list is updated upon submitting:
Grid Features
The Bryntum Grid component uses features, which are prefixed with Feature
as both configuration settings and property values, and are associated with the instance's relevant API features.
Many features of the grid are set to _true_
by default, but you can toggle the features to suit your needs. For instance, in the _App.js_
file, update the _feature_
variable like this:
const [features, setFeatures] = useState({
cellEdit : true,
regionResize : false,
stripe: true,
filter: true,
rowReorder: true,
columnReorder: true,
});
When the _filter_
is set to true, you can filter the data per column like this:
Setting _rowReorder_
to true also allows for row rearrangement. In the following image, the last row is moved to the third row:
Similarly, enabling _columnReorder_
makes it possible to move columns around by dragging the headings:
As you can see, the last column is now the second column.
There are many features available in Bryntum Grid that you can use to listen to events based on the triggering of any feature. A full list of features is available in the Bryntum Grid docs.
Conclusion
In this article, you learned how to use Bryntum Grid with its configurations in a React application. You also learned how to manage the application state with RxJS. In addition, you learned how to get data from the RxJS store to prefill the grid and, later, add more data to the grid from the store.
Are you already using Bryntum Grid? We'd love to hear your feedback on how it's changed your workflow.
Bryntum helps the world stay on schedule. Our component library offers a selection of high-quality, advanced UI controls for various frontend frameworks. Want to learn more? Try out our scheduling and Gantt components at bryntum.com.
Posted on August 8, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.