DEV Community

Bryntum for Bryntum

Posted on

Getting Started with Bryntum Grid, React, and RxJS

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"
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

Then from the terminal, navigate to your project folder and install all the necessary dependencies using the following code:

cd react-bryntum-grid
Enter fullscreen mode Exit fullscreen mode
npm install
Enter fullscreen mode Exit fullscreen mode

Then start the app using the following command:

npm start
Enter fullscreen mode Exit fullscreen mode

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

Bryntum starter template

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;

Enter fullscreen mode Exit fullscreen mode

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';

Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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();

Enter fullscreen mode Exit fullscreen mode

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'
                        }]
Enter fullscreen mode Exit fullscreen mode

Next, create a method for sending and receiving data from the store:

export const DataStore = {
    sendData: (data) => { subject.next([...data] ); },
    onData: () => subject.asObservable(),
    data,
};
Enter fullscreen mode Exit fullscreen mode

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);

}
Enter fullscreen mode Exit fullscreen mode

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();  
} , []);

}

Enter fullscreen mode Exit fullscreen mode

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>
        </>
    );

Enter fullscreen mode Exit fullscreen mode

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;
}

Enter fullscreen mode Exit fullscreen mode

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

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);

    }

Enter fullscreen mode Exit fullscreen mode

Then update it:


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

Enter fullscreen mode Exit fullscreen mode

​​Fill form data

Now the list is updated upon submitting:

Updated grid

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,
    });

Enter fullscreen mode Exit fullscreen mode

When the _filter_ is set to true, you can filter the data per column like this:

Filter data

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

Row reorder

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

Column reorder

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.

Top comments (0)