JStree Async Search - javascript

Whe are busy building a web based app. And we inherited the code where the previous developers used jstree so now the whole site consist out of a tree that uses jstree.
Everything worked even the search on the tree, but then we came across a problem where certain tabs loaded too long because of the tree which was too big.
So we went and made the the tree async / lazy loading which works perfectly but know the problem is that the search doesn't work that well.
Because we made a api for the search which works but it doesn't do the call back after new tree has been loaded.
Can someone help because I've been struggling for 3 days now and its giving me a head ache.
// Tree Search
searchAjaxFunction: function () {
var TreeCustomApiRequest = {
nTreeCustomDesc: document.getElementById("tree_search").value,
nUserId: document.getElementById("TrendUserID").value,
nAccessLevel: document.getElementById("hfTrendAccessLevel").value
}
$.ajax({
type: "POST",
data: JSON.stringify(TreeCustomApiRequest),
url: 'api/TreeCustomSearch.aspx',
success: function (jsonData)
{
Tree.dataJson = jsonData;
// Clear the tree.
//Tree.dataJson = jsonData;
if ($("#tree").jstree()) {
$('#tree').jstree(true).settings.core.data = jsonData;
$('#tree').jstree(true).deselect_node(this);
$('#tree').jstree(true).toggle_node(this);
$('#tree').jstree(true).refresh();
}
},
contentType: "application/json"
});
},
onClickFunctionNode: function(node) {
Tree.treeDivIdSelector.jstree(true).toggle_node(node);
},
pluginsArray: ["search", "checkbox", "types", "json_data","html_data"],
treeMenuContextItems: {},
Init: function(initData) {
Tree.dataJson = initData.dataJson;
Tree.treeDivIdSelector = initData.chartDivId;
Tree.searchDivIdSelector = initData.searchDivId;
var apiUriTree = 'api/TreeCustomChildren.aspx';
Tree.treeDivIdSelector.jstree({
"checkbox": {
"keep_selected_style": true,
"three_state": false
},
"plugins": Tree.pluginsArray,
'core': {
'data': function (node, cb) {
// Fetch tree custom parent nodes
if (node.id === "#") {
cb(Tree.dataJson);
}
else {
var _cb = cb;
//Fetch tree custom Child nodes
var TreeCustomApiRequest = {
nUserId: document.getElementById("TrendUserID").value,
nAccessLevel: document.getElementById("hfTrendAccessLevel").value,
nTreeCustomParentId: node.id
}
function recieveData(data) {
cb(data);
}
$.ajax({
type: "POST",
data: JSON.stringify(TreeCustomApiRequest),
url: apiUriTree,
success: recieveData,
contentType: "application/json"
});
}
},
"themes": {
"icons": false
}
},
"contextmenu": {
items: Tree.pluginsArray.indexOf("contextmenu") > -1 ? Tree.treeMenuContextItems : null
}
});
var tree = Tree.treeDivIdSelector.jstree();
function getNode(sNodeID) {
return tree.get_node(sNodeID);
}
Tree.treeDivIdSelector.on('click', '.jstree-anchor', function(e) {
Tree.onClickFunctionNode(this);
}
);
//Tree.searchDivIdSelector.keyup(Tree.searchFunction);
},
The next code is in the client side......
<script type="text/javascript">
$(document).ready(function () {
var dataJson = <%=sTreeViewJson%>
Tree.Init({ dataJson: dataJson, chartDivId: $("#tree") });
$("#btnSearch").click(function () {
// Do the Ajax search
Tree.searchAjaxFunction();
//var value = document.getElementById("tree_search").value;
//Tree.searchFunction();
})
});
</script>

