Kendo UI: Can't add a node to treeview when using custom schema - ajax

I have a kendo tree initialized with the following datasource:
var dataSource = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: '/Quota/Home/GetTemplateHierarchy',
dataType: 'json',
data: { hierarchyID: hierarchyID, quotaSetID: quotaSetID, batchSize: 10 }
}
},
schema: {
model: {
id: 'id',
hasChildren: 'hasChildren',
children: 'items',
fields: {
text: 'text'
}
}
}
});
Does anyone know how to add and create a new node for this datasource? I've tried the generic treeview.append({ text: "Boo"}) but it doesn't do anything. I've successfully removed nodes, but can't seem to add any. The documentation is not clear as to how to add anything when using custom schemas.

Not sure what do you want to be the text of the node that you want to display. So I will guess that you want to display the only element in the schema nodelevel
The data in that case should be: { nodelevel : 99 }
Following a complete example where I have an initial node and then I append sub-nodes to the selected node.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Tree View</title>
<!-- Kendo UI Web styles-->
<link href="styles/kendo.common.min.css" rel="stylesheet" type="text/css"/>
<link href="styles/kendo.default.css" rel="stylesheet" type="text/css"/>
<!-- Kendo UI Web scripts-->
<script src="js/jquery.min.js" type="text/javascript"></script>
<script src="js/kendo.web.min.js" type="text/javascript"></script>
<script>
$(document).ready(function () {
var count = 0;
var data = [
{ nodelevel: count++ }
];
var dataSource = new kendo.data.HierarchicalDataSource({
data :data,
schema:{
model:{
id :'id',
hasChildren:'hasChildren',
children :'items',
fields :{
nodelevel:{
type :'number',
editable:true,
nullable:false
}
}
}
}
});
var tree = $("#tree").kendoTreeView({
dataSource :dataSource,
dataTextField:"nodelevel"
}).data("kendoTreeView");
$("#add").click(function () {
var selected = tree.select();
if (selected.length > 0) {
tree.append({ nodelevel: count++ }, selected);
}
});
});
</script>
</head>
<body>
Add to selected
<div id="tree"></div>
</body>
</html>

Paul, I'd like to propose another solution...
<!-- Kendo UI Web styles-->
<link href="../styles/kendo.common.min.css" rel="stylesheet" type="text/css"/>
<link href="../styles/kendo.default.min.css" rel="stylesheet" type="text/css"/>
<!-- Kendo UI Web scripts-->
<script src="../js/jquery.min.js" type="text/javascript"></script>
<script src="../js/kendo.web.min.js" type="text/javascript"></script>
<!-- Local Styles -->
<style type="text/css">
</style>
<!-- Initialize Form Elements -->
<script type="text/javascript">
$(document).ready(function () {
function loadMore() {
var uid = $(this).data("uid");
var node = tree.findByUid(uid);
tree.insertBefore(content, node);
tree.remove(node);
addLoadMore(".k-i-pencil");
}
function addLoadMore(clss) {
$(clss, tree.element).closest(".k-item").on("click", loadMore);
}
var content = [
{
text :"node1",
items:[
{ text:"node1.1" },
{ text:"node1.2" },
{ text:"node1.3", spriteCssClass:"k-icon k-i-pencil" },
{ text:"node1.4" }
]
}
];
var tree = $("#tree").kendoTreeView({
dataSource:content
}).data("kendoTreeView");
addLoadMore(".k-i-pencil");
});
</script>
</head>
<body>
<div id="tree"></div>
</body>
</html>
Here I create a tree with a content loaded from JSON (it should be replaced by your ajaxAntiForgery). There is one node in the tree that has an icon (k-i-pencil). Then I call a function addLoadMore that intercepts clicks on the node with k-i-pencil and add new content to this node -using insertBefore for inserting the new content before the content with k-i-pencil and then removes the old node).
I think that this example is pretty similar to what you are doing with your button.
So, take a look into loadMore function to see how I detect the node corresponding to where I clicked (I extract the uid and the find the node with this uid by using tree.findByUid).
Finally I remove the original node (invoking tree.remove) and set again the interceptor for the new nodes with k-i-pencil.
Hopefully this is pretty close to what you have.

