I'm using rc-tree, a version of tree.js to react, I dont know how create a method that when check on a tree item change a property of that element, parent items and their children items.
For example:
If I click on New Folder1 change checked value on New Folder1 item,
new Folder2, new Folder3 and finally, layer12.
If I click on layer12 change checked value on layer12, New Folder3,
New Folder2 and finally New Folder1.
And If I click on new Folder2 change checked value on Folder2,
Folder1, Folder3 and finally layer12.
Here is a json schema:
{
"name": "New Folder1",
"key": "0-625",
"isLeaf": false,
"type": "folder",
"expanded": false,
"checked": true,
"children": [{
"name": "New Folder2",
"key": "0-629",
"isLeaf": false,
"type": "folder",
"expanded": false,
"checked": true,
"children": [{
"name": "New Folder3",
"key": "0-623",
"isLeaf": false,
"type": "folder",
"expanded": false,
"checked": true,
"children": [{
"name": "layer12",
"key": "0-99",
"isLeaf": true,
"type": "layer",
"checked": true
}]
}]
}]
},
I found this method where find node when you check and item on tree. But how to change their children nodes and parent nodes.
function getNodeByKey(key, node){
var reduce = [].reduce;
function runner(result, node){
if(result || !node) return result;
return node.key === key && node || //is this the proper node?
runner(null, node.children) || //process this nodes children
reduce.call(Object(node), runner, result); //maybe this is some ArrayLike Structure
}
return runner(null, node);
}
EDIT:
In React you need to use the ref property in order to access the node element and then you can access the child and parent using javascript: reactjs
To access child and parent I guess that I have to use childNodes, parentNode, nextSibling and previousSibling.
But how can use ref property??? Because its an array of nodes
render() {
const loop = (data) => {
return data.map((item) => {
if (item.children && item.children.length) {
return <TreeNode ref={this.myRef} title={item.name} key={item.key} checked={item.checked} >{loop(item.children)}</TreeNode>;
}
return (
<TreeNode ref={this.myRef} title={item.name} key={item.key} isLeaf={item.isLeaf} checked={item.checked} />
);
});
};
return (
<div className="draggable-container">
<Tree
// Expand
expandedKeys={this.state.expandedKeys}
onExpand={this.onExpand} autoExpandParent={this.state.autoExpandParent}
// Draggable
draggable
onDragStart={this.onDragStart}
onDragEnter={this.onDragEnter}
onDrop={this.onDrop}
// Select && Check
onSelect={this.onSelect}
checkable onCheck={this.onCheck} checkedKeys={this.state.checkedKeys} >
{ loop(this.state.treeData) }
</Tree>
</div>
);
}
onCheck = (checkedKeys, event) => {
how can get node checked??? it always returns last node
const node = this.myRef.current;
console.log(node)
}
So... regarding your 'ref' issue: you assigned them all to the same variable, you should generate ref-variable for each node:
this.myRefs = {};
<TreeNode ref={itemRef=>this.myRefs[item.key]=itemRef} title={item.name} key={item.key} checked={item.checked} >{loop(item.children)}</TreeNode>
So you can access each node by its key.
Another way to implement it would be to assign a more useful keys:
{
"name": "New Folder1",
"key": "0",
"isLeaf": false,
"type": "folder",
"expanded": false,
"checked": true,
"children": [{
"name": "New Folder2",
"key": "0.0",
"isLeaf": false,
"type": "folder",
"expanded": false,
"checked": this.state.keysCheckedStatus['0.0'],
"children": [{
"name": "New Folder3",
"key": "0.0.0",
"isLeaf": false,
"type": "folder",
"expanded": false,
"checked": this.state.keysCheckedStatus['0.0.0'],
"children": [{
"name": "layer12",
"key": "0.0.0.0",
"isLeaf": true,
"type": "layer",
"checked": this.state.keysCheckedStatus['0.0.0.0']
},{
"name": "layer13",
"key": "0.0.0.1",
"isLeaf": true,
"type": "layer",
"checked": this.state.keysCheckedStatus['0.0.0.1']
}]
}]
}]
}
onCheck = (checkedKeys, event) => {
let keysCheckedStatus = this.state.keysCheckedStatus;
for(let key in checkedKeys){
let connectedKeys= Object.keys(this.state.keysCheckedStatus)
.filter(k=> (k.length > key.length) && k.startsWith(key)) || (key.startsWith(k));
for(let connectedKey in connectedKeys){
keysCheckedStatus[connectedKey]=true;
}
}
this.setState({keysCheckedStatus});
}
This is my solution, because my idea is modify treeData with all tree info nodes:
onCheck = (checkedKeys, event) => {
// console.log(this.treeData);
const checkedKey = event.node.props.eventKey;
this.updateItemChecked(checkedKey);
this.setState({ checkedKeys: checkedKeys }, () => {
this.props.parentTree(this.treeData);
});
}
updateItemChecked = (key) => {
var result = getNodeByKey(key, this.treeData);
if (result.type.localeCompare('folder') !== 0) {
if (result.checked === true ) {
result.checked = false;
} else {
result.checked = true;
}
} else {
this.checkIfFolderHasItem(result);
}
}
checkIfFolderHasItem = (result) => {
if ( result.children && result.children.length > 0) {
result.children.forEach( (item) => {
if (item.type.localeCompare('folder') !== 0) {
this.updateItemChecked(item.key);
} else {
this.checkIfFolderHasItem(item);
}
});
}
}
// Expand
onExpand = (expandedKeys, event) => {
// console.log('onExpand', expandedKeys);
const checkedKey = event.node.props.eventKey;
this.updateFolderExpanded(checkedKey);
this.setState({ expandedKeys, autoExpandParent: false }, ()=> {
this.props.parentTree(this.treeData);
});
}
updateFolderExpanded = (key) => {
var result = getNodeByKey(key, this.treeData);
if (result.type.localeCompare('folder') === 0) {
if (result.expanded === true ) {
result.expanded = false;
} else {
result.expanded = true;
}
}
}
render() {
const loop = (data) => {
return data.map((item) => {
if (item.children && item.children.length) {
return <TreeNode title={item.name} key={item.key} checked={item.checked} >{loop(item.children)}</TreeNode>;
}
return (
<TreeNode title={item.name} key={item.key} isLeaf={item.isLeaf} checked={item.checked} />
);
});
};
return (
<div className="draggable-container">
{
// (this.state.showModal) ? <TreeModal show={this.state.showModal} info={this.state.selected} treeData={this.state.treeData} parentTreeModal={this.doParentTreeModal} /> : null
}
<Tree
// Expand
expandedKeys={this.state.expandedKeys}
onExpand={this.onExpand} autoExpandParent={this.state.autoExpandParent}
// Draggable
draggable
onDragStart={this.onDragStart}
onDragEnter={this.onDragEnter}
onDrop={this.onDrop}
// Select && Check
onSelect={this.onSelect}
checkable onCheck={this.onCheck} checkedKeys={this.state.checkedKeys} >
{ loop(this.state.treeData) }
</Tree>
</div>
);
}
JSON Example:
[
{
"name": "Capas1",
"key": "0-23",
"isLeaf": false,
"type": "folder",
"expanded": true,
"children": [{
"name": "sectores",
"key": "0-20",
"isLeaf": true,
"type": "layer",
"checked": true
},
{
"name": "distribucion",
"key": "0-22",
"isLeaf": true,
"type": "layer",
"checked": false
}]
},
{
"name": "Nueva Carpeta0",
"key": "0-624",
"isLeaf": false,
"type": "folder",
"expanded": false,
"checked": false
},
{
"name": "Nueva Carpeta1",
"key": "0-625",
"isLeaf": false,
"type": "folder",
"expanded": true,
"children": [{
"name": "Nueva Carpeta2",
"key": "0-629",
"isLeaf": false,
"type": "folder",
"expanded": true,
"children": [{
"name": "Nueva Carpeta3",
"key": "0-623",
"isLeaf": false,
"type": "folder",
"expanded": true,
"children": [{
"name": "distribucion33",
"key": "0-99",
"isLeaf": true,
"type": "layer",
"checked": true
}]
}]
}]
},
{
"name": "sectores1",
"key": "0-27",
"isLeaf": true,
"type": "layer",
"checked": true
},
{
"name": "sectores12",
"key": "0-89",
"isLeaf": true,
"type": "layer",
"checked": false
},
{
"name": "Capas 2",
"key": "0-588",
"isLeaf": false,
"type": "folder",
"expanded": false,
"children": [{
"name": "Capas 3",
"key": "0-589",
"isLeaf": false,
"type": "folder",
"expanded": false,
"children": [{
"name": "Prueba",
"key": "0-36",
"isLeaf": true,
"type": "layer",
"checked": false
}]
}]
}
]
Related
Issue:
I'm trying to update(axios.patch) active data from false to true of a nested object (children) by ID using axios patch request. I'm using vuejs as my frontend and json-server as my backend. Can anyone please help me.
Data:
{
"id": 3,
"icon": "store",
"name": "Store Management",
"children": [
{
"id": 1,
"name": "Tables",
"icon": "",
"active": false,
"path": "/store-management/tables"
},
{
"id": 2,
"name": "Discounts",
"icon": "",
"active": false,
"path": "/store-management/discounts"
},
{
"id": 3,
"name": "Surcharges",
"icon": "",
"active": false,
"path": "/store-management/surcharges"
},
{
"id": 4,
"name": "Promos",
"icon": "",
"active": false,
"path": "/store-management/promos"
}
],
"expanded": true,
"path": "",
"active": false,
"hasChildren": true
}
Function:
When I call the #click function the navigateChildren will execute and it needs to get the path of the nested object and at the same time update the active value to true or false.
async navigateChildren(id) {
try {
const menuChildren = await axios.get('http://localhost:3000/menu/3')
const menuChildrenList = menuChildren.data
const children = menuChildrenList.children[id - 1]
const inactive = await axios.patch(
'http://localhost:3000/menu/' + this.menuId,
{
active: false
}
)
console.log(inactive)
const active = await axios.patch('http://localhost:3000/menu/3', {
children: {
active: true
}
})
console.log(active)
const path = children.path
this.$store.commit('setMenuId', id)
this.$router.push(path)
console.log(children)
} catch (error) {
}
}
Many Thanks.
I have an object like this :
{
"roleId": "75f6af0f-a483-4ad1-af5f-5802887fe5e6",
"roleClaims": [
{
"type": "Permissions",
"value": "Permissions.Brands.View",
"selected": false
},
{
"type": "Permissions",
"value": "Permissions.Brands.Create",
"selected": false
},
{
"type": "Permissions",
"value": "Permissions.Dashboard.Create",
"selected": false
},
{
"type": "Permissions",
"value": "Permissions.Users.Create",
"selected": false
}
]
}
I want to re-organize the roleClaims array [ like each unique types objects (value = "Permissions.Brands.View" > Brands ) are separated array ] as mentioned below. And additionally add an extra property checkboxId (which value is unique number) to filtered object from the array of objects.
Is is really possible?
{
"roleId": "75f6af0f-a483-4ad1-af5f-5802887fe5e6",
"roleClaims": [
{
"valueId": "a8ca7eac-4f18-42d6-983f-44f6a8e157dc",
"valueType": "Brands",
"valueArray": [
{
"checkboxId": uuidv4(), // create new unique id
"type": "Permissions",
"value": "Permissions.Brands.View",
"selected": false
},
{
"checkboxId": uuidv4(),,
"type": "Permissions",
"value": "Permissions.Brands.Create",
"selected": false
}
]
},
{
"valueId": "a2566fd4-8763-41d4-881e-029851a440fd",
"valueType": "Dashboard",
"valueArray": [
{
"checkboxId": uuidv4(),,
"type": "Permissions",
"value": "Permissions.Dashboard.Create",
"selected": false
}
]
},
{
"valueId": "72328955-2bd2-469c-a094-be0bba383edd",
"valueType": "Users",
"valueArray": [
{
"checkboxId": uuidv4(),,
"type": "Permissions",
"value": "Permissions.Users.Create",
"selected": false
}
]
}
]
}
I tried with this :
const getRoleDetailsByRoleId = roleId => {
axios.get(`${urls.account.permissions.get_all_by_roleId}?roleId=${roleId}`).then(res => {
const permissionData = res.data;
const splitedValues = [];
permissionData.roleClaims.forEach(item => splitedValues.push(item.value.split('.')[1]));
const uniqueValues = [...new Set(splitedValues)];
const modifiePermissiondObj = {
roleId: permissionData.roleId,
roleClaims: uniqueValues.map(item => ({
valueId: uuidv4(),
valueType: item,
valueArray: permissionData.roleClaims.filter((fileredItem, index, arr) => fileredItem.value.split('.')[1] === item)
}))
};
setPermissions(modifiePermissiondObj);
setIsPageLoaded(true);
});
};
I have modified the roleClaims array but can't add the additional property.
If possible please help me.
const permissionData = {
"roleId": "75f6af0f-a483-4ad1-af5f-5802887fe5e6",
"roleClaims": [
{
"type": "Permissions",
"value": "Permissions.Brands.View",
"selected": false
},
{
"type": "Permissions",
"value": "Permissions.Brands.Create",
"selected": false
},
{
"type": "Permissions",
"value": "Permissions.Dashboard.Create",
"selected": false
},
{
"type": "Permissions",
"value": "Permissions.Users.Create",
"selected": false
}
]
}
const transformedPermissionData = permissionData.roleClaims.reduce((newOutput, role) => {
const extractedRole = role.value.split('.')[1];
const roleIndex = newOutput.roleClaims.findIndex(output => output && output.valueType === extractedRole)
if(roleIndex !== -1){
newOutput.roleClaims[roleIndex].valueArray.push({...role, checkboxId: 'UUID'})
}else {
newOutput.roleClaims.push({
valueId: 'UUID',
valueType: extractedRole,
valueArray: [{...role, checkboxId: 'UUID'}]
})
}
return newOutput
}, { roleId: permissionData.roleId, roleClaims: []})
console.log(transformedPermissionData)
You just need to map your valueArray like this:
valueArray: permissionData.roleClaims
.filter((fileredItem, index, arr) => fileredItem.value.split('.')[1] === item)
.map(value => ({...value, checkboxId: uuidv4()}))
I have a REST call which returns different sets of result. Each data set contains data for different parts of the page. It contains nested array of objects and I am not sure how do I easily display the name and value pairs from the rest call to my page depending on the certain section.
Here's what the REST call response looks like:
{
"dstrSpecificHelpRs": [
{
"row": [
{
"name": "HELP_TEXT_TITLE_NM",
"value": "TestAgain and again and again and again andagain50",
"link": {
"exists": false,
"linkType": null,
"linkId": null
}
},
{
"name": "HELP_TEXT_ID",
"value": "100114",
"link": {
"exists": false,
"linkType": null,
"linkId": null
}
},
{
"name": "Help",
"value": "Help",
"link": {
"exists": true,
"linkType": "url",
"linkId": "www.google.com"
}
}
]
},
{
"row": [
{
"name": "HELP_TEXT_TITLE_NM",
"value": "Testing Helpline Page and 2301 DisasterONLY",
"link": {
"exists": false,
"linkType": null,
"linkId": null
}
},
{
"name": "HELP_TEXT_ID",
"value": "100174",
"link": {
"exists": false,
"linkType": null,
"linkId": null
}
},
{
"name": "Help",
"value": "Help",
"link": {
"exists": true,
"linkType": "url",
"linkId": "www.google.com"
}
}
]
}
],
"rgstInfoRs": [
{
"row": [
{
"name": "PREFIX_NM",
"value": "MS",
"link": {
"exists": false,
"linkType": null,
"linkId": null
}
},
{
"name": "FST_NM",
"value": "MITZI",
"link": {
"exists": false,
"linkType": null,
"linkId": null
}
}
]
}
],
"insSettlementRs": [
{
"row": [
{
"name": "ON_FILE",
"value": "0",
"link": {
"exists": false,
"linkType": null,
"linkId": null
}
}
]
}
],
"dstrOptionRs": [
{
"row": [
{
"name": "DSTR_OPTION",
"value": "1",
"link": {
"exists": false,
"linkType": null,
"linkId": null
}
},
{
"name": "HELPLINE_AREA_CD",
"value": "818",
"link": {
"exists": false,
"linkType": null,
"linkId": null
}
},
{
"name": "HELPLINE_PHN_NR",
"value": "5055511",
"link": {
"exists": false,
"linkType": null,
"linkId": null
}
}
]
}
],
"correspondenceOutRs": [
{
"row": [
{
"name": "SUMMARY_CD_TX",
"value": "SUPER,SEAL,APPR_INTRO,APPROVAL,ECNA",
"link": {
"exists": false,
"linkType": null,
"linkId": null
}
}
]
},
{
"row": [
{
"name": "SUMMARY_CD_TX",
"value": "9069CL,SEAL",
"link": {
"exists": false,
"linkType": null,
"linkId": null
}
},
{
"name": "ASTN_PGM_CD",
"value": "MISC",
"link": {
"exists": false,
"linkType": null,
"linkId": null
}
},
{
"name": "GENERATED_DT",
"value": "2020-09-03 14:08:10.0",
"link": {
"exists": false,
"linkType": null,
"linkId": null
}
}
]
}
],
"statePhoneRs": [],
"insAssistanceRs": [
{
"row": [
{
"name": "DOC_ID",
"value": "",
"link": {
"exists": false,
"linkType": null,
"linkId": null
}
},
{
"name": "RGSN_ID",
"value": "370002900",
"link": {
"exists": false,
"linkType": null,
"linkId": null
}
}
]
}
]
}
and here's what I have working so far:
class App extends React.Component {
constructor(props) {
super(props);
this.setState = {
data: []
};
}
componentDidMount() {
fetch("https://demo3531217.mockable.io/getRegistrationData")
.then((res) => res.json())
.then((res) => {
const responseData = this.getPayloadObject(res);
this.setState({
data: responseData
});
})
.catch((error) => console.error(error));
}
getPayloadObject = (action) => {
console.log(action);
Object.keys(action).forEach((key) => {
if (typeof action[key] === "object") {
const payload = action[key];
let result = _.map(
payload,
(data, i) => {
const row = data["row"];
const rowData = _.map(row, (item) => {
return {
name: item.name,
value: item.value
};
});
console.log("rowData ", rowData);
},
[]
);
return result;
}
});
};
render() {
return (
<div>
<div>
<h1>Section 1</h1>
</div>
<div>
<h1>Section 2</h1>
</div>
</div>
);
}
}
if I wanted to display certain data for specific section how do I so in my page? Can someone please help?
link for sandbox can be found here: https://codesandbox.io/s/vibrant-sid-i140l?file=/src/App.js:75-1304
Let's try breaking the state into multiple sections. Something like this.
constructor(props) {
super(props);
this.state = {
dstrSpecificHelpRs: [],
rgstInfoRs: [],
insSettlementRs: [],
dstrOptionRs: [],
correspondenceOutRs: [],
statePhoneRs: [],
insAssistanceRs: []
};
}
Then, let's deconstruct the API response and set individual items in the state.
componentDidMount() {
fetch("https://demo3531217.mockable.io/getRegistrationData")
.then((res) => res.json())
.then((res) => {
// const responseData = this.getPayloadObject(res);
const {
dstrSpecificHelpRs,
rgstInfoRs,
insSettlementRs,
dstrOptionRs,
correspondenceOutRs,
statePhoneRs,
insAssistanceRs
} = res;
this.setState({
dstrSpecificHelpRs: dstrSpecificHelpRs,
rgstInfoRs: rgstInfoRs,
insSettlementRs: insSettlementRs,
dstrOptionRs: dstrOptionRs,
correspondenceOutRs: correspondenceOutRs,
statePhoneRs: statePhoneRs,
insAssistanceR: insAssistanceRs
});
})
.catch((error) => console.error(error));
}
Now all you have to do is find a way to loop through individual items in the state. Something like this
render() {
const dstrSpecificHelpRs = this.state.dstrSpecificHelpRs.map(row => row["row"]);
console.log("Sample = ", sample);
return (
<div>
<div>
<h1>Section 1</h1>
<div>
{dstrSpecificHelpRs.map(item => item.map(key => <p>{key.name}</p>))}
</div>
</div>
<div>
<h1>Section 2</h1>
</div>
</div>
);
}
This is by no means a perfect solution though. If you could change the response model, that would have been sweet!.
sorry but I dont understand well refs. I've been reading react doc but I dont know how create an array of refs and access a node when check item.
My idea is ref all Tree Nodes and when call onCheck access to current ref and change property checked to a different status to current item, his parent items and his child items using javascript using childNodes, parentNode, nextSibling and previousSibling.
onCheck = (checkedKeys, event) => {
how can get node checked??? it always returns last node
const node = this.myRef.current;
console.log(node)
}
componentDidMount() {
// I have to do something here???
}
render() {
const loop = (data) => {
return data.map((item) => {
if (item.children && item.children.length) {
return <TreeNode ref={this.myRef} title={item.name} key={item.key} checked={item.checked} >{loop(item.children)}</TreeNode>;
}
return (
<TreeNode ref={this.myRef} title={item.name} key={item.key} isLeaf={item.isLeaf} checked={item.checked} />
);
});
};
return (
<div className="draggable-container">
<Tree
// Expand
expandedKeys={this.state.expandedKeys}
onExpand={this.onExpand} autoExpandParent={this.state.autoExpandParent}
// Draggable
draggable
onDragStart={this.onDragStart}
onDragEnter={this.onDragEnter}
onDrop={this.onDrop}
// Select && Check
onSelect={this.onSelect}
checkable onCheck={this.onCheck} checkedKeys={this.state.checkedKeys} >
{ loop(this.state.treeData) }
</Tree>
</div>
);
}
Instead of using React.createRef, you can make use of ref callback like
constructor(props) {
super(props);
this.myRef = {};
}
onCheck = (checkedKeys, event) => {
how can get node checked??? it always returns last node
const checkedKey = // get the checkedKey here, if its a array, loop and use
const node = this.myRef[checkedKey];
console.log(node)
}
render() {
const loop = (data) => {
return data.map((item, index) => {
if (item.children && item.children.length) {
return <TreeNode ref={(ref) => this.myRef[key] = ref} title={item.name} key={item.key} checked={item.checked} >{loop(item.children)}</TreeNode>;
}
return (
<TreeNode ref={(ref) => this.myRef[key] = ref} title={item.name} key={item.key} isLeaf={item.isLeaf} checked={item.checked} />
);
});
};
return (
<div className="draggable-container">
<Tree
// Expand
expandedKeys={this.state.expandedKeys}
onExpand={this.onExpand} autoExpandParent={this.state.autoExpandParent}
// Draggable
draggable
onDragStart={this.onDragStart}
onDragEnter={this.onDragEnter}
onDrop={this.onDrop}
// Select && Check
onSelect={this.onSelect}
checkable onCheck={this.onCheck} checkedKeys={this.state.checkedKeys} >
{ loop(this.state.treeData) }
</Tree>
</div>
);
}
This is my solution, because I had to modify treeData:
onCheck = (checkedKeys, event) => {
// console.log(this.treeData);
const checkedKey = event.node.props.eventKey;
this.updateItemChecked(checkedKey);
this.setState({ checkedKeys: checkedKeys }, () => {
this.props.parentTree(this.treeData);
});
}
updateItemChecked = (key) => {
var result = getNodeByKey(key, this.treeData);
if (result.type.localeCompare('folder') !== 0) {
if (result.checked === true ) {
result.checked = false;
} else {
result.checked = true;
}
} else {
this.checkIfFolderHasItem(result);
}
}
checkIfFolderHasItem = (result) => {
if ( result.children && result.children.length > 0) {
result.children.forEach( (item) => {
if (item.type.localeCompare('folder') !== 0) {
this.updateItemChecked(item.key);
} else {
this.checkIfFolderHasItem(item);
}
});
}
}
// Expand
onExpand = (expandedKeys, event) => {
// console.log('onExpand', expandedKeys);
const checkedKey = event.node.props.eventKey;
this.updateFolderExpanded(checkedKey);
this.setState({ expandedKeys, autoExpandParent: false }, ()=> {
this.props.parentTree(this.treeData);
});
}
updateFolderExpanded = (key) => {
var result = getNodeByKey(key, this.treeData);
if (result.type.localeCompare('folder') === 0) {
if (result.expanded === true ) {
result.expanded = false;
} else {
result.expanded = true;
}
}
}
render() {
const loop = (data) => {
return data.map((item) => {
if (item.children && item.children.length) {
return <TreeNode title={item.name} key={item.key} checked={item.checked} >{loop(item.children)}</TreeNode>;
}
return (
<TreeNode title={item.name} key={item.key} isLeaf={item.isLeaf} checked={item.checked} />
);
});
};
return (
<div className="draggable-container">
{
// (this.state.showModal) ? <TreeModal show={this.state.showModal} info={this.state.selected} treeData={this.state.treeData} parentTreeModal={this.doParentTreeModal} /> : null
}
<Tree
// Expand
expandedKeys={this.state.expandedKeys}
onExpand={this.onExpand} autoExpandParent={this.state.autoExpandParent}
// Draggable
draggable
onDragStart={this.onDragStart}
onDragEnter={this.onDragEnter}
onDrop={this.onDrop}
// Select && Check
onSelect={this.onSelect}
checkable onCheck={this.onCheck} checkedKeys={this.state.checkedKeys} >
{ loop(this.state.treeData) }
</Tree>
</div>
);
}
JSON Example:
[
{
"name": "Capas1",
"key": "0-23",
"isLeaf": false,
"type": "folder",
"expanded": true,
"children": [{
"name": "sectores",
"key": "0-20",
"isLeaf": true,
"type": "layer",
"checked": true
},
{
"name": "distribucion",
"key": "0-22",
"isLeaf": true,
"type": "layer",
"checked": false
}]
},
{
"name": "Nueva Carpeta0",
"key": "0-624",
"isLeaf": false,
"type": "folder",
"expanded": false,
"checked": false
},
{
"name": "Nueva Carpeta1",
"key": "0-625",
"isLeaf": false,
"type": "folder",
"expanded": true,
"children": [{
"name": "Nueva Carpeta2",
"key": "0-629",
"isLeaf": false,
"type": "folder",
"expanded": true,
"children": [{
"name": "Nueva Carpeta3",
"key": "0-623",
"isLeaf": false,
"type": "folder",
"expanded": true,
"children": [{
"name": "distribucion33",
"key": "0-99",
"isLeaf": true,
"type": "layer",
"checked": true
}]
}]
}]
},
{
"name": "sectores1",
"key": "0-27",
"isLeaf": true,
"type": "layer",
"checked": true
},
{
"name": "sectores12",
"key": "0-89",
"isLeaf": true,
"type": "layer",
"checked": false
},
{
"name": "Capas 2",
"key": "0-588",
"isLeaf": false,
"type": "folder",
"expanded": false,
"children": [{
"name": "Capas 3",
"key": "0-589",
"isLeaf": false,
"type": "folder",
"expanded": false,
"children": [{
"name": "Prueba",
"key": "0-36",
"isLeaf": true,
"type": "layer",
"checked": false
}]
}]
}
]
I am using jsTree and I plan to centralize how all the commands are executed/passed to jsTree so that I can perform some checks before executing these commands.
I am able to invoke commands against the tree but I am finding it hard to pass more than one arguments to the command.
If you refer the below screen shot then it shows that I am trying to pass three arguments to the command.
But then when it reaches to jsTree it is of course treated as an array, I would like to pass them as arguments rather then an array.
Code snippet to help understand question better.
var Demo = function() {
var $tree = $("#jstree");
var isTreeReady = false;
function execute_command(command) {
if (typeof command === 'undefined') {
alert("command not passed to execute_command();");
return;
}
if (isTreeReady) {
if (arguments.length === 1) {
return $tree.jstree(command);
} else {
/*This is where I need help*/
/*It works fine if there is only one argument*/
/*But when I try to pass multiple arguments jstree sees them as an array instead of separate arguments*/
var args = [];
for (var i = 1; i < arguments.length; i++) {
args.push(arguments[i]);
}
//I have also tried
//var args = Array.prototype.slice.call(arguments, 1)
return $tree.jstree(command, args);
}
} else {
alert('Tree is not ready for command [' + command + ']');
}
}
function select_node(event, selected) { //triggered when an node is selected
}
function ready() {
isTreeReady = true;
}
return {
Initialize: function() {
$tree.on("ready.jstree", ready)
.on("select_node.jstree", select_node)
.jstree({
'core': {
'data': [{
"id": "0",
"parent": "#",
"text": "Home",
"state": {
"opened": true,
"selected": true,
"disabled": false
},
"li_attr": {
"class": "",
"disabled": ""
}
}, {
"id": "78612",
"parent": "0",
"text": "Getting started",
"state": {
"opened": false,
"selected": false,
"disabled": false
},
"li_attr": {
"class": "active disable",
"disabled": "disabled"
}
}, {
"id": "78617",
"parent": "0",
"text": "What's new",
"state": {
"opened": false,
"selected": false,
"disabled": false
},
"li_attr": {
"class": "",
"disabled": ""
}
}, {
"id": "78614",
"parent": "0",
"text": "2 minute video tutorials",
"state": {
"opened": false,
"selected": false,
"disabled": false
},
"li_attr": {
"class": "",
"disabled": ""
}
}, {
"id": "78615",
"parent": "0",
"text": "How-to papers",
"state": {
"opened": false,
"selected": false,
"disabled": false
},
"li_attr": {
"class": "",
"disabled": ""
}
}, {
"id": "78613",
"parent": "0",
"text": "Reference",
"state": {
"opened": false,
"selected": false,
"disabled": false
},
"li_attr": {
"class": "",
"disabled": ""
}
}, {
"id": "78616",
"parent": "0",
"text": "Hands on exercises",
"state": {
"opened": false,
"selected": false,
"disabled": false
},
"li_attr": {
"class": "",
"disabled": ""
}
}],
"themes": {
"variant": "large",
"dots": false,
"icons": false,
},
"multiple": false,
}
});
},
SelectNode: function(contentID) {
if (typeof contentID !== 'undefined' && execute_command('is_selected', "#" + contentID) === false) {
execute_command('deselect_all', false);
execute_command('select_node', "#" + contentID);
}
},
GetSelectedNodePath: function() {
return execute_command('get_path', '#' + execute_command('get_selected')[0], ' -> ', false); //get_path takes three arguments
}
}
}();
Demo.Initialize();
<link href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" integrity="sha256-7s5uDGW3AHqw6xtJmNNtr+OBRJUlgkNJEo78P4b0yRw= sha512-nNo+yCHEyn0smMxSswnf/OnX6/KwJuZTlNZBjauKhTK0c+zT+q5JOCx0UFhXQ6rJR9jg6Es8gPuD2uZcYDLqSw=="
crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
<div>
<label>Works:</label>
<input type="button" class="btn btn-default" value="Select 'Getting Started'" onclick="Demo.SelectNode(78612)" />
<br />
<label>Does NOT work:</label>
<input type="button" class="btn btn-default" value="Get Selected Node Path" onclick="alert(Demo.GetSelectedNodePath())" />
</div>
<div id="jstree">
</div>
You can use apply() to pass an array of arguments to a function. You'll need to include command in the array, as well.
args.splice(0, 0, command);
return $tree.jstree.apply( $tree, args );
var Demo = function() {
var $tree = $("#jstree");
var isTreeReady = false;
function execute_command(command) {
if (typeof command === 'undefined') {
console.log("command not passed to execute_command();");
return;
}
if (isTreeReady) {
return $tree.jstree.apply($tree, arguments);
} else {
console.log('Tree is not ready for command [' + command + ']');
}
}
function select_node(event, selected) { //triggered when an node is selected
}
function ready() {
isTreeReady = true;
}
return {
Initialize: function() {
$tree.on("ready.jstree", ready)
.on("select_node.jstree", select_node)
.jstree({
'core': {
'data': [{
"id": "0",
"parent": "#",
"text": "Home",
"state": {
"opened": true,
"selected": true,
"disabled": false
},
"li_attr": {
"class": "",
"disabled": ""
}
}, {
"id": "78612",
"parent": "0",
"text": "Getting started",
"state": {
"opened": false,
"selected": false,
"disabled": false
},
"li_attr": {
"class": "active disable",
"disabled": "disabled"
}
}, {
"id": "78617",
"parent": "0",
"text": "What's new",
"state": {
"opened": false,
"selected": false,
"disabled": false
},
"li_attr": {
"class": "",
"disabled": ""
}
}, {
"id": "78614",
"parent": "0",
"text": "2 minute video tutorials",
"state": {
"opened": false,
"selected": false,
"disabled": false
},
"li_attr": {
"class": "",
"disabled": ""
}
}, {
"id": "78615",
"parent": "0",
"text": "How-to papers",
"state": {
"opened": false,
"selected": false,
"disabled": false
},
"li_attr": {
"class": "",
"disabled": ""
}
}, {
"id": "78613",
"parent": "0",
"text": "Reference",
"state": {
"opened": false,
"selected": false,
"disabled": false
},
"li_attr": {
"class": "",
"disabled": ""
}
}, {
"id": "78616",
"parent": "0",
"text": "Hands on exercises",
"state": {
"opened": false,
"selected": false,
"disabled": false
},
"li_attr": {
"class": "",
"disabled": ""
}
}],
"themes": {
"variant": "large",
"dots": false,
"icons": false,
},
"multiple": false,
}
});
},
SelectNode: function(contentID) {
if (typeof contentID !== 'undefined' && execute_command('is_selected', "#" + contentID) === false) {
execute_command('deselect_all', false);
execute_command('select_node', "#" + contentID);
}
},
GetSelectedNodePath: function() {
return execute_command('get_path', '#' + execute_command('get_selected')[0], ' -> ', false); //get_path takes three arguments
}
}
}();
Demo.Initialize();
<link href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" integrity="sha256-7s5uDGW3AHqw6xtJmNNtr+OBRJUlgkNJEo78P4b0yRw= sha512-nNo+yCHEyn0smMxSswnf/OnX6/KwJuZTlNZBjauKhTK0c+zT+q5JOCx0UFhXQ6rJR9jg6Es8gPuD2uZcYDLqSw=="
crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
<div>
<label>Works:</label>
<input type="button" class="btn btn-default" value="Select 'Getting Started'" onclick="Demo.SelectNode(78612)" />
<br />
<label>Does NOT work:</label>
<input type="button" class="btn btn-default" value="Get Selected Node Path" onclick="console.log(Demo.GetSelectedNodePath())" />
</div>
<div id="jstree">
</div>