Thank you Nikolay, it was a stupid mistake from me so what I added was just this to my code:
success: function (jsonData, callback )
{
//Goes back to the Callback with the new search data
Tree.Init({ dataJson: jsonData, chartDivId: $("#tree"), searchDivId: $("#tree_search") });
$('#tree').jstree(true).refresh();
}
So I removed the
$('#tree').jstree(true).settings.core.data = jsonData;
$('#tree').jstree(true).deselect_node(this);
$('#tree').jstree(true).toggle_node(this);
Know it gets my data and refreshes the table with the init function while it has my new data.
Hope this also may help someone = ).

Related

Select2 AJAX not showing "No data found" when no data in database, instead showing search parameter as option to select

I've been working on a project where I've to load select2 option from ajax call.
The code is working fine, except in search result, it always shows search parameter as option. Even if there is no data in database, it still showing it as option, not showing "No data found".
My code is here
$(".search_user").select2({
minimumInputLength: 11,
tags: [],
ajax: {
url: "/user/get_user",
dataType: 'json',
type: "GET",
quietMillis: 250,
data: function (term) {
return {
term: term
};
},
processResults: function (data) {
var Return = [];
for (var i in data.item) {
console.log(data.item[i])
if (data.item[i].id != data.item[i].text) {
Return.push(data.item[i]);
}
}
return {
results: Return
}
}
}
});
my return json is like this
{"item":[{"id":16,"name":"Razin Abid"}]}
My view is looking like this.
Please help me out.
If you using firemodal on stisla
$('#modal-create-promo').click(()=>{
setTimeout(()=>{
$('#fire-modal-1').removeAttr('tabindex');
});
});
$("#modal-create-promo").fireModal({
...
});
It's work for me
Thats because you enable tags option from select2. You need to remove 'Tags:[]' from your code.
visit : https://select2.org/tagging
so, your code should be like this:
$(".search_user").select2({
minimumInputLength: 11,
ajax: {
url: "/user/get_user",
dataType: 'json',
type: "GET",
quietMillis: 250,
data: function (term) {
return {
term: term
};
},
processResults: function (data) {
var Return = [];
for (var i in data.item) {
console.log(data.item[i])
if (data.item[i].id != data.item[i].text) {
Return.push(data.item[i]);
}
}
return {
results: Return
}
}
}
});

Unable to save data using jquery which is lengthy

