ReactJS Integration

Why

For some customers we need render hundreds rows in one table with many columns and all with inline AJAX updates for each column. With AngularJS is too slow any sotrable actions, filters and initial render is unusable.

With ReactJS we can render thousands of rows without any lags.

Note

For now it’s an implementation with many dysfunctions versus standard AngularJS. But ready for experimenting.

Beginnings

For this purpose is there initial implementation of ReactJS SortTable which is available for some scenarios.

In previous chapter we introduced how we work with tables and their views.

GenericView has one additionaly argument which specify used table. If we want render React table for our panel we can simply set react=True on Panel class and voila our index is rendered as ReactJS table as we used to.

As you can see in the url if we append /react to our url contrib render ReactJS table. For example our index contrib/models/<my_class>/index/ and append /react finally we have contrib/models/<my_class>/index/react/

Usage

pip install xstatic-react

Add to settings.py

import xstatic.pkg.react

STATICFILES_DIRS = [
    ('lib', xstatic.main.XStatic(xstatic.pkg.react).base_dir),

]
  • /contrib/models/project/react ..

In the Panel

from horizon_contrib.panel import ModelPanel
from horizon_redmine.dashboard import RedmineDashboard

class ProjectPanel(ModelPanel):
    name = "Projects"
    slug = 'projects'
    model_class = 'project'

    react = True

RedmineDashboard.register(ProjectPanel)

As table

from horizon_contrib.tables import ReactTable


class MyReactTable(ReactTable):

    ...

Note

For now we use the in-browser JSX transformer.

ReactJS DataTable

var Table = Reactable.Table;
var Tr = Reactable.Tr;
var Td = Reactable.Td;

var HorizonReactDataTable = React.createClass({
  getInitialState: function(){
    return {data: []};
  },
  render: function(){
    return (
    <Table
      id="{{ table.slugify_name }}"
      className="{% block table_css_classes %}table table-bordered table-striped datatable {{ table.css_classes }}{% endblock %}"
      sortable={true}
      data={this.state.data}
      >
    {% for row in rows %}

      <Tr{{ row.attr_string|safe }}>
          {% spaceless %}
              {% for cell in row %}
                 <Td{{ cell.attr_string|safe }}>{%if cell.wrap_list %}<ul>{% endif %}{{ cell.value }}{%if cell.wrap_list %}</ul>{% endif %}</Td>
              {% endfor %}
          {% endspaceless %}
          <Td>{{ row.render_row_actions }}</Td>
      </Tr>

    {% endfor %}

    </Table>
    )
  },
  componentDidMount: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
 }
});
/* here we expect url/json as data url */
React.renderComponent(<HorizonReactDataTable url="json"/>,
document.getElementById('{{ table.slugify_name }}'));

Note

Implementation uses https://github.com/glittershark/reactable