The treeview.append should work and append new node to the root level if you do not specify a note to append it to.
You could also use the dataSource.insert({text:"foo"}) or dataSource.add.

Related

Kendo DataBound e.model object VS Edit e.model object

I'm using Kendo DataBound event to print the model from the row triggering the event, the problem I'm facing is the model is undefined when using DataBound different from using Edit event.
.Events(e => { e.DataBound(#<text>function(e) { alert(e.model); }</text>) })
The problem is that apparently e.DataBound is not handling the e argument as the Edit, Cancel, and the rest of events.
When trying with e.Edit(#<text>function(e) { alert(e.model); }</text>) the e.model object is loaded with the properties and values.
Is there a way to achieve this?
You can achieve that by using jQuery only:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled</title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.1.114/styles/kendo.common.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.1.114/styles/kendo.rtl.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.1.114/styles/kendo.default.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.1.114/styles/kendo.mobile.all.min.css">
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2020.1.114/js/angular.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2020.1.114/js/jszip.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2020.1.114/js/kendo.all.min.js"></script>
<script>
$(function() {
$('#grid').kendoGrid({
dataSource: {
data: [{ A: 1, B: 2 }, { A: 3, B: 4 }]
},
});
let grid = $("#grid").data("kendoGrid");
$("#grid").on('click', 'tbody td', function(e) {
let $td = $(e.target),
dataItem = grid.dataItem($td.parent()),
cellContent = dataItem[$td.data('field')];
console.log($td, dataItem, cellContent);
});
});
</script>
</head>
<body>
<div id="grid"></div>
</body>
</html>
Demo
Or by using the grid's change event. But in order to use that event you need to set your grid selectable to true:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled</title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.1.114/styles/kendo.common.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.1.114/styles/kendo.rtl.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.1.114/styles/kendo.default.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.1.114/styles/kendo.mobile.all.min.css">
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2020.1.114/js/angular.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2020.1.114/js/jszip.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2020.1.114/js/kendo.all.min.js"></script>
<script>
$(function() {
$('#grid').kendoGrid({
dataSource: {
data: [{ A: 1, B: 2 }, { A: 3, B: 4 }]
},
selectable: true,
change: function() {
let dataItem = this.dataItem(this.select());
console.log(dataItem);
}
});
});
</script>
</head>
<body>
<div id="grid"></div>
</body>
</html>
Demo

Conditionally hide button in cell of KendoUIGrid

I have a Kendo UI Grid in which one column has a button, but I musgt hide the button depending on the row which the button is in (in this case first row and last row).
How can I do that?
My code is below.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Kendo UI Snippet</title>
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2016.2.714/styles/kendo.common.min.css"/>
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2016.2.714/styles/kendo.rtl.min.css"/>
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2016.2.714/styles/kendo.silver.min.css"/>
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2016.2.714/styles/kendo.mobile.all.min.css"/>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2016.2.714/js/kendo.all.min.js"></script>
</head>
<body>
<div id="grid">
</div>
<script>
$("#grid").kendoGrid({
columns: [
{ field: "name" },
{ field: "age" },
{ width: 150,
command:
[
{
name:"Up",
imageClass: "k-icon k-i-arrow-s",
click: function(e) {
var tr = $(e.target).closest("tr");
var item = this.dataItem(tr);
var dir = "U";
var dataItem = this.dataItem($(e.currentTarget).closest("tr"));
moveItem.moveUp(dir,dataItem.order).addCallback(function(response){
alert(response);
})
}
},
]
}
],
dataSource: [
{ name: "Jane Doe", age: 30 },
{ name: "John Doe", age: 33 }
]
});
var grid = $("#grid").data("kendoGrid");
grid.hideColumn(grid.columns[0].columns[0]);
</script>
</body>
</html>
==================
I have added the code that contains the moveItem.moveItemUp method.
In this method I use a remote procedure call to execute some server side javascript. It doesn't have anything to do, really, with hiding of the buttons.
<xe:jsonRpcService
id="jsonRpcService1"
serviceName="moveItem">
<xe:this.methods>
<xe:remoteMethod
name="moveUp"
script="return direction + order">
<xe:this.arguments>
<xe:remoteMethodArg
name="direction"
type="string">
</xe:remoteMethodArg>
<xe:remoteMethodArg
name="order"
type="number">
</xe:remoteMethodArg>
</xe:this.arguments>
</xe:remoteMethod>
</xe:this.methods>
</xe:jsonRpcService>
There are three ways to customise Kendo UI Grid row and cell appearance:
http://docs.telerik.com/kendo-ui/controls/data-management/grid/how-to/style-rows-cells-based-on-data-item-values
Row and column templates do not provide information about the data item index, so the remaining option is to use the dataBound event, get the Grid tbody, locate the first and last child table rows and finally, hide the buttons inside them. The buttons will have a k-grid-Up CSS class, i.e. depending on the command name (case sensitive).
One way of hiding controls within the grid is via CSS. You could create the following styles to hide the first and last buttons in a row:
#grid> tbody > tr:first-child > td > input {
display:none;
}
#grid> tbody > tr:last-child > td > input {
display:none;
}
(You will need to change these styles to get it work with your specific grid and buttons).

kendo ui autocomplete - json file datasource - template - 404 Not Found error - /undefined URL

Below code has been thankfully provided by machun for toggling between RTL and LTR directions in Kendo UI widgets.
The code consists of:
HTML:
kendo autocomplete form plus a button to activate support for RTL and LTR language.
Script:
k-rtl class container
datasource (json file)
kendo autocomplete widget initializing + template to show image beside data and to open data links in the same tab
k-rtl class
The problem is that links don't open correctly. It shows a 404 Not Found error plus a /undefined at the end of the URL.
Live demo
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled</title>
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.common.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.rtl.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.default.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.mobile.all.min.css">
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2015.3.930/js/angular.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2015.3.930/js/jszip.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2015.3.930/js/kendo.all.min.js"></script>
</head>
<body>
<div id="container">
<input type="button" id="toggleRTL" value="Activate RTL Support" class="k-button" />
<input id="autocomplete" type="text" />
</div>
</body>
</html>
<script>
/*------k-rtl class container----------*/
function createAutoComplete(){
if($("#autocomplete").data("kendoAutoComplete") != null){
$("#autocomplete").parent().remove();
$("#container").append("<input id='autocomplete' type='text' />")
}
/*------datasource (json file)---------*/
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "json.txt",
dataType: "json",
data: {
q: "javascript"
}
}
},
schema: {
data: "results"
}
});
/*------kendo autocomplete widget initializing + template to show image beside data and to open data links in the same tab----------*/
$("#autocomplete").kendoAutoComplete({
dataSource: dataSource,
dataTextField: "name",
template: '<span><img src="/kendo-autocomplete-test/img/#: id #.jpg" /></span>' + '<span data-href="#:link#">#:name#</span>',
select: function(e) {
var href = e.item.find("span").data("href");
location.assign(href);
}
});
}
/*------k-rtl class----------*/
createAutoComplete();
$('#toggleRTL').on('click', function(event) {
var form = $('#container');
console.log(form);
if (form.hasClass('k-rtl')) {
console.log("test1");
form.removeClass('k-rtl')
} else {
console.log("test2");
form.addClass('k-rtl');
}
createAutoComplete();
})
</script>
I advice to debug your function first then simply check the variable and make sure it contain the right thing. You overlooked a simple thing that your jquery dom selector isn't quite right resulting var href contain "undefined".
Change
var href = e.item.find("span").data("href");
To
var href = e.item.find("span[data-href]").attr("data-href");
Take a look here