I have a textareafor
<div class="inner-addon left-addon">
Html.TextAreaFor(m => m.DataFixes, new { #class = "resizedTextbox", id = "txtDataFixes", placeholder = "Data Fixes" , style = "width : 70px,height : 70px;" })
</div>
I have used jquery to save the data using the button click. When i click on the save button then iam able to save the data in the textbox for when the data entered is small, But when i try to save a lengthy data, it doesnot get saved. The below is my jquery code. I think it has something to do with the var object.
$('#btnUpdateDataSet').click(function() {
var note = $("#txtNote").val();
var fileContentName = $("#txtFileContentName").val();
var fileContentId = $("#fileContentId").val();
var dataFixes = $("#txtDataFixes").val();
var oldWorkitemId = $('#drpOldWorkitemId option:selected').val();
if (fileContentName.length == 0) {
var fileContentId = null;
} else {
var fileContentId = $("#fileContentId").val();
}
updateDataSet(workItemID, dataSetDateStamp, cycle, reference, feed, source, target, lineStart, extension, note, fileContentId, dataFixes, oldWorkitemId);
});
The below is my controller
public ActionResult EditDataSet( string dataFixes)
{
EditDataSetVM editDataSetVM = new EditDataSetVM();
editDataSetVM.DataFixes = dataFixes;
return PartialView("EditDataSetView", editDataSetVM);
}
My Ajax call
function updateDataSet(workItemID, dataSetDateStamp, cycle, reference, feed, source, target, lineStart, extension, note, fileContentId, dataFixes,oldWorkitemId) {
$.ajax({
type: "POST",
url: "/DataSet/UpDateDataSetDetails",
contentType: "application/json; charset=utf-8",
data: { "workItemId": workItemID, "dataSetDateStamp":
dataSetDateStamp, "cycle": cycle, "reference": reference, "feed": feed, "source": source, "target": target, "lineStart": lineStart, "extension":
extension, "note": note, "fileContentId": fileContentId, "dataFixes":
dataFixes, "oldWorkitemId": oldWorkitemId },
datatype: "json",
success: function (data) {
if (data == "Update Succeeded") {
$("#btnViewDataSet").click();
}
else {
$("div.toshow").show();
$('#lblUpdateDataSetResult').html('Following error(s) occured:<br\>' + data);
}
},
error: function () {
alert("Update WorkItem metadata failed.");
}
});
}

Kendo Grid C# - Select current page without refresh datasource again

i have been trying to fix this, what i want to do is:
I have a datasource who gets data from server, when i go to server, i get the list of items, then i have to search the item i have to select (This item could be in any page), after i have the item and the page where the item is located (assuming each page has 30 items), then i call LINQ expression to skip the required ammount of data and take 30. Finally i return this list to the client side.
When data arrives to client i need to "auto-select" the selected item and change the page to locate the user in the right page where the selected item is located. I have the new page, skip, selected value and everything in the client side again.
What do you suggest to me to change the page into the kendo grid datasource without call a new refresh and go to the server again?
This is how the datasource looks like:
return new kendo.data.DataSource({
serverPaging: true,
transport: {
read: {
url: URLController.Current().getURL('MyURL'),
contentType: 'application/json',
accepts: 'application/json',
type: 'POST'
},
parameterMap: function(data, type) {
if (data) {
return JSON.stringify(
{
data: jsonData,
pageSize: data.pageSize,
skip: data.skip,
take: data.take
});
}
}
},
schema: {
data: function (data) {
var dropDownData = JSON.parse(data);
gridElement.attr('data-model', JSON.stringify({ data: data }));
return dropDownData.Data;
},
total: function (data) {
var dropDownData = JSON.parse(data);
return dropDownData.total;
},
model: {
id: 'ID'
}
},
pageable: true,
pageSize: 30,
error: function(e) {
alert('Error ' + e);
}
});
When the grid data is bounded i have to change the page to current page number and then select the current item.
grid.one('dataBound', function (e) {
var currentGridElement = this.element;
var currentModel = currentGridElement.attr('data-model');
var currentJsonData = parseDropDownDataJSONString(currentModel).data;
var gridDataSource = this.dataSource;
var selection = gridDataSource.get(currentJsonData.selectedValue);
if (selection != undefined) {
var row = currentGridElement.find('tbody>tr[data-uid=' + selection.uid + ']');
if (row != undefined) {
currentGridElement.attr('data-closeByChange', false);
gridDataSource.page(currentJsonData.pageNumber);
this.select(row);
dexonDropDownGrid.combobox().text(selection.DISPLAY);
}
}
var aaaa = 0;
});
This is how my databound event listener looks like, when i try to set the page it calls again the server and i got more delay to load the right data.
Is there any way to solve this?
Thanks
Have the same problem.
There is how I fix that(not the best solution ever, but it works):
var forcedPageChange = false;
var cachedResult;
var dataSource = new kendo.data.DataSource({
transport: {
read: function (options) {
if (forcedPageChange) { // prevent data request after manual page change
forcedPageChange = false;
options.success(cachedResult);
cachedResult = null;
return;
}
gridDataProvider.getData() // promise of data
.then(function (result) {
// check if current page number was changed
if ($scope.gridConfig.dataSource.page() !== result.pageNumber ||
$scope.gridConfig.dataSource.pageSize() !== result.rowsPerPage) {
cachedResult = _.clone(result);
forcedPageChange = true;
options.page = result.pageNumber;
options.pageSize = result.rowsPerPage;
$scope.gridConfig.dataSource.query(options);
}
options.success(result);
}, function () {
options.error();
});
}
},
schema: {
data: function (response) {
return response.items;
},
total: function (response) {
return response.totalCount;
}
},
//...
serverPaging: true,
serverSorting: true,
serverFiltering: true
});
I found that dataSource.page(newPageNumber) doesn't work in this situation. It just drop page number to 1.
This solution works, but I still have a bug with missing sorting icon after dataSource.query(options)...

Js variable does not update in ajax

I use jstree and want to reload it with new data but I cannot send it to new data.
var $driver = 0;
$(document).ready(function () {
$('#tree_folder').jstree({
'core': {
'check_callback': true,
"themes": {
"responsive": false
},
'data': {
type: "POST",
url: "Doc.aspx/Folder",
data: function () { return '{"driver":"' + $driver + '"}' },
contentType: "application/json"
}
}
});
});
$(document).on('click', '.tile', function () {
var $item = $(this);
var $driver = $item.attr('data-driver');
// alert($driver);
$('#tree_folder').jstree('refresh');
});
I got the new value when clicked, it send old default data every time. Above in alert function, it can give me the right value although json post send default one even data is written with function
function () { return '{"driver":"' + $driver + '"}' }
How can I get the new value from variable?
Remove var before $driver from .tile click function as you are created global previously,
Try this,
$(document).on('click', '.tile', function () {
var $item = $(this);
$driver = $item.attr('data-driver'); // remove var from this line
// alert($driver);
$('#tree_folder').jstree('refresh');
});
Also use cache:false in jstree like,
function getDriver() {
return '{"driver":"' + $driver+ '"}';
}
$(document).ready(function () {
$('#tree_folder').jstree({
'core': {
'check_callback': true,
"themes": {
"responsive": false
},
cache: false, // cache false
'data': {
type: "POST",
url: "Doc.aspx/Folder",
data: getDriver(), // get updated driver
contentType: "application/json"
}
}
});
});
Also take a look on change ajax options in jstree from server

loading a JavaScript file with vars not set at load time

the post title may not explain fully, but here is what I am hoping to do: I have my JavaScript code in a separate file, and I have it arranged like so
var PK = {
"vars" : {
"uris" : {
"app1": "http://this/server/",
"app2": "http://that/server/"
},
"something": {
"objects": [],
"obj1": { "url": PK.vars.uris.app1 },
"obj2": { "url": PK.vars.uris.app2 }
}
},
"methods" : {
"doThis" : function(a) {
$.ajax({
url: PK.vars.uris.app1,
data: data,
type: "GET",
success: function(data) { .. do something .. }
});
},
"doThat" : function(a) {
$.ajax({
url: PK.vars.uris.app2,
data: data,
type: "GET",
success: function(data) { .. do something else .. }
});
},
"init" : function(position) {
if (position) { PK.methods.doThis();
}
else {
PK.methods.doThat();
}
}
}
};
and then, in my html, I have the following
$(document).ready(function() {
PK.vars.uris.app1 = "[% app1 %]";
PK.vars.uris.app2 = "[% app2 %]";
PK.methods.init();
});
where the values of app1 and app2 are sent from the server based on a config file. Except, it doesn't work as expected, because, when the separate JavaScript loads, PK.vars.uris is not defined at that time. Of course, everything works beautifully if I have PK.vars.uris{} hardcoded.
How can I delay the evaluation of var PK until after the document has loaded and PK.vars.uris is available to be used in the JavaScript code?
Is the problem that you need to pass values into an initialiser?
How's this approach:
In your external file:
function PK_Constructor(app1Uri, app2Uri) {
this.vars = { "uris" : {
"app1" : app1Uri,
"app2" : app2Uri
},
"something": {
"objects": [],
"obj1": { "url": app1Uri },
"obj2": { "url": app1Uri }
},
};
this.doThis = function(a) {
$.ajax({
url: this.vars.uris.app1,
data: data,
type: "GET",
success: function(data) { .. do something .. }
});
// etc
}
And in you HTML:
// Ensuring PK has global scope
var PK = undefined;
$(document).ready(function() {
PK = new PK_Constructor("[% app1 %]", "[% app2 %]");
});

Categories

Resources