I have a little problem with my KendoUi-grid. It's very simple :
JS File
$("#gridPlannif").kendoGrid({
datasource: ds_VEHICULE_SANSDATEFIN,
height: 200,
toolbar: ["create"],
sortable: true,
filterable: true,
scrollable: true,
columns: [{
field: "sDateArriveePrevue",
title: "Arrivée à partir du",
}, {
[... some columns... ]
},{
command: ["edit", "destroy"], title: " ", width: "200px" }
],
editable: {
mode: "popup",
[... some configurations ... ]
}
});
Controler
public ActionResult UpdateVehicule([DataSourceRequest]DataSourceRequest request, Planification vehicule)
{
try
{
if (this.ModelState.IsValid)
{
[...]
}
else
{
[...]
}
return Json(new[] { vehicule }.ToDataSourceResult(request, ModelState));
}
catch (Exception e)
{
return Json(new[] { vehicule });
}
}
View (.ascx)
[...]
<script>
ds_VEHICULE_SANSDATEFIN = new kendo.data.DataSource({
autoSync: true,
transport: {
read: {
url: '<%= Url.Action("GetVehicules_SansDateFin", "Plannification") %>'
},
update: {
url: '<%= Url.Action("UpdateVehicule", "Plannification") %>'
},
destroy: {
url: '<%= Url.Action("DeleteVehicule", "Plannification") %>'
},
create: {
url: '<%= Url.Action("AddVehicule", "Plannification") %>'
}
}
});
</script>
[...]
Problems
-> First problem : the datasource definition doesn't works.. I must do that instructions after grid initialisation :
$("#gridPlannif").data("kendoGrid").setDataSource(ds_VEHICULE_SANSDATEFIN);
$("#gridPlannif").data("kendoGrid").dataSource.read();
$("#gridPlannif").data("kendoGrid").refresh();
Thanks to that, grid display data correctly.
-> Second problem, the most important :
"add", "edit" and "destroy" doesn't call controller. With firebug, I see no call to the controller, I don't know why. I use on the same page a Scheduler component and it works, it uses the same functions on the controller to add / update / delete.
Someone has a suggestion ?
Thank you.
It sounds like your JavaScript library code for " $("#gridPlannif").kendoGrid({ " is not wrapped by a document.ready (assuming you are also using jQuery) and loading before the View's JavaScript code (class libraries load before View code, unless told otherwise).
So, be sure to wrap your JavaScript library code like this:
$(function() { // This is jQuery shorthand for document.ready
$("#gridPlannif").kendoGrid({
datasource: ds_VEHICULE_SANSDATEFIN,
height: 200,
toolbar: ["create"],
sortable: true,
filterable: true,
scrollable: true,
columns: [{
field: "sDateArriveePrevue",
title: "Arrivée à partir du",
}, {
[... some columns... ]
},{
command: ["edit", "destroy"], title: " ", width: "200px" }
],
editable: {
mode: "popup",
[... some configurations ... ]
}
});
What this will do is allow all of the View page code to render, including the inline <script> blocks defined before it tries to wire up the Kendo Grid. All of this to make sure the Data Source exists prior to trying to call it from the Kendo Grid initialization.
Related
in my project i want to initialize Kendo Grid from jquery file. i have created a .js file in which i have created a function
function initializeGrid(gridName, url, onSelectFunction) {
onSelectFunction = onSelectFunction || null;
$("#" + gridName).kendoGrid({
dataSource: {
type: "json",
transport: {
read: url
},
schema: {
model: {
fields: {
ClientID: {type: "number"},
Client:{type: "string"}
}
}
},
pagesize: 30,
Paging: true,
Filtering: true,
},
selectable: "multiple cell",
filterable: true,
columns: [
{ field: "ClientID" },
{ Template: ("<input type='checkbox' id='#:data.ClientID#' class='k-checkbox'/><label class='k-checkbox-label' onclick='event.stopPropagation()' for='#:data.ClientID#'></label>") },
{ field: "Client" }
]
});
$("#" + gridName).attr("data-val-number", "Invalid input.");
}
this function accepts name of the control and url to load data source from as arguments. in another .js file i have all code that loads controls by calling the earlier function.
initializeGrid("client", "/Clients/GetDataForGrid", null);
issue is that when i run the program it is not creating the grid and loading the data instead showing a drop down with no data. i checked http://docs.telerik.com/kendo-ui/api/javascript/ui/grid?utm_medium=social-owned&linkId=38973492 for reference but no use.
i would really appreciate help here.
I have created window on sever side with LinkButton on bottom
<ext:Window runat="server" ID="winIndex" Title="Test">
<AutoLoad Url="index.html" Mode="IFrame" />
<Buttons>
<ext:LinkButton runat="server" ID="btn" Text="Test Button">
<Listeners>
<Click Handler="Ext.msg.alert('Alert','test');" />
</Listeners>
</ext:LinkButton>
</Buttons>
</ext:Window>
i wanted to create this window on client side using javascript this is what i tried
var CreateWindow = function () {
var windowConfig = {
id: "winIndex",
hidden: false,
closeAction: "hide",
title: "Test",
buttons: [
{
id: "btn",
text: "Test Button",
listeners:
{
click:
{
fn: function (el, e) {
Ext.msg.alert('Alert','test');
}
}
}
}
],
autoLoad: {
url: "index.html",
nocache: true,
mode: "iframe",
showMask: true,
triggerEvent: "show",
reloadOnEvent: true
}
}
new Ext.Window(windowConfig)
}
Window rendered perfectly using javascript too except LinkButton. it draws normal button rather than LinkButton but i need link button just like server side ext control. Any help will be appreciated.
From your code snippet I am assuming you are referring to Ext.NET 1.x and Ext JS 3.x.
If so, by default, when using the buttons configuration option for a new Ext.Window, the default component used will be Ext.Buttons.
LinkButtons are a useful extension from Ext.NET, and they have their xtype as netlinkbutton so you would have to explicitly set that, for example:
new Ext.Window({
title: "Test",
height: 300,
width: 300,
buttons: [{
id: "btn",
xtype: 'netlinkbutton',
text: "Test Button",
listeners: {
click: {
fn: function (el, e) {
Ext.Msg.alert('Alert', 'test');
}
}
}
}]
}).show();
Notice the key thing is xtype: netlinkbutton
Hope that helps!
P.S. Note that in Ext.NET 3, the LinkButton is renamed to HyperLinkButton and its xtype is now nethyperlinkbutton.
use netlinkbutton as xtype in ExtJs. netlinkbutton is exactly what LinkButton is in Ext.net
I have a Kendo UI grid where some of the columns can be filtered. For each row in that column, you can open a popup to see some details to the specific entry.
I can open the popup without any problems. But: after closing it and trying to filter any of the columns, I get the following error: JavaScript runtime error: Unable to get property 'toggle' of undefined or null reference
If I filter a column before I open a popup, it works like a charm.
If I filter a column and then open the popup, the already filtered column can be filtered again but the others not.
I don't know why I can't filter columns after opening and closing the popup.
Any ideas or hints would be really helpful. Thanks
HTML:
<div id="windoofTestOuter"><div id="windoofTest"></div></div>
<div id="processGrid"></div>
My grid:
$("#processGrid").kendoGrid({
sortable: true,
pageable: true,
selectable: true,
filterable: {
extra: false
},
dataSource: {
type: "aspnetmvc-ajax",
transport: {
read: {
url: "/Home/GetProcesses",
cache: false,
type: "POST",
dataType: "json"
},
parameterMap: function (data) {
return $.extend({}, data, { sort: data.sort, filter: data.filter });
}
},
serverPaging: true,
serverFiltering: true,
serverSorting: true,
page: "#ViewBag.ProcessPage",
schema: { data: "Data", total: "Total", model: { id: "Id" } },
pageSize: "#(#Model.MaxCountToShow)"
},
columns: [
{ field: "ErrorDateTime", title: "ProcessDateTime", width: "170px"/*, filterable: { ui: dateFilter }*/ },
{ field: "Name", title: "Processtype", attributes: { value: "type" }, width: "240px;", filterable: { ui: processtypeFilter} },
{ field: "Service", title: "Service", width: "181px;", filterable: { ui: serviceFilter } },
{ field: "Operation", title: "Operation", width: "130px", filterable: { ui: operationFilter } }
]
}).data("kendoGrid");
The link/string which shall open the popup:
function createProcessActionString(process) {
var det = '<a class="makeANiceMouse" onclick="processDetailUrl(' + process.Id + ', ' + grid.dataSource.page() + ')">Details</a>';
return det;
}
My popup:
function processDetailUrl(id, page) {
var windoof = $("#windoofTest").kendoWindow({
width: "1150px",
height: "300px",
content: det,
title: "Process Details",
actions: ["Minimize", "Maximize", "Close"],
close: function (e) {
windoof.data("kendoWindow").content(" ");
}
});
windoof.data("kendoWindow").center().open();
}
I deleted the unnecessary columns and so on..
EDIT: I tried to intitialize the filter in the filterMenuInit. After opening and closing the popup, I clicked on the filter icon of one of the columns, and I get the error : JavaScript runtime error: Unable to get property 'toggle' of undefined or null reference . The same one as before.
EDIT: I used the windoof.destroy() but the filters weren't accessable afterwards.
EDIT solution: I have a workaround for working with the filters again. I just fake a click on each of it before I open a popup. It's not beautiful but it serves me so far.
BUT It seems like everything gets kicked/killed by that damn popup. I can't even access the grid's datasource anymore.. It's strange...
I'm dealing with the same issues but got well passed the Data not being there. Check out or use onDataBound and use e.sender to get a handle to the Grid Object opposed to .data("KendoGrid") from the onClose of the popup this is what fixed it for me. I'm still trying to get my filters to work though after the pop up closes.
I want to achive lazy loading of tree branches in an MVC application with extjs4.1 where the braches are located on different urls. I have come quite some ways and hit quite some walls, right now it does not branch.
Here is where I fail:
Ext.define('OI.view.tree.Tree' ,{
extend: 'Ext.tree.Panel',
alias : 'widget.treepanel',
store: 'TreeStore',
collapsible: true,
rootVisible: false,
viewConfig: {
plugins: [{
ptype: 'treeviewdragdrop'
}]
},
height: 350,
width: 400,
title: 'Directory Listing',
initComponent: function() {
this.store = Ext.data.StoreManager.lookup(this.store);
this.store.getProxy().url = 'data/level1.json'; // <-- init loading
this.store.load();
this.callParent(arguments);
},
listeners: {
itemclick: function(view, record) {
console.info('ID: '+record.get('id'));
console.info('TEXT: '+record.get('text'));
console.info('PrimType: '+record.get('primaryType'));
console.info(record.fields.getCount());
console.info('JCRPATH: '+record.get('jcrPath'));
var newBranchStore = Ext.create('Ext.data.TreeStore', {
model: 'OI.model.Branch',
autoLoad: true,
proxy: {
type: 'ajax',
reader: {
url: 'data/'+ record.get('jcrPath') +'/level1.json', //<-- load json at the level of the url path returned by the model
type: 'json'
}
},
folderSort: false
});
newBranchStore.load({url: 'data/'+ record.get('jcrPath') +'/level1.json',
callback: function(){
console.log('loaded');
var mynode = newBranchStore.getNodeById('content_mytest');
console.info(mynode.get('id'));
this.store.getNodeById(record.get('id')).appendChild(mynode).expand(); // <-- this does not work
},
scope: this
});
}
}
});
The first level is loaded correctly, however when I trigger a click on the node, I am getting the right json returned from the server, in this case a static json file for debugging, and I try to statically fetch a node and append it to the one that has been clicked. But it is never injected.
What I eventually want to achive is that I can append all children returned by the json file to the node that has been clicked.
Further I am a bit confused about treestores ...
Am I correct when I say that there can be only ONE treestore per tree, right? So I need to attach the new nodes to the original treestore ... I am slightly confused and could need all the pointers I can get.
You are way overcomplicating this, use this approach instead (basically just swap out the url of your store before it loads to the correct url):
Ext.define('OI.view.tree.Tree' ,{
extend: 'Ext.tree.Panel',
alias : 'widget.treepanel',
store: 'TreeStore',
collapsible: true,
rootVisible: false,
viewConfig: {
plugins: [{
ptype: 'treeviewdragdrop'
}]
},
height: 350,
width: 400,
title: 'Directory Listing',
initComponent: function() {
this.store = Ext.data.StoreManager.lookup(this.store);
this.store.getProxy().url = 'data/level1.json'; // <-- init loading
this.store.load();
this.callParent(arguments);
},
listeners: {
beforeload: function(store, operation) {
store.getProxy().url = 'data/'+ operation.node.get('jcrPath') +'/level1.json';
}
}
});
I have following problem. I have grid with tbar. Inside tbar I have number of Ext.form.field.Trigger.
When the user click on trigger button I want to filter the store using function that is provided with grid. I want to define functionality of triggerclick inside defined class, so I can reuse this component with different grid.
So, in short I want to find the panel where clicked component is placed and call panel function, or pass reference of panel to triggerclick, or fire an event with some parameter that will calculated based on where the button was clicked, or maybe there is a better method to accomplish this.
The code (FilterField -> extension of trigger):
Ext.define('GSIP.core.components.FilterField', {
extend: 'Ext.form.field.Trigger',
alias: 'widget.filterfield',
initComponent: function() {
this.addEvents('filterclick');
this.callParent(arguments);
},
onTriggerClick: function(e, t) {
//Ext.getCmp('gsip_plan_list').filterList(); - working but dont want this
//this.fireEvent('filterclick'); - controller cant see it,
//this.filterList; - is it possible to pass scope to panel or reference to panel
//e.getSomething() - is it possible to get panel via EventObject? smth like e.getEl().up(panel)
}
});
code of panel:
Ext.define('GSIP.view.plans.PlanReqList', {
extend: 'Ext.grid.Panel',
alias: 'widget.gsip_devplan_list',
id: 'gsip_plan_list',
title: i18n.getMsg('gsip.view.PlanReqList.title'),
layout: 'fit',
initComponent: function() {
this.store = 'DevPlan';
this.tbar = [{
xtype: 'filterfield',
id: 'filter_login',
triggerCls: 'icon-user',
//scope:this - how to pass scope to panel without defining onTriggerClick here
// onTriggerClick: function() {
// this.fireEvent('filterclick'); //working event is fired but controller cant see it
// this.filterList; //this is working but i dont want to put this code in every filterfield
// },
// listeners : {
// filterclick: function(btn, e, eOpts) { //this is working
// }
// },
}];
this.columns = [{
id: 'id',
header: "Id",
dataIndex: "id",
width: 50,
sortable: true,
filterable: true
}, {
header: "Name",
dataIndex: "name",
width: 150,
sortable: true,
filterable: true
}, {
header: "Author",
dataIndex: "author",
sortable: true,
renderer: this.renderLogin,
filterable: true
}];
this.callParent(arguments);
},
filterList: function() {
this.store.clearFilter();
this.store.filter({
property: 'id',
value: this.down("#filter_id").getValue()
}, {
property: 'name',
value: this.down("#filter_name").getValue()
});
},
renderLogin: function(value, metadata, record) {
return value.login;
}
});
part of code of Controller:
init: function() {
this.control({
'attachments': {
filesaved: this.scanSaved,
}
}, {
'scan': {
filesaved: this.attachmentSaved
}
}, {
'#filter_login': {
filterclick: this.filterStore //this is not listened
}
});
},
filterStore: function() {
console.log('filtering store');
this.getPlanListInstance().filter();
},
Controller can listen to anything. Just need to specify exactly what to. But I would fire events on the panel level - add this into your trigger handler:
this.up('panel').fireEvent('triggerclicked');