kendoui: Bind Remote datasource to drop down list in template

I have a edit template using a list view and want a drop down list that is populated from a remote source. But the drop down list just shows the loading icon.
Here is the DropDownList DataSource.
var dsTitles = new kendo.data.DataSource({
transport: {
read: "../data/options/",
dataType: "json"
},
serverFiltering: true,
filter: [{
field: "category_opt",
operator: "eq",
value: "title"
}]
});
and here is what I'm putting in the edit template
<input name="title_clt"
data-bind="value:title_clt"
data-value-field="value_opt"
data-text-field="label_opt"
data-source="dsTitles"
data-role="dropdownlist"
required
validationMessage="Required" />
any help would be great.
Your code is basically fine but there a couple of question that you might have missed.
Since you are defining the DataSource saying data-source="dsTitles" as part of the HTML the order on how you define things is pretty important.
The first thing that gets defined is the HTML. Which means that dsTitle should be global.
Then, after the input is processed is when you should call kendo.init.
So, it should be something like this:
<html>
<head>
<meta charset="UTF-8"/>
<title>OnaBai - KendoUI DrowDownList</title>
<!-- Kendo UI Web styles-->
<link href="styles/kendo.common.min.css" rel="stylesheet" type="text/css"/>
<link href="styles/kendo.default.min.css" rel="stylesheet" type="text/css"/>
<!-- Kendo UI Web scripts-->
<script src="js/jquery.min.js" type="text/javascript"></script>
<script src="js/kendo.web.min.js" type="text/javascript"></script>
<!-- Web Page styling -->
<style type="text/css">
</style>
<script type="text/javascript">
var dsTitles = new kendo.data.DataSource({
transport: {
read: "../data/options/",
dataType: "json"
},
serverFiltering: true,
filter: [{
field: "category_opt",
operator: "eq",
value: "title"
}]
});
$(document).ready(function () {
kendo.init("input");
});
</script>
</head>
<body>
<input name="title_clt"
data-bind="value:title_clt"
data-value-field="value_opt"
data-text-field="label_opt"
data-source="dsTitles"
data-role="dropdownlist"
required
validationMessage="Required" />
</body>
</html>
I think the answer might be as simple as using a Kendo DropDownListFor, which will be populated with the given data.

