Getting Started with Bryntum Grid, React, and RxJS
Tags: react, javascript, ui, rxjs
Published: 2023-08-08 10:16:59


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](https://www.bryntum.com/products/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)](https://sass-lang.com).

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](https://reactjs.org), Bryntum Grid, and [Reactive Extensions for JavaScript (RxJS)](https://rxjs.dev). 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](https://nodejs.org/en/) version 14 or newer installed on your operating system (OS). You'll also need a code editor. Here, [Visual Studio (VS) Code](https://code.visualstudio.com/) 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](https://reactjs.org/docs/getting-started.html) and [Bryntum React guide](https://www.bryntum.com/docs/grid/guide/Grid/quick-start/react).

All the code for this tutorial can be found in this [GitHub repo](https://github.com/Chidexprince/react-bryntum-grid).

### Set Up Bryntum Grid

In this tutorial, you'll learn how to get started if you're using the [Create React App script](https://create-react-app.dev/). 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:

```bash 
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:

```bash
 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](https://bryntum.com/store/calendar). 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:

```bash
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:

```bash 
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:

```js
"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:

```js
"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:

```bash
cd react-bryntum-grid
```

```bash
npm install
```

Then start the app using the following command:

```bash
npm start
```

You should see the following page with a sample grid on it:

![Bryntum starter template](https://i.imgur.com/lMxnCo7.png)

### 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:

```javascript

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:

```css

// 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](https://www.bryntum.com/docs/grid/api/Grid/feature).

### 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](https://rxjs.dev/guide/overview).

The fundamental features of RxJS are as follows:

* **[Observable](https://rxjs.dev/guide/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](https://rxjs.dev/guide/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](https://rxjs.dev/guide/subscription):** This has to do with an observer requesting information from an observable. An observer will only receive data that they subscribe to.
* **[Subjects](https://rxjs.dev/guide/subject):** 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:

```bash 
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_`:

```javascript
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:

```javascript
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:

```javascript
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]_`:

```javascript
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:

```javascript
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:

```javascript
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`:

```css

.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:

![Info form](https://i.imgur.com/klmc0rv.png)

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:

```javascript
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:

```javascript

<button className='btn-primary' onClick={handleSubmit}>Submit</button>

```

​​![Fill form data](https://i.imgur.com/xKUBGPV.png)

Now the list is updated upon submitting:

![Updated grid](https://i.imgur.com/tYDFeys.png)

### 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:

```js
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:

![Filter data](https://i.imgur.com/kIB4n45.gif)

Setting `_rowReorder_` to true also allows for row rearrangement. In the following image, the last row is moved to the third row:

![Row reorder](https://i.imgur.com/fH5mmYS.gif)

Similarly, enabling `_columnReorder_` makes it possible to move columns around by dragging the headings:

![Column reorder](https://i.imgur.com/gM88Y8b.gif)

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](https://www.bryntum.com/docs/grid/guide/Grid/integration/react/guide#features).

## Conclusion

In this article, you learned how to use [Bryntum Grid](https://www.bryntum.com/products/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](https://www.bryntum.com) 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](https://www.bryntum.com).