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>
Related
I have a collection called dish-category which contains many dishes, and a dish collection that contains many dish-options (another collection).
the list of dishes from each dish-category is available in the API but the nested collection of dish options from each dish is not available on strapi.
the following are the settings for my models:
dish-category.settings.json:
{
"kind": "collectionType",
"collectionName": "dish_categories",
"info": {
"name": "DishCategory",
"description": ""
},
"options": {
"increments": true,
"timestamps": true,
"draftAndPublish": true
},
"pluginOptions": {},
"attributes": {
"Name": {
"type": "string"
},
"Description": {
"type": "text"
},
"dishes": {
"collection": "dish",
"via": "dish_category"
}
}
}
dish.settings.json:
{
"kind": "collectionType",
"collectionName": "dishes",
"info": {
"name": "Dish",
"description": ""
},
"options": {
"increments": true,
"timestamps": true,
"draftAndPublish": true
},
"pluginOptions": {},
"attributes": {
"Name": {
"type": "string"
},
"Description": {
"type": "text"
},
"Total": {
"type": "decimal",
"min": 0,
"required": false,
"default": 0
},
"dish_categories": {
"collection": "dish-category"
},
"dish_options": {
"collection": "dish-option",
"via": "dish"
},
"dish_category": {
"via": "dishes",
"model": "dish-category"
}
}
}
dish-option.settings.json:
{
"kind": "collectionType",
"collectionName": "dish_options",
"info": {
"name": "DishOption",
"description": ""
},
"options": {
"increments": true,
"timestamps": true,
"draftAndPublish": true
},
"pluginOptions": {},
"attributes": {
"Name": {
"type": "string"
},
"Price": {
"type": "decimal",
"min": 0,
"default": 0
},
"dish": {
"via": "dish_options",
"model": "dish"
}
}
}
on the dish-category/controllers/dish-category.js file I tried populating the attribute:
'use strict';
/**
* Read the documentation (https://strapi.io/documentation/developer-docs/latest/development/backend-customization.html#core-controllers)
* to customize this controller
*/
module.exports = {
async find(params, populate){
return strapi.query('dish-category').find(params, ["dishes","dish.dish_options"]);
}
};
I am having trouble displaying nested relations with multiple values, I have tried looking up solutions online, I came across this thread https://forum.strapi.io/t/simple-nested-array-issue/1045/4 but the solution doesn't work for me and it seems like the link to the example is no longer available.
I'm a complete noob in JS since I have been coding in PHP always so here comes the noobs question.
I have a date picker and it works fine but the problem is that when a date has been selected it doesn't update the value of the corresponding input field. the script apparently works using the class name so there will be multiple inputs declared as the date picker using the same class on the same page but I have to update the value of the input fields individually meaning if the user selects 11/28/2020 for input1 only input1 updates with the value, not the other inputs that have been declared as the date picker by the same class.
here is the date picker initialization code I'm using:
<script>
$('.persian-date').persianDatepicker({
"inline": false,
"format": "YYYY/MM/DD",
"viewMode": "day",
"initialValue": false,
"minDate": null,
"maxDate": null,
"autoClose": true,
"position": "auto",
"altFormat": "",
"altField": "",
"onlyTimePicker": false,
"onlySelectOnDate": false,
"calendarType": "persian",
"inputDelay": 800,
"observer": true,
"calendar": {
"persian": {
"locale": "fa",
"showHint": true,
"leapYearMode": "algorithmic"
},
"gregorian": {
"locale": "en",
"showHint": true
}
},
"navigator": {
"enabled": true,
"scroll": {
"enabled": true
},
"text": {
"btnNextText": "<",
"btnPrevText": ">"
}
},
"toolbox": {
"enabled": false,
"calendarSwitch": {
"enabled": false,
"format": "MMMM"
},
"todayButton": {
"enabled": false,
"text": {
"fa": "امروز",
"en": "Today"
}
},
"submitButton": {
"enabled": false,
"text": {
"fa": "تایید",
"en": "Submit"
}
},
"text": {
"btnToday": "امروز"
}
},
"timePicker": {
"enabled": false,
"step": 1,
"hour": {
"enabled": false,
"step": null
},
"minute": {
"enabled": false,
"step": null
},
"second": {
"enabled": false,
"step": null
},
"meridian": {
"enabled": false
}
},
"dayPicker": {
"enabled": true,
"titleFormat": "YYYY MMMM"
},
"monthPicker": {
"enabled": true,
"titleFormat": "YYYY"
},
"yearPicker": {
"enabled": true,
"titleFormat": "YYYY"
}
});
</script>
I am trying to change the values of my nested object by using the data from another object but for some reason it is never setting the value. If i put static text in there it works but just doesn't work if the data from my other object
const projectFormTypes = [
{
"type": "Theatrical",
"sections" : {
"project": {
"fields": [
{
"label": "Project Title",
"name": "title",
"required": true,
"type": "textbox",
"visible": true,
'value': ''
},
]
},
"participants": {
"fields": [
{
"label": "First Name",
"name": "firstName",
"required": false,
"type": "textbox",
"visible": true,
"value": "first name 1"
},
]
},
"earnings": {
"fields": [
{
"label": "Compensation Amount",
"name": "wages",
"prefix": "$",
"required": false,
"type": "textbox",
"visible": true,
"value": 100000
},
]
}
}
},
]
const projectData = [{"fileDetailRecordId":3,"detailRecordId":"341697P3","signatoryName":"comp 2","signatoryId":"comp sag","contract":"Theatrical","sagId":"aftra 2","title":"Project 2","principalPhotoDate":"2019-12-13","madeFor":"Interactive Media","ppe":"2019-12-13","sessionDateTv":"2019-12-13","marketPaid":"In-Flight","commercialTitle":"Project 2","sessionDate":"2019-12-13","useType":"Clip Use","ssn":"987654","firstName":"test","middleName":"test","lastName":"test","loanOutNumber":"45687","loanOutName":"54854","performerType":"Background","performerCategory":"Dancer","paymentType":"Payroll","wages":"852963","subjectToPh":"852963","phContrib":"8529363","contribPercent":"10.0000","detailStatus":"DRAFT","earningsFileId":341697,"detailStatusId":{"parentRefId":32,"activeFlag":true,"refCode":"detail_processing","refValue":"Processing","comments":"detail is being processed","createdBy":"NS","createdAt":"2018-10-04T01:33:18.000+0000","updatedBy":"NS","updatedAt":"2019-06-19T17:45:39.000+0000","cmsProcessEfDetailLogList":[],"referenceId":33,"cmsEarningsFileList":[],"cmsEarningsFileList1":[]},"createdBy":"UI","updatedBy":"UI"},{"fileDetailRecordId":1,"detailRecordId":"341697P1","signatoryName":"comp name","signatoryId":"comp aftra","contract":"Theatrical","sagId":"aftra id","title":"Project 1","principalPhotoDate":"2019-12-13","madeFor":"Foreign TV","ppe":"2019-12-13","sessionDateTv":"2019-12-13","marketPaid":"Network","commercialTitle":"Project 1","sessionDate":"2019-12-13","useType":"Phono Conversation","ssn":"456","firstName":"first name 1","middleName":"middle name 1","lastName":"last name 1","loanOutNumber":"456","loanOutName":"456","performerType":"AFTRA Staff","performerCategory":"Actor","paymentType":"Deferred","wages":"500","subjectToPh":"500","phContrib":"500","contribPercent":"1000.0000","detailStatus":"DRAFT","earningsFileId":341697,"detailStatusId":{"parentRefId":32,"activeFlag":true,"refCode":"detail_processing","refValue":"Processing","comments":"detail is being processed","createdBy":"NS","createdAt":"2018-10-04T01:33:18.000+0000","updatedBy":"NS","updatedAt":"2019-06-19T17:45:39.000+0000","cmsProcessEfDetailLogList":[],"referenceId":33,"cmsEarningsFileList":[],"cmsEarningsFileList1":[]},"createdBy":"UI","updatedBy":"UI"},{"fileDetailRecordId":2,"detailRecordId":"341697P2","signatoryName":"comp name","signatoryId":"comp aftra","contract":"Theatrical","sagId":"aftra id","title":"Project 1","principalPhotoDate":"2019-12-13","madeFor":"Foreign TV","ppe":"2019-12-13","sessionDateTv":"2019-12-13","marketPaid":"Home Video","commercialTitle":"Project 1","sessionDate":"2019-12-13","useType":"Clip Use","ssn":"123","firstName":"last name 2","middleName":"last name 2","lastName":"last name 2","loanOutNumber":"456","loanOutName":"456","performerType":"AFTRA Staff","performerCategory":"Dance Coreographer","paymentType":"Deferred","wages":"800","subjectToPh":"800","phContrib":"800","contribPercent":"50.0000","detailStatus":"DRAFT","earningsFileId":341697,"detailStatusId":{"parentRefId":32,"activeFlag":true,"refCode":"detail_processing","refValue":"Processing","comments":"detail is being processed","createdBy":"NS","createdAt":"2018-10-04T01:33:18.000+0000","updatedBy":"NS","updatedAt":"2019-06-19T17:45:39.000+0000","cmsProcessEfDetailLogList":[],"referenceId":33,"cmsEarningsFileList":[],"cmsEarningsFileList1":[]},"createdBy":"UI","updatedBy":"UI"}]
const pp = Object.keys(projectFormTypes).forEach(function(r) {
for(let key in projectFormTypes[r].sections){
for(let o in projectFormTypes[r].sections[key].fields){
projectFormTypes[r].sections[key].fields[o].value = projectData[0][o.name];
}
}
});
console.log('result', projectFormTypes);
projectData[0][o.name]
should be
projectData[0][projectFormTypes[r].sections[key].fields[o].name]
o is the index in the fields array, and numbers don't have a name property. You want the name of the current element of the for loop.
But the code is simplified and less error prone if you use forEach() for all the nested loops.
const projectFormTypes = [{
"type": "Theatrical",
"sections": {
"project": {
"fields": [{
"label": "Project Title",
"name": "title",
"required": true,
"type": "textbox",
"visible": true,
'value': ''
}, ]
},
"participants": {
"fields": [{
"label": "First Name",
"name": "firstName",
"required": false,
"type": "textbox",
"visible": true,
"value": "first name 1"
}, ]
},
"earnings": {
"fields": [{
"label": "Compensation Amount",
"name": "wages",
"prefix": "$",
"required": false,
"type": "textbox",
"visible": true,
"value": 100000
}, ]
}
}
}, ]
const projectData = [{"fileDetailRecordId":3,"detailRecordId":"341697P3","signatoryName":"comp 2","signatoryId":"comp sag","contract":"Theatrical","sagId":"aftra 2","title":"Project 2","principalPhotoDate":"2019-12-13","madeFor":"Interactive Media","ppe":"2019-12-13","sessionDateTv":"2019-12-13","marketPaid":"In-Flight","commercialTitle":"Project 2","sessionDate":"2019-12-13","useType":"Clip Use","ssn":"987654","firstName":"test","middleName":"test","lastName":"test","loanOutNumber":"45687","loanOutName":"54854","performerType":"Background","performerCategory":"Dancer","paymentType":"Payroll","wages":"852963","subjectToPh":"852963","phContrib":"8529363","contribPercent":"10.0000","detailStatus":"DRAFT","earningsFileId":341697,"detailStatusId":{"parentRefId":32,"activeFlag":true,"refCode":"detail_processing","refValue":"Processing","comments":"detail is being processed","createdBy":"NS","createdAt":"2018-10-04T01:33:18.000+0000","updatedBy":"NS","updatedAt":"2019-06-19T17:45:39.000+0000","cmsProcessEfDetailLogList":[],"referenceId":33,"cmsEarningsFileList":[],"cmsEarningsFileList1":[]},"createdBy":"UI","updatedBy":"UI"},{"fileDetailRecordId":1,"detailRecordId":"341697P1","signatoryName":"comp name","signatoryId":"comp aftra","contract":"Theatrical","sagId":"aftra id","title":"Project 1","principalPhotoDate":"2019-12-13","madeFor":"Foreign TV","ppe":"2019-12-13","sessionDateTv":"2019-12-13","marketPaid":"Network","commercialTitle":"Project 1","sessionDate":"2019-12-13","useType":"Phono Conversation","ssn":"456","firstName":"first name 1","middleName":"middle name 1","lastName":"last name 1","loanOutNumber":"456","loanOutName":"456","performerType":"AFTRA Staff","performerCategory":"Actor","paymentType":"Deferred","wages":"500","subjectToPh":"500","phContrib":"500","contribPercent":"1000.0000","detailStatus":"DRAFT","earningsFileId":341697,"detailStatusId":{"parentRefId":32,"activeFlag":true,"refCode":"detail_processing","refValue":"Processing","comments":"detail is being processed","createdBy":"NS","createdAt":"2018-10-04T01:33:18.000+0000","updatedBy":"NS","updatedAt":"2019-06-19T17:45:39.000+0000","cmsProcessEfDetailLogList":[],"referenceId":33,"cmsEarningsFileList":[],"cmsEarningsFileList1":[]},"createdBy":"UI","updatedBy":"UI"},{"fileDetailRecordId":2,"detailRecordId":"341697P2","signatoryName":"comp name","signatoryId":"comp aftra","contract":"Theatrical","sagId":"aftra id","title":"Project 1","principalPhotoDate":"2019-12-13","madeFor":"Foreign TV","ppe":"2019-12-13","sessionDateTv":"2019-12-13","marketPaid":"Home Video","commercialTitle":"Project 1","sessionDate":"2019-12-13","useType":"Clip Use","ssn":"123","firstName":"last name 2","middleName":"last name 2","lastName":"last name 2","loanOutNumber":"456","loanOutName":"456","performerType":"AFTRA Staff","performerCategory":"Dance Coreographer","paymentType":"Deferred","wages":"800","subjectToPh":"800","phContrib":"800","contribPercent":"50.0000","detailStatus":"DRAFT","earningsFileId":341697,"detailStatusId":{"parentRefId":32,"activeFlag":true,"refCode":"detail_processing","refValue":"Processing","comments":"detail is being processed","createdBy":"NS","createdAt":"2018-10-04T01:33:18.000+0000","updatedBy":"NS","updatedAt":"2019-06-19T17:45:39.000+0000","cmsProcessEfDetailLogList":[],"referenceId":33,"cmsEarningsFileList":[],"cmsEarningsFileList1":[]},"createdBy":"UI","updatedBy":"UI"}]
projectFormTypes.forEach(function(type) {
Object.values(type.sections).forEach(function(section) {
section.fields.forEach(function(field) {
field.value = projectData[0][field.name];
});
});
});
console.log('result', projectFormTypes);
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
}]
}]
}
]
I need to open the edit form for a particular record in a jqgrid from another page.
Do I need to capture the load event in jqgrid then pull the id out of the URL and manually select the record or is there an easier way?
Due to paging the record is not likely to be on the page at all when it loads.
The key column is "BLS_ID"
here is the code that opens the page:
function OpenInNewTab()
{
var bls_id = '#BLS.bls_id#';
var win=window.open('#URLFOR(controller="realty", action="rpi_data_sheet_view")#?template=RPI_Deleted_BLS&BLS_ID='+bls_id, '_blank');
win.focus();
}
here is the code from the jqgrid page:
<cfoutput>
<script type="text/javascript" src="includes/js/jquery.BlockUI.js"></script>
<script type="text/javascript">
// called by grid-wrapper when form is shown
function setup_archived_installations_table_form(form) {
var form = $(form);
form.find('##AREA').hfds('disable');
form.find('##INST_NAME').hfds('disable');
form.find('##BLS_NO').hfds('disable');
form.find('##SUB_NO').hfds('disable');
form.find('##TRANS_DESCRIP_2').hfds('disable');
form.find('##USE_DESC').hfds('disable');
form.find('##DET_DESC').hfds('disable');
form.find('##RP_CODE').hfds('disable');
form.attr("permissionsObject", "b_bls_disposition");
applyFormPermissions();
//form.find('select').width(160).hfds('wideSelectFix');
$('##DISP_DATE').addClass("date-picker");
setup_form_elements();
// disable everything but trans_code
//form.find('input, select[name != "TRANS_CODE"]').hfds('disable');
}
$(function() {
$('##disposition_btn').click(function() {
var modal = $('##disposition_modal');
var selected = $('##archived_installations_table').jqGrid('getGridParam', 'selrow');
modal.load('#URLFor(action="disposition_form", params="bls_id=")#' + selected, function() {
$(this).find('.date-picker').addClass("date-picker");
modal.dialog({
title: 'Disposition-related Fields',
modal: true,
width: 500
});
});
});
$('##disposition_form form').live('submit', function(e) {
var self = $(this);
var url = $(this).attr('action');
var modal = $('##disposition_modal');
modal.block({message: ''});
$.ajax({
url: self.attr('action'),
data: self.serialize(),
type: 'POST',
success: function() {
$('##archived_installations_table').trigger('reloadGrid');
},
error: function() {
alert('Failed to file disposition');
},
complete: function() {
modal.unblock();
modal.dialog('close');
}
});
/*
*$.post(url, $(this).serialize(), function(data) {
* $('##building_datasheet_table').trigger('reloadGrid');
* modal.unblock();
* modal.dialog('close');
*});
*/
return false;
})
});
</script>
<h1 class="title">Deleted Buildings, Structures, Lands</h1>
<cfsavecontent variable="BuildingTableDef">
{
"height": "auto",
"autowidth" : true,
"shrinkToFit" : false,
"gridview": true,
"url":"#URLFor(action="jqGrid_get", params="modelName=BLS&customSQLMethod=BLSDatasheet(0,1)")#",
"editurl": "#URLFor(action='saveDeletedBLS')#",
"datatype": "json",
"rowNum": "10",
"pager": "##archived_installations_pager",
"jsonReader": {
"root": "ROWS",
"page": "PAGE",
"total": "TOTAL",
"record": "RECORDS",
"repeatitems": false
},
"colModel":[
{ "name" : "AREA", "width": "100", "label": "Area", "editable": true, "edittype": "select", "stype":"select", "formatter": "select", "editoptions": {
"value": "#jqGridValueString(areas, "area_code", "area_name")#"
}},
{ "name" : "INST_NO", "width": "75" },
{ "name" : "INST_NAME", "editable": true },
{ "name" : "PROP_TYPE", "label": "Prop Type", "formatter": "select", "editable": false, "edittype": "select", "stype":"select", "editoptions": {
"value": "#jqGridValueString(prop_types, "prop_type", "prop_desc")#"
}},
{ "name" : "STATE", "width": "50" },
{ "name" : "COUNTY" },
{ "name" : "CITY_TOWN" },
{ "name" : "BLS_NO", "width": "75", "editable": true },
{ "name" : "SUB_NO", "width": "75", "editable": true },
{ "name" : "TRANS_CODE", "width": "75", "editable": true, "edittype": "select", "search": false, "editoptions": {
"value": "#jqGridValueString(trans_codes, "trans_code2", "trans_descrip2")#"
}},
{ "name" : "TRANS_DESCRIP_2", "label": "Action", "editable": true },
{ "name" : "USE_DESC", "label": "Use Desc", "editable": true, "edittype": "select", "stype": "select", "editoptions": {
"value": "#jqGridValueString(b_use_descs, "use_desc")#"
}},
{ "name" : "DET_DESC", "label": "Detailed Desc", "editable": true },
{ "name" : "RP_CODE", "width": "75", "label": "RP Code", "editable": true },
{ "name" : "GSM", "width": "75", "label": "GSM", "align":"right", "formatter": "number", "formatoptions":{"decimalSeparator":".", "thousandsSeparator": ",", "decimalPlaces": 2, "defaultValue": "0.0"} },
{ "name" : "GSF", "width": "75", "label": "GSF", "align":"right", "formatter": "number", "formatoptions":{"decimalSeparator":".", "thousandsSeparator": ",", "decimalPlaces": 2, "defaultValue": "0.0"} },
{ "name" : "BLDG_CNT", "width": "75", "align":"right", "label": "No Bldgs"},
{ "name" : "STEW_CODE", "label": "Steward", "editable": false, "formatter": "select", "edittype": "select", "stype":"select", "editoptions": {
"value": "#jqGridValueString(stewards, "stew_code", "stew_description")#"
}},
{ "name" : "POTEN_OWNER", "label": "Poten Owner", "editable": false },
{ "name" : "CNTRCT_ARNGMT", "label": "Contract Arrangement", "formatter": "select", "editable": false, "edittype": "select", "stype":"select", "editoptions": {
"value": "#jqGridValueString(contract_arrangements, "cntrct_arngmt", "cntrct_arngmt_desc")#"
}},
{ "name" : "EST_CST_IND", "label": "Est. Cost Indicator", "formatter": "select", "editable": false, "edittype": "select", "stype":"select", "editoptions": {
"value": "#jqGridValueString(est_costs, "code", "code_descr")#"
}},
{ "name" : "NEG_CST_IND", "label": "Neg. Cost Indicator", "formatter": "select", "editable": false, "edittype": "select", "stype":"select", "editoptions": {
"value": "#jqGridValueString(neg_costs, "code", "code_descr")#"
}},
{ "name" : "COND", "label": "Condition", "editable": false, "formatter": "select", "edittype": "select", "stype":"select", "editoptions": {
"value": "#jqGridValueString(conditions, "cond", "cond_desc")#"
}},
{ "name" : "CNSTR", "label": "Construction", "editable": false, "formatter": "select", "edittype": "select", "stype":"select", "editoptions": {
"value": "#jqGridValueString(constructions, "cnstr", "constr_desc")#"
}},
{ "name" : "DISP", "label": "Disposal", "formatter": "select", "editable": false, "edittype": "select", "stype":"select", "editoptions": {
"value": "#jqGridValueString(disposals, "disp", "disp_desc")#"
}},
{ "name" : "STAND", "label": "Standard", "formatter": "select", "editable": false, "edittype": "select", "stype":"select", "editoptions": {
"value": "#jqGridValueString(standards, "stand", "stand_desc")#"
}},
{ "name" : "DISP_METHOD", "label": "Disp Method", "editable": true,
"edittype": "select","formatter": "select","stype":"select",
"editoptions": {
"value": "#jqGridValueString(disp_meths, "disp_code", "disp_desc")#"
}
},
{ "name" : "DISP_DATE", "align": "right", "label": "Disp Date",
"datefmt": "mm/dd/yyyy",
"formatter": "date",
"formatoptions": { "srcformat": "F, d y H:i:s", "newformat": "m/d/Y" },
"editable": true, "editrules": {
"edithidden": true
}},
{ "name" : "DISP_VALUE", "label": "Disp Value", "align":"right", "editable": true, "editrules": {
"edithidden": true, "number": true
},
"formatter": "number",
"formatoptions":{"decimalSeparator":".", "thousandsSeparator": "", "decimalPlaces": 2, "prefix": ""}
},
{ "name" : "NET_PROCEEDS", "label": "Net Proceeds", "align":"right", "editable": true, "editrules": {
"edithidden": true, "number": true
},
"formatter": "number",
"formatoptions":{"decimalSeparator":".", "thousandsSeparator": "", "decimalPlaces": 2, "prefix": ""}
},
{ "name" : "RECIPENT", "label": "Recipient", "editable": true, "editrules": {
"edithidden": true
}},
{ "name" : "ADDRESS_ID2", "width": "50", "label": "Addr ID" },
{ "name" : "BLS_ID", "width": "50", "label": "BLS ID", "key": true }
],
"caption": "Real Property - Buildings"
}
</cfsavecontent>
<cfsavecontent variable="tableEventListeners">
ondblClickRow: function(id){
$('##archived_installations_table').jqGrid('editGridRow', id, {
closeAfterEdit: true,
recreateForm: true,
afterShowForm: function (id) {
if (typeof setup_archived_installations_table_form === 'function') {
setup_archived_installations_table_form(id);
}
$(":input", id).each(function() {
$this = $(this);
$this.data("originalValue", $this.val());
$this.wrap("<div class='jqGridFormField' />");
$this.bind("change keyup", function () {
$wrapper = $(this).parent("div.jqGridFormField");
if ($(this).val() != $(this).data("originalValue"))
$wrapper.addClass("jqGridFormFieldChanged");
else
$wrapper.removeClass("jqGridFormFieldChanged");
});
});
}
});
}
</cfsavecontent>
<cfset perms = model('BLSDisposition').getPermissions()>
<cfsavecontent variable="pagerDef">
{
<cfif ListFindNoCase(perms.objectPermissions, "UPDATE")>
edit: true,
<cfelse>
edit: false,
</cfif>
add: false,
del: false,
search: true,
editfunc: function(id) {
$('##archived_installations_table').jqGrid('editGridRow', id, {
closeAfterEdit: true,
recreateForm: true,
onInitializeForm: function(id) {
if (typeof setup_archived_installations_table_form === 'function') {
setup_archived_installations_table_form(id);
}
}
});
}
},
{}, // default settings for edit
{}, // default settings for add
{}, // delete instead that del:false we need this
{
closeAfterSearch: true,
multipleSearch: true,
multipleGroup: true
}, // search options
{} /* view parameters*/
</cfsavecontent>
#jqGridWrapper(accessibleView=IsDefined("session.user.is_notified") AND IsBoolean(session.user.is_notified) AND session.user.is_notified,
modelName="BLS",
footerRow="true",
filterToolbar="true",
tableID="archived_installations_table",
pagerID="archived_installations_pager",
exportToExcelOption="true",
pagerDefinition="#pagerDef#",
tableDefinitionJSON='#BuildingTableDef#',
tableEventListeners='#tableEventListeners#')#
Got it. Had to add the following to tableEventListeners:
gridComplete: function(){
var blsid=(decodeURIComponent((new RegExp('[?|&]' + 'BLS_ID' + '=' + '([^&;]+?)(&|##|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null);
if(blsid!=null){
$('##archived_installations_table').jqGrid('editGridRow', blsid);
}
},