Jqgrid ColumnChooser column order change is not working

I am new to jQuery & jgrid. I am trying to use columnchooser to both to let user remove columns and change column order. Removing and adding columns are working fine. But changing the column order is not working. Below is what I have in the code.
<head>
<link rel="stylesheet" type="text/css" media="screen" href="/xxxx/resources/css/jquery/ui-lightness/jquery-ui-1.8.6.custom.css" />
<link rel="stylesheet" type="text/css" media="screen" href="/xxxx/resources/css/jqgrid/ui.jqgrid.css" />
<link rel="stylesheet" type="text/css" media="screen" href="/xxxx/resources/css/edi/standard.css" />
<link rel="stylesheet" type="text/css" media="screen" href="/xxxx/resources/css/jquery/ui-multiselect/ui.multiselect.css" />
<script type="text/javascript" src="/xxxx/resources/js/jquery/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="/xxxx/resources/js/jquery/jquery-ui-1.8.6.custom.min.js"></script>
<!-- <script type="text/javascript" src="/xxxx/resources/js/jquery/jquery-ui-1.8.11.custom.js"></script>-->
<script type="text/javascript" src="/xxxx/resources/js/jqgrid/grid.locale-en.js"></script>
<script type="text/javascript" src="/xxxx/resources/js/jquery/ui.multiselect.js"></script>
<script type="text/javascript" src="/xxxx/resources/js/jqgrid/jquery.jqGrid.min.js"></script>
<script type="text/javascript">
var jq = jQuery.noConflict();
jq.jgrid.no_legacy_api = false;
</script>
<script type="text/javascript" src="/xxxx/resources/js/jqgrid/jquery.jqGrid.min.js"></script> <!-- 3.8.2 version-->
<!--<script type="text/javascript" src="/xxxx/resources/js/jqgrid/jquery.searchFilter.js"></script>-->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>XXXX</title>
</head>
ui.multiselect.js file contains the suggested fix already.
$.widget("ui.multiselect", {
options: {
sortable: true,
searchable: true,
doubleClickable: true,
animated: 'fast',
show: 'slideDown',
hide: 'slideUp',
dividerLocation: 0.6,
nodeComparator: function(node1,node2) {
var text1 = node1.text(),
text2 = node2.text();
return text1 == text2 ? 0 : (text1 < text2 ? -1 : 1);
}
}},
destroy: function() {
this.element.show();
this.container.remove();
// Modified to work with jquery.ui.1.8
if ($.Widget === undefined)
$.widget.prototype.destroy.apply(this, arguments);
else {
$.Widget.prototype.destroy.apply(this, arguments);
return this;
}}
And I am using the columnchooser as below.
jq("#grid").jqGrid('navButtonAdd','#pager',
{ caption: "Columns",
title: "Reorder Columns",
onClickButton : function (perm){
jq("#grid").jqGrid('columnChooser');
}
});
Below is what I have tried so far.
When I add {"msel_opts": $.ui.multiselect.defaults} as an option, I am getting ui undefined JS error.
When I tried to include grid.jqueryui.js, got object or method not supported.
I am stuck # this. Would somebody help please?
It is difficult to find the error in your code, because you posted only one code fragment. Probably you try to add the button in the navigator toolbar with respect of 'navButtonAdd' before you created the navigator toolbar with respect of 'navGrid'.
In any way one small working example here could help you to find your error.
For others who are in the same requirement, you may consider my columnchooser implementation.
My Dialog Form Declaration. (Dialog box which will be shown when columnchooser button is clicked.
All required fields will not be allowed to remove.
Creating the ColumnChooser Button for my Grid.
jq("#grid").jqGrid('navButtonAdd','#pager',{
caption: "Columns",
title: "Customize Columns",
onClickButton : function (){
/*jq("#grid").jqGrid('columnChooser',{
height:columnChooserHt
});*/
createDialogDiv();
jq( "#dialog-form" ).dialog('open');
}
});
Adding Save(OK) and Cancel Buttons to my Div.
jq(function(){
jq( "#dialog-form" ).dialog({
autoOpen: false,
height: 300,
width: 350,
modal: true,
buttons: {
"OK": function() {
changeColView();
jq( "#dialog-form" ).dialog('close');
},
Cancel: function() {
jq( "#dialog-form" ).dialog('close');
}
},
close: function() {
}
});
});
Function which inserts the column names with the select boxes which needed to be displayed on the ColumnChooser Dialog Box.
function createDialogDiv(){
var colModelDiv = jq("#grid").jqGrid('getGridParam','colModel');
var colNamesDiv = jq("#grid").jqGrid('getGridParam','colNames');
//alert(JSON.stringify(colModelDiv));
//alert(JSON.stringify(colNameDiv));
var container = document.getElementById('dialog-form');
//alert(colNamesDiv.length);
var chckBox="";
for(i=0;i<colNamesDiv.length;i++){
if(colModelDiv[i].hidden && colModelDiv[i].hidden == true ){
chckBox+="<input type='checkbox' id='"+colNamesDiv[i]+"' name='"+colNamesDiv[i]+"' value='"+colModelDiv[i].name+"'>"+colNamesDiv[i]+"</input><br/>";
}else{
if(colModelDiv[i].editrules && colModelDiv[i].editrules.required){
chckBox+="<input type='checkbox' id='"+colNamesDiv[i]+"' name='"+colNamesDiv[i]+"' value='"+colModelDiv[i].name+"' disabled>"+colNamesDiv[i]+"</input><br/>";
}
else
chckBox+="<input type='checkbox' id='"+colNamesDiv[i]+"' name='"+colNamesDiv[i]+"' value='"+colModelDiv[i].name+"' checked>"+colNamesDiv[i]+"</input><br/>";
}
}
container.innerHTML=chckBox;
}
Finally the actual method which changes the Columns chosen from Columnchooser.
function changeColView(){
var colModelDiv = jq("#grid").jqGrid('getGridParam','colModel');
var colNamesDiv = jq("#grid").jqGrid('getGridParam','colNames');
for(i=0;i<colNamesDiv.length;i++){
var chckBox=document.getElementById(colNamesDiv[i]);
if(chckBox && chckBox.value && (!(chckBox.checked || chckBox.disabled))){
jq("#grid").jqGrid('hideCol',chckBox.value);
}
if(chckBox && chckBox.checked){
jq("#grid").jqGrid('showCol',chckBox.value);
}
}
jq("#grid").trigger('reloadGrid');
}
Plz let me know your thoughts on this one.

Resources