Coder Social home page Coder Social logo

react-clusterize's People

Contributors

cheton avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

s-a vitaly-z

react-clusterize's Issues

Clusterize.js feature parity

Thanks for writing an awesome React port of Clusterize.js! For my use case, I wanted to apply the Clusterize component to a table body. Unfortunately, the current implementation is a bit opinionated on the DOM structure and doesn't support some of Clusterize.js's features.

I wanted to propose another version of the Clusterize component that I've called ClusertizedContainer. In this component, the wrapper doesn't render a parent/child div. Instead, it renders a container component with a configurable tag. It also replaces the internal scrollElem and makes it a requirement to provide the id of the component with overflow enabled. Furthermore, it includes configurable properties supported by Clusterize.js (e.g blocks_in_cluster), and a convenient handler for row click events.

This, of course, introduces a breaking change to the API. If this is an issue, perhaps it can be included as an optional component? I'd love to hear any thoughts and suggestions. I can share a branch and create a pull request if there is any interest.

import ReactDOMServer from 'react-dom/server';
import ClusterizeJS from 'clusterize.js';
import PropTypes from 'prop-types';
import React from 'react';

class ClusterizedContainer extends React.Component {

    constructor(props) {
        super(props);
        this.contentElem = null;
        this.clusterize = null;
        this.rowClass = `clusterized-container-row-${Math.random()}`;
    }

    shouldComponentUpdate() {
        return false;
    }

    componentDidMount() {
        const clusterizeOptions = {
            rows: this.rowsToStrings(this.props.children),
            contentElem: this.contentElem
        };
        if (typeof this.props.tag !== 'undefined') {
            clusterizeOptions.tag = this.props.tag;
        }
        if (typeof this.props.show_no_data_row !== 'undefined') {
            clusterizeOptions.show_no_data_row = this.props.show_no_data_row;
        }
        if (typeof this.props.rows_in_block !== 'undefined') {
            clusterizeOptions.rows_in_block = this.props.rows_in_block;
        }
        if (typeof this.props.blocks_in_cluster !== 'undefined') {
            clusterizeOptions.blocks_in_cluster = this.props.blocks_in_cluster;
        }
        if (typeof this.props.no_data_text !== 'undefined') {
            clusterizeOptions.no_data_text = this.props.no_data_text;
        }
        if (typeof this.props.no_data_class !== 'undefined') {
            clusterizeOptions.no_data_class = this.props.no_data_class;
        }
        if (typeof this.props.keep_parity !== 'undefined') {
            clusterizeOptions.keep_parity = this.props.keep_parity;
        }
        if (typeof this.props.scrollId !== 'undefined') {
            clusterizeOptions.scrollId = this.props.scrollId;
        }
        this.clusterize = new ClusterizeJS(clusterizeOptions);
    }

    componentWillUnmount() {
        if (this.clusterize) {
            this.clusterize.destroy(true);
            this.clusterize = null;
        }
    }

    componentWillReceiveProps(nextProps) {
        if (this.clusterize !== null) {
            if (nextProps.children.length === 0) {
                this.clusterize.clear();
            } else if (nextProps.children !== this.props.children) {
                this.clusterize.update(this.rowsToStrings(nextProps.children));
            }
        }
    }

    /**
     * Rows To Strings
     *
     * Description: Converts the child row elements to strings.
     * @param rows {array} // The rows to convert.
     * @returns {array} // The same rows as strings.
     */
    rowsToStrings(rows) {
        return rows.map(row => {
            const clone = React.cloneElement(row, {
                className: `${row.props.className} ${this.rowClass}`
            });
            return ReactDOMServer.renderToString(clone);
        });
    }

    /**
     * On Click
     *
     * Description: Handles click events for the container and finds the closest row.
     * @param e {event}  // The event object.
     */
    onClick(e) {
        let elem = e.target;
        while (!elem.classList.contains(this.rowClass)) {
            elem = elem.parentNode;
        }
        this.props.onRowClick(e, elem);
    }

    render() {
        const Container = this.props.container;
        return (
            <Container
                className={this.props.className}
                style={this.props.style}
                onClick={e => this.onClick(e)}
                ref={node => { this.contentElem = node; }}
            />
        );
    }
}

ClusterizedContainer.defaultProps = {
    style: { outline: 'none' },
    onRowClick: () => {},
    container: 'div',
    children: []
};

ClusterizedContainer.propTypes = {
    tag: PropTypes.string,
    show_no_data_row: PropTypes.bool,
    rows_in_block: PropTypes.number,
    blocks_in_cluster: PropTypes.number,
    no_data_text: PropTypes.string,
    no_data_class: PropTypes.string,
    keep_parity: PropTypes.bool,
    children: PropTypes.array.isRequired,
    scrollId: PropTypes.string.isRequired,
    style: PropTypes.object,
    onRowClick: PropTypes.func,
    container: PropTypes.string
};

export default ClusterizedContainer;

Example Usage:

<div id="scrollElem">
    <table>
       <thead>
           <tr>
               <th>Column A</th>
               <th>Column B</th>
           </tr>
       </thead>
       <ClusterizedContainer
            container="tbody"
            scrollId="scrollElem"
            rows_in_block={100}
            onRowClick={(e, row) => { /* noop */ }}>
            { rows }
        </ClusterizedContainer>
    </table>
</div>

Onclick for row element doesn't work

First of all thanks for the excellent component, however I have found one bug:
Adding an onclick event doesn't get put in the DOM when using react-clusterize but does when using vanilla clusterize. Example:

import React from 'react';
import ReactDOM from 'react-dom';
import Clusterize from 'react-clusterize';
 
const rows = [];
const maxRows = 10000;
for (let i = 0; i < maxRows; ++i) {
    rows[i] = (
        <div style={{ borderBottom: '1px solid #f0f0f0', padding: '5px 10px' }}>
            <a onclick="window.alert('not called')">Item #{i + 1}</a>
        </div>
    );
}
rows.length = maxRows;
 
const mountNode = document.getElementById('#container');
 
ReactDOM.render(<Clusterize rows={rows} />, mountNode);

I have tried combinations of onclick, onClick and different types of parameters: binding a function in react, using a code string etc. But none of them seem to be loading.
Many thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.