# XlReactWidgetLazyLoadedTreeComponent

This component is a wrapper for `XlReactWidgetTree` which brings on top of that the loading of nodes on demand. 
`XlReactWidgetTree` gives an opportunity to not display those nodes, but from backend part they all be fetched.
In this component you can provide pagination and when user starts scrolling the list/tree down the new nodes will be 
fetched. To make more smooth experience for the user, a bit more nodes are fetched then displayed on the screen and 
at certain point of scroller (calculated in px and can be customized with parameters) fetching the next page of data
starts.

## Summary

* [Exports](#exports)
* [Playground](#playground)

### Exports
```text
- XlReactWidgetLazyLoadedTree
```  

### Playground
* [Lazy Loaded Tree Widget](https://xebialabs.github.io/xl-react-components/kitchen-sink.html#/widget/widgetTreeLazyLoaded)

### Properties

- **autoOpen** - (bool) - if true, opens all nodes.
- **blocksInCluster** - (number) - Default value is 4. Specifies the amount of blocks in cluster. When scroll reaches last block - content replaces with next cluster.
- **className** - (string) - Default value `tree-container`. Specifies the class name of the tree component
- **dndHandlers** - (object) - provides options to work with drag and drop functionality. Fires when
    - **onDrag** - (func) - a dragged item (element or text selection) is dragged.
    - **onDragEnd** - (func) - a drag operation ends (such as releasing a mouse button or hitting the Esc key)
    - **onDragEnter** - (func) - a dragged item enters a valid drop target. 
    - **onDragExit** - (func) - an element is no longer the drag operation's immediate selection target.
    - **onDragLeave** - (func) - a dragged item leaves a valid drop target.
    - **onDragOver** - (func) - a dragged item is being dragged over a valid drop target, every few hundred milliseconds.
    - **onDragStart** - (func) - the user starts dragging an item.
    - **onDrop** - (func) - an item is dropped on a valid drop target.
- **dontSelectClasses** - (array of strings) - CSS classes which makes nodes not selectable. That can be
useful, when it is possible to select only a certain group of nodes at a time. Or if certain nodes never 
can be selected, or if user doesn't have permissions on certain nodes.  
- **droppableOptions** - (boolean or object) - By default is false (not droppable). Makes tree nodes droppable.
    - **accept** - (function) - By default `(event, options) => true`. Controls which draggable elements are accepted by the droppable.
    - **drop** - (function) - By default `function(event, options) {}`.  Triggered when an accepted draggable is dropped on the droppable.
    - **hoverClass** - (string) - By default `""`. If specified, the class will be added to the droppable while an acceptable draggable is being hovered over the droppable.
- **hasMore** - (boolean) - By default `false`. That's an indication for the component whether it should do a request 
for the next page of data. 
- **isLoadingNewNodes** - (boolean) - By default `false`. If `true` will display a spinner to indicate that
 new data is loading
- **loadNodes** - (function) - By default `null`. Loads nodes on demand.
- **model** - (array) - Array of nodes treated as an initial data for the tree. 
- **newNodes** - (array) - Array of new nodes which will be appended to a tree.
- **noDataText** - (string) - By default `No data`. Displayed text in case when tree data is empty.
- **nodeHandlers** - (object) - Shape of the object is:  `{ onCloseNode: PropTypes.func, onOpenNode: PropTypes.func}`.
You can provide 1 or 2 handlers to listen events when node is expanded or collapsed. As a parameter you'll receive the full
node.
- **onClick** - (function) - That's a handler which is triggered whenever any part of tree is clicked. 
Therefore you have only 1 handler which reacts on click, instead of N listeners attached to each tree node.
- **onDoubleClick** - (function) - Same as `onClick` but do double click.
- **onNodesSelected``** - (function) - That's handler is triggered in 3 situations: 
    * when single node selected
    * when multiple nodes selected (multi clicked nodes)
    * when nodes selected in batch (Ctrl/Cmd + Shift)   
- **onScrollEnd** - (function) - that function will be called when new data has to be fetched for the next bunch of nodes.
- **registerNodeListeners** - (function) - that handler is triggered once the tree is mounted and provided as a parameter
to attach listeners to it.
- **rowRenderer** - (function) - This is a required function which will be triggered to render the node.
There is no default renderer. But there are some predefined renderer which you can use:
    * xlReactTreeRowRenderer
    * xlReactIconRenderer
    * XlReactTreeRowComponent
    * xlReactTreeRowIconRenderer
- **scrollEndThreshold** - (number) - By default `50`px. Number of pixels of the scroller till the end of the screen when
when it will identify that new data has to be fetched.  
- **selectable** - (boolean) - By default `true`. If set to `false` it won't be possible to select any node.
Can be useful in case of view only mode.
- **selectedNodes** - (array of strings) - This is an array of node ids which will be highlighted to represent
selected nodes.
- **selectionMode** - (enum 'single' or 'multi') - If set to 'single', selection of second node will deselect first node.
- **treeRef** - (function) - Callback which will be triggered and assigns the reference to a tree element. You
will need it in case of direct access of infinite-tree API methods.

### Example

```javascript
import R from 'ramda';

const assignTree = (component) => {
  if (component) {
      this.tree = component.tree;
  }
};

const rowRenderer = R.curry((highlightText, node) => {
    const label = node.renameMode ?
        <input
            className="infinite-tree-rename-input"
            data-current-value={node.name}
            data-id={node.id}
            defaultValue={node.name}
            type="text"
        /> : <span className="infinite-tree-title" data-id={node.id} data-type={node.type}>
            {buildNodeTitle(highlightText, node)}
        </span>;
    return <XlReactTreeRowComponent
        data-type={node.type}
        draggable={true}
        node={node}
        togglerClass={getTogglerClass(node)}>
        {xlReactTreeRowIconRenderer(node.icon)}
        {label}
        {renderContextMenuIcon(node)}
    </XlReactTreeRowComponent>;
});

const selectedNodes = () => selectedNode ? [selectedNode] : [];

const handleScrollEnd = () => {
    this.props.loadMoreSearchResults();
};

const handleNodesSelected = (selectedNodes) => {
    this.props.onSelectNodes(selectedNodes);
};

const registerNodeListeners = (tree) => {
    $(treeSelector).off('click', contextMenuButtonSelector);
    $(treeSelector).on('click', contextMenuButtonSelector, createOpenContextMenuHandler(false));
};

 <XlReactWidgetLazyLoadedTree
    hasMore={this.props.hasMore}
    isLoadingNewNodes={this.props.isLoadingSearchResults}
    newNodes={this.props.searchResults}
    onNodesSelected={handleNodesSelected}
    onScrollEnd={handleScrollEnd}
    registerNodeListeners={registerNodeListeners}
    rowRenderer={rowRenderer(searchText || '')}
    selectedNodes={selectedNodes}
    treeRef={assignTree}
/>

```
