# Basic

## Introducing

API provides a set of functions for advanced work with the tree: add/remove tree node, searching, changing state and so on.

It is divided into 2 parts for several reasons:

* for reducing the weight of the component
* a separate API has more features that are not very often needed in the work

## Connection

The connection of the API is very easy. The component has a property `onReady`. It calls right after `componentDidMount` call. The API object is passed as the first argument to the `onReady` function.

```javascript
class AwesomeComponent extends React.PureComponent {
    treeApi = null
    
    handleTreeReady = (treeApi) => {
        this.treeApi = treeApi
    }
    
    render() {
        return <EyzyTree 
            data={data}
            onReady={this.handleTreeReady}
        />
    }
}
```

## Methods

{% hint style="info" %}
Most methods accept a **Query** argument. Full description: [Query](query)
{% endhint %}

### find

* **Description**: Finds nodes by specified [Query](query)
* **Arguments**:&#x20;
  * `query`: [Query](query)
* **Returns**:&#x20;
  * `TreeNode`
  * `null` if node is not found
* **Usage:**&#x20;

```javascript
const awesomeNode = this.treeApi.find({text: 'Awesome Node'})
```

###

### findAll

* **Description**: Similar to `find` method. But it returns all found nodes.
* **Arguments**:&#x20;
  * `query`: [Query](query)
* **Returns**:&#x20;
  * `Array<TreeNode>`
* **Usage:**&#x20;

```javascript
const expandedNodes = this.treeApi.findAll({expanded: true})
```

###

### selected

