React bootstrap table with Meteor?


#1

Hi,

I am trying to move slowly from Blaze to React. I want to have a reactive table in the page, with sorting and search. Looks like there’s already a solid one implemented as React component. However, I don’t know how to add this to my project, I know, quite a noobie…

Any advice?


#2

Hey,

Yeah - I got this to work. In essence -

Follow instructions on the git page, https://github.com/AllenFang/react-bootstrap-table to install.

  1. Do the install in your project: meteor npm install react-bootstrap-table --save
  2. You will also need to add: meteor npm install --save meteor-node-stubs
  3. You don’t need to build it, just do the ECMAScript 6 import in your component.
  4. Add in the CSS file. Just copy into your client/spreadsheets directory.

Example below: There is a bunch of other stuff i was p[laying with, specifically an accordion, but the getUsers2() is what you want.

// imports/ui/components/globaladmin/users-list.js

import React, { Component, PropTypes } from 'react';
import { createContainer } from 'meteor/react-meteor-data';

// Publications
import { Users } from '../../../api/globaladmin/users.js';

// React-Bootstrap
import { Accordion, Panel } from 'react-bootstrap';

// React-Bootstreap-Table
import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';

// Sub Components
import User from './user.js';

class UsersList extends Component {
  getUsers() {
    return this.props.users.map((user) =>
      <User key = {user._id} user = {user} />
    );
  }

  getUsers2() {
    const users = [];

    const quantity = this.props.count;
    for (let i = 0; i < quantity; i++) {
      users.push({
        id: this.props.users[i]._id,
        name: this.props.users[i].profile.name.first
         + this.props.users[i].profile.name.last,
      });
    }

    return (
      <BootstrapTable data={ users }>
        <TableHeaderColumn dataField="id" isKey={ true }>Product ID</TableHeaderColumn>
        <TableHeaderColumn dataField="name">Product Name</TableHeaderColumn>
      </BootstrapTable>
    );
  }

  render() {
    return (
      <div className="global-admin">
        <Accordion>
          <Panel header="Collapsible Group Item #1" eventKey="1">
            {this.getUsers()}
          </Panel>
          <Panel header="Collapsible Group Item #2" eventKey="2">
            {this.getUsers2()}
          </Panel>
          <Panel header="Collapsible Group Item #3" eventKey="3">
            <p>Even more stuff</p>
          </Panel>
        </Accordion>
      </div>
    );
  }
}

UsersList.propTypes = {
  users: PropTypes.array.isRequired,
  count: PropTypes.number.isRequired,
};

export default createContainer(() => {
  Meteor.subscribe('users-list');

  return {
    users: Users.find({}).fetch(),
    count: Users.find().count(),
  };
}, UsersList);

Looks like:

I’m using Meteor Chef’s base as the harness for this. I’ll try to put together a gist about how to use all these nicely in a bit. Table’s in React seem like far more pain and boilerplate than they should be. I did not bother changing the productname and product id, that was from the example i was using.

Tat


#3

Hi ,
I have been able to get this working . But “New Row” modal does not seem to be working .

  • The modal code is present in the html
  • if I change the display options of the modal it shows on the screen

So I believe the issue could be because of data-toggle property not working within the meteor setup.Any ideas ?


#4

Hi @smitkant ,

I got it to work using below. I ended up not actually using the component, as I’m trying to learn react. But below is what I did -

import React from 'react';

// Container
import { createContainer } from 'meteor/react-meteor-data';

// React-Bootstrap-Table
import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';

function addRole(row) {
  Meteor.call('roles.insert', row.toString());
}

function removeRole(row) {
  Meteor.call('roles.remove', row.toString());
}

const options = {
  afterInsertRow: addRole,
  afterDeleteRow: removeRole,
};

const selectRowProp = {
  mode: 'radio',
};

class Working extends React.Component {
  getRoles() {
    const roles = [];
    const quantity = this.props.count;

    for (let i = 0; i < quantity; i ++) {
      roles.push({
        number: i,
        id: this.props.roles[i]._id,
        name: this.props.roles[i].name,
      });
    }

    return roles;
  }

  render() {
    return (
      <div>
        <h4>Role List</h4>
        <BootstrapTable
          data={ this.getRoles() }
          insertRow={ true }
          deleteRow={ true }
          selectRow={ selectRowProp }
          options={ options }
        >
          <TableHeaderColumn dataField="number">Role #</TableHeaderColumn>
          <TableHeaderColumn dataField="name" isKey={ true }>Role Name</TableHeaderColumn>
        </BootstrapTable>
      </div>
    );
  }
}

Working.propTypes = {
  // Some props here
  roles: React.PropTypes.array.isRequired,
  count: React.PropTypes.number.isRequired,
};

export default createContainer(() => {
  Meteor.subscribe('roles-list');

  return {
    roles: Meteor.roles.find({}).fetch(),
    count: Meteor.roles.find().count(),
  };
}, Working);

The options triggers the below -

const options = {
  afterInsertRow: addRole,
  afterDeleteRow: removeRole,
};

This calls the relevant functions. The roles.insert and roles.remove are on the server side. I’m using the roles package here for authentication/authorization. It was just a convenient collection to play around with while I was testing this.

function addRole(row) {
  Meteor.call('roles.insert', row.toString());
}

function removeRole(row) {
  Meteor.call('roles.remove', row.toString());
}

Thanks so much.

Tat


#5

Thx a ton Tat. Will try this out .


#6

Hi Tat,

import React, { Component } from 'react';
import {BootstrapTable,TableHeaderColumn} from 'react-bootstrap-table';

// App component - represents the whole app
export default class App extends Component {

    render(){
        var data = [
            {id : 1, name : "Tom"},
            {id : 2, name : "Dick"},
            {id : 3, name : "Harry"},
        ];

        var selectRowProp = {
            mode: "radio"
        };

        return(
            <BootstrapTable
                data={data}
                selectRow={selectRowProp}
                insertRow={true}
            >
                <TableHeaderColumn dataField="id" isKey={true}>Id</TableHeaderColumn>
                <TableHeaderColumn dataField="name" >Name</TableHeaderColumn>
            </BootstrapTable>
        );
    }
}

have reduced the code to this . but still can’t get the modal to open on clicking “New Row” .
HTML file looks like this

<head>
    <title>Test table</title>

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="react-bootstrap-table-all.min.css" >
</head>

<body>
<div id="app"></div>
</body>

Any ideas ? BTW i am including the CSS file by creating a soft link from inside the node_modules folder

Smit


#7

I simply manually copied the css file into my stylesheets folder. I’m not sure it works if you use the <link....> thing. Also added bootstrap directly from npm…

Also, to be honest, the entire thing was very fiddly. It was easier to just build a table directly from react-bootstrap.

Tat


#8

Hi Tat,

Thanks for the reply . Silly me had included bootstrap js file incorrectly . Its sorted now . Thanks again

Smit


#9

How to handle properly pagination in publications on the server side ?