* **Description**: Returns selected nodes. Simple.
* **Returns**: Result can be different depends on mode (multiple or single). See [Component props](../../component-props#options)
  * **Single mode:** `TreeNode` or `null`
  * **Multiple mode:** array of `TreeNode`. It will be **always** an array.
* **Usage:**&#x20;

Single mode:

```javascript
const selectedNode = this.treeApi.selected()

this.setState({
    selectedNodeText: selectedNode ? selectedNode.text : 'Please select a node'
})
```

Multiple mode:&#x20;

{% hint style="info" %}
For a tree in multi-selection mode the **selected** method returns _always_ an array. It does not matter if the selected nodes or not.
{% endhint %}

```jsx
<EyzyTree 
    data={data}
    multiple={true}
/>
```

```javascript
const selectedNodes = this.treeApi.selected()

this.setState({
    selectedNames: selectedNodes.map(node => node.text).join(', ')
})
```

###

### checked

* **Description**: For `checkable` mode the library will combine checked nodes into an array. There are different ways to select "checked" nodes by using `valueConsistsOf` argument.
  * `ALL` (default) it will gather all "checked" nodes
  * `BRANCH` if node has children and it is checked (and all of the children nodes are checked) then all children nodes will be excluded from the result
  * `LEAF` returns nodes which doesn't has children nodes
  * `WITH_INDETERMINATE` the same as `ALL`plus indeterminate nodes
* **Arguments**:&#x20;
  * `valueConsistsOf`: 'ALL' | 'BRANCH' | 'LEAF' | 'WITH\_INDETERMINATE'
  * `showDisabled`: boolean (default **false**)
* **Returns**:&#x20;
  * `Array<TreeNode>`
* **Usage:**&#x20;

```javascript
const checkedBranches = this.treeApi.checked('BRANCH')
```

###

### set

{% hint style="info" %}
It is not recommended to use this method.
{% endhint %}

* **Description**: Set any property to node. This method use `find` method from the API. So it will apply changes only for the **first** match.
* **Arguments**:&#x20;
  * `criteria` [Find criteria](query)
  * `propName`: node of a property (ex: expanded, disabled and so on)
  * `propValue`
* **Returns**:&#x20;
  * `boolean`
* **Usage:**&#x20;

```javascript
this.treeApi.set({expanded: false}, 'expanded', true)
```

To apply changes for all matches use next snippet:

```javascript
const checkedNodes = this.treeApi.findAll({checked: true})

checkedNodes.forEach(node => {
    this.treeApi.set(node.id, 'checked', true)
})
```

###

### data

{% hint style="info" %}
You can store here whatever you want.&#x20;
{% endhint %}

* **Description**: It is getter/setter for the `data` property of the node.
* **Arguments:**
  * `query`: [Query](query)
  * `key`: string | object
  * `value` : any (not required)
* **Returns:**&#x20;
  * `undefined`
  * `data object`
  * `TreeNode`
* **Usage:**

```jsx
// tree data
const data = [
    { text: 'Item 1', data: { isSuper: true } },
    { text: 'Item 2' },
    { text: 'Item 3' }
]

// it will find the first item (!)
this.treeApi.data(/Item/, 'isSuper', false)
// or
// data is instead extended by shallow merge
// node.data will be { isSuper: false, isSuper2: false }
this.treeApi.data(/Item/, { isSuper2: false })

```

{% hint style="info" %}
This method has different return results
{% endhint %}

```jsx
// tree data
const data = [
    { text: 'Item 1', data: { isSuper: true } },
    { text: 'Item 2' },
    { text: 'Item 3' }
]

// return a value: value
this.treeApi.data(/Item/, 'isSuper')

// get full data object: { isSuper: true, isSuper2: 'string' }
this.treeApi.data(/Item/)

// setter: return TreeNode
this.treeApi.data(/Item/, { isSuper2: false })

// setter: return TreeNode
this.treeApi.data(/Item/, 'isSuper2', 'string')
```

###

### addClass

* **Description**: It will add classNames for the node. This class will be added to the node with the class `.node-content` (check [Node's structure](../../customization#nodes-strcutrure))
* **Arguments:**
  * `query`: [Query](query)
  * `Array<className>`: string\[]
* **Returns:**&#x20;
  * `TreeNode` if node is found
  * `null` if node is not found
* **Usage:**

```javascript
this.treeApi.addClass(/excess/, ['excess-node', 'you-can', 'pass', 'many', 'names'])
```

###

### removeClass

* **Description**: The same behavior as `addClass` method, but it removes classNames
* **Arguments:**
  * `query`: [Query](query)
  * `Array<className>`: string\[]
* **Returns:**&#x20;
  * `TreeNode` if node is found
  * `null` if node is not found
* **Usage:**

```javascript
this.treeApi.removeClass(/excess/, ['excess-node', 'you-can', 'pass', 'many', 'names'])
```

###

### hasClass

* **Description**: Checks if a node has a `className`
* **Arguments:**
  * `query`: [Query](query)
  * `className`: string
* **Returns:**&#x20;
  * `boolean`
* **Usage:**

```javascript
const hasClass = this.treeApi.hasClass(/excess/, 'highligted')
```

###

### append

* **Description**: Inserts nodes to the end of the matched node
* **Arguments:**
  * `query`: [Query](query)
  * `nodes`: _string | object | Promise_
  * `opts`: [Insertion options](../../guides/async#insertion-options)
* **Returns:**&#x20;
  * `Promiselike<TreeNode[]>` added nodes (always an array)
  * `null` if node is not found
* **Usage:**

```javascript
const appendedNodes = this.treeApi.append(
    'Item 1', // find criteria
    ['Item 1.1.', 'Item 1.2'], // nodes can be as string
    true // expand node with text 'Item 1' (if node was found)
)

this.treeApi.append(
    { selected: true },
    [
        { text: 'Selected children 1', disabled: true },
        { text: 'Selected children 2' }        
    ]
)

// it also can be a function, but it must return a Promise
this.treeApi.append(
    'Selected children 2',
    (node) => {
        // node.text === 'Selected children 2'
        return fetch(`/api?childName=${node.text}`)
            .then(response => response.json())
    }
)
```

###

### prepend

* **Description**: This method is similar to `append`. But nodes inserting to the beginning of children list. (well ... you know, as well as jQuery :) )
* **Example:**

```javascript
// tree structure
/**
item 1
item 2
 item 2.1
 item 2.2
item 3
*/

this.treeApi.append('item 2', [
 'item 2.3', 'item 2.4', { text: 'item 2.5', checked: true }
])

// will be:
/**
item 1
 item 2.3    << new node
 item 2.4    << new node
 item 2.5    << new node
 item 2.1
 item 2.2
item 2
item 3
*/
```

###

### before

* **Description**: This method is similar to `append`. But nodes inserting **before** matched node.
* **Example:**

```javascript
// tree structure
/**
item 1
item 2
item 3
*/

this.treeApi.before(/item 2/, 'item n')

// will be:
/**
item 1
item n <<<<<<< -- added node
item 2
item 3
*/
```

###

### after

* **Description**: This method is similar to `append`. But nodes inserting **after** matched node.

```javascript
// tree structure
/**
item 1
item 2
item 3
*/

this.treeApi.before(/item 2/, 'item n')

// will be:
/**
item 1
item 2
item n <<<<<<< -- added node
item 3
*/
```

###

### remove

* **Description**: It removes matched node.
* **Arguments:**
  * `query`: [Query](query)
* **Returns:**&#x20;
  * `TreeNode` removed node
  * `null` if node is not found
* **Usage:**

```javascript
const removedNode = this.treeApi.remove(/bad node/)

if (removedNode) {
    alert(`Congrat... node(${removedNode.id} has removed!`)
}
```

###

### uncheckAll

* **Description**: Set for all _checked_ nodes _unchecked_ states



### unselectAll

* **Description**: Removes selection for all selected nodes

###

### toArray

* **Description**:  Returns list of nodes.

