I have the following code in an MVC controller:
public JsonResult ARequest()
{
Dictionary<string, object> AnObject = new Dictionary<string,object>();
AnObject["foo"] = new object[] {"item 1", "item 2", "item 3"};
return Json(AnObject, JsonRequestBehavior.AllowGet);
}
And it works as expected; when I call it from a browser, I get the following JSON object:
{"foo":["item 1","item 2","item 3"]}
I have another file, this time with a Kendo UI Autocomplete Widget. Here is the code:
<input id="products" style="width: 250px" />
/*...*/
$("#products").kendoAutoComplete({
filter: "contains",
minLength: 3,
dataTextField: foo,
dataSource: {
type: "odata",
pageSize: 10,
transport: {
read: {
url: "education-portal/ARequest"
}
}
}
});
As per the official examples here and here.
The problem is, when I load the page I don't get anything. The AutoComplete is blank and it stays blank. No results show up when I type anything in the box. Any idea what went wrong? I can't see it for the life of me.
There are several problems:
You should not define dataTextField since your array of value are not objects but strings.
You should say where in the received data is actually the array of items.
Is the type odata or JSON?
It should be something like:
$("#products").kendoAutoComplete({
filter: "contains",
minLength: 3,
dataSource: {
type: "json",
pageSize: 10,
transport: {
read: {
url: "education-portal/ARequest"
},
schema : {
data: "foo"
}
}
}
});
Example here : http://jsfiddle.net/OnaBai/rSjpS/
Since you are wrapping the collection inside a field called foo, you should specify this via the dataSource.schema.data options.
e.g.
dataSource: {
schema: {
data: "foo"
}
}
You do not have to specify any datavaluefield or datatextfield
Related
I am passing in a JSON array to my JTable and am trying to use AJAX to show the data with no page load. This is an asp.net core mvc app with a C# back-end. The data loads, but as i said i do not have the ability to sort and all results are shown instead of only 10 per page as I request in the sorting param.
What do I ned to change here?
[Route("api/ca")]
public JsonResult Index()
{
var ListData = _context.CIModel.FromSql("StoredProcedureName").ToList();
return Json(new { Result = "OK", Records = ListData, TotalRecordCount = ListData.Count });
}
$('#btnTest').click(function () {
$('#jTableTest').jtable({
paging: true,
pageSize: '10',
sorting: true,
defaultSorting: 'Name ASC',
actions: {
listAction: function (postData, jtParams) {
return $.Deferred(function ($dfd) {
$.ajax({
url: 'https://localhost:44328/api/ca?jtStartIndex=' + jtParams.jtStartIndex + '&jtPageSize=' + jtParams.jtPageSize + '&jtSorting=' + jtParams.jtSorting,
type: 'GET',
dataType: 'json',
success: function (data) {
$dfd.resolve({ Records: data.records, Result: data.result, TotalRecordCount: data.TotalRecordCount });
},
error: function () {
$dfd.reject();
}
});
});
}
},
fields: {
name: {
title: 'Name',
width: '35%'
},
phone: {
title: 'Phone',
width: '15%'
},
yrsexp: {
title: 'Experience',
width: '15%'
}
}
});
$('#jTableTest').jtable('load');
});
Sorting and paging are both SERVER side operations. You need slight changes on both client and server.
On the client, in this example you don't need to write your own deferred function, Just give jTable the URL. It will then pass, paging (jtStartIndex and jtPageSize) and sorting (jtSorting) parameters to the server. These parameters are in the jtParams argument passed to the deferred function, so you have to forward them in you ajax call.
One the server, you need to respond to these sorting and paging parameters. Do note, that on a paged reply, TotalRecordCount is the total number of unpaged records. not the number returned. It is used by jTable to show the total number of pages.
I'm trying to populate a jqgrid using data from my [HttPost] controller method.
my controllers look like this
Public ActionResult Index()
{
SearchModel sm = new SearchModel();
// gets specific data from sm here
return View(sm);
}
[HttpPost]
Public ActionResult Index(SearchModel sm)
{
// does some stuff with the entered data from the form to return search results
// not sure what exactly to do here....
}
My form looks like this:
#model SearchModel
#{
//layout stuff and other script links are here
}
{Html.EnableClientValidation();}
#using (Html.BeginForm("Index", "Page",
FormMethod.Post, new { id = "search-form" }))
{
//I have the form and post data here
}
#if (Model.SearchRecords != null)
{
Html.RenderPartial("SearchRecordsPartial");
}
My Partial where the jqgrid is looks like this:
#model SearchModel
<div>
<table id="list" class="scroll" cellpadding="0" cellspacing="0"></table>
<div id="pager" class="scroll" style="text-align:center;"></div>
</div>
The jquery:
$(function () {
$("#list").jqGrid({
url: '/Page/Index/',
datatype: 'json',
mtype: 'GET',
colNames: ['Id', 'Votes', 'Title'],
colModel: [
{ name: 'Id', index: 'Id', width: 40, align: 'left' },
{ name: 'Votes', index: 'Votes', width: 40, align: 'left' },
{ name: 'Title', index: 'Title', width: 400, align: 'left'}],
pager: jQuery('#pager'),
rowNum: 10,
rowList: [5, 10, 20, 50],
sortname: 'Id',
sortorder: "desc",
viewrecords: true,
imgpath: '/content/themes/ui-lightness/images',
caption: 'Appeal Case Records'
});
});
Any help or links to how to do this would be awesome. I've tried searching online for helps and there is a lot of different articles but I can't seem to find one that uses asp.net mvc with populating a jqgrid from form data.
Thanks,
Here's a good link:
Using jQuery Grid With ASP.NET MVC
I'm putting together an MVC4 jqGrid, and this helped me out quite a bit.
EDIT:
Just to add a bit more color, I don't think you want to return your grid results in your Index action. jQgrid is going to call the url you specify whenever it needs to load new data - as a result of sorting, searching, refreshing, etc... If you take a look at the article I linked, it goes into this in some more detail.
If you just want to show data in grid, you can use below code, but if you want to use the functionality like add, edit, delete, filter, sort,etc this code is not enough, please specify the requirments in details.
[HttpPost]
Public ActionResult Index(SearchModel sm)
{
List<Object> returnData = new List<Object>();
returnData.Add(new { id = 1, cell = new string[] {"Id1","Votes1","Title1"} });
returnData.Add(new { id = 2, cell = new string[] {"Id2","Votes2","Title2"} });
returnData.Add(new { id = 3, cell = new string[] {"Id3","Votes3","Title3"} });
var result = new { total = 1, page = 1, records = 3, rows = returnData };
return Json(result, JsonRequestBehavior.AllowGet);
}
You should pass the sorting and paging parameters in that controller action
[HttpPost]
public ActionResult ListCustomer(string sidx, string sord, int page, int rows)
{
// return the json data
}
I m using kendo drop down box to my web page. This is my java script function.
function BindNonEventDownList(_propertyId, _url, _textField, _valueField) {
$(_propertyId).kendoDropDownList({
optionLabel: '<%= Resources.ResourceiChain.Select %>',
dataTextField: _textField,
dataValueField: _valueField,
dataSource: {
type: "json",
serverFiltering: true,
transport: {
read: _url
},
schema: {
data: "Data",
total: "Count"
}
}
});
}
This is my Response.
{"Data":[],"Count":0}
I want to get this count to a variable. How can I do it?
You can use the total method of the data source:
var dropdown = $(_propertyId).data("kendoDropDownList");
var count = dropdown.dataSource.total();
However make sure the data has been received when you call the total method. Otherwise it will return 0.
I found the answer......First intialized the datasource. Then using data.length you can get the length of the data..
function BindNonEventDownList(_propertyId, _url, _textField, _valueField) {
var dataSource = new kendo.data.DataSource({
transport: {
read: _url
},
schema: {
data: "Data",
total: "Count"
}
});
dataSource.fetch(function(){
var data = this.data();
console.log("data:"+data.length);
});
$(_propertyId).kendoDropDownList({
optionLabel: '<%= Resources.ResourceiChain.Select %>',
dataTextField: _textField,
dataValueField: _valueField,
dataSource: dataSource
});
}
I have a GridPanel that must have its store model AND column model created dynamically, after a DB SP returns the columns of the table.
My question is how can I pass the value ( string or JSON )s from the server to the GridPanel?
Ext.define('Base.GridPanel', {
extend: 'Ext.grid.Panel',
xtype: 'gridpanel',
flex: #BFE.Frontend.Defaults.BaseGridPanel.flex,
hideMode: '#BFE.Frontend.Defaults.BaseGridPanel.hideMode',
collapsible: true,
constructor: function(id, title, columns, store)
{
this.id = id;
this.title = title;
this.columns = columns;
this.store = store;
this.callParent();
}
});
I use this custom defined GridPanel along with the following model and store for now.
Ext.define('Tasks', {
extend: 'Ext.data.Model',
fields:
[
{name: 'Case_ID', type: '#MCSJS.Models.DataType.Auto'},
{name: 'BP_Name', type: '#MCSJS.Models.DataType.Auto'},
{name: 'Project', type: '#MCSJS.Models.DataType.Auto'},
{name: 'Business_Unit', type: '#MCSJS.Models.DataType.Auto'},
{name: 'Task', type: '#MCSJS.Models.DataType.Auto'},
{name: 'Title', type: '#MCSJS.Models.DataType.Auto'},
{name: 'Last_Edit', type: '#MCSJS.Models.DataType.Auto'},
{name: 'Entity_Name', type: '#MCSJS.Models.DataType.Auto'},
{name: 'Process_Instance_ID', type: '#MCSJS.Models.DataType.Auto'},
{name: 'Start_of_Business', type: '#MCSJS.Models.DataType.Auto'},
{name: 'Last_User', type: '#MCSJS.Models.DataType.Auto'}
]
});
var myTaskStore = Ext.create('Ext.data.Store', {
storeId: 'myTasks',
model: 'Tasks',
autoLoad: true,
proxy:
{
type: 'ajax',
url: '/Task/GetMyTaskData',
reader:
{
type: 'json',
root: 'data'
}
}
});
This is how I create a GridPanel :
var columns = [ { text: 'Case ID', dataIndex: 'Case_ID' },
{ text: 'BP Name', dataIndex: 'BP_Name' } ];
new Base.GridPanel('#BFE.Frontend.MyTask.GridPanel', 'My Tasks', columns, myTaskStore)
Ext provides some support for that. You can send the model configuration by adding a metaData property to the server response. You can configure the name of the property with the metaProperty option.
The documentation doesn't make it obvious, but you can reconfigure the fields of the model this way. Here's the kind of response that would do that:
{
data: [...]
,metaData: {
// This will be recognized and processed automatically
// by the proxy
fields: [
{name: "id", type: "int"},
{name: "myField", type: "string"},
...
]
// This one is for our own usage, see bellow
,columns: [
{dataIndex: "id", text: "ID},
{dataIndex: "myField", text: "My field"},
...
]
}
}
As noted in the doc, when the data model changes, you'll want to update your components as well. Sencha has provided the metachange for that. Notice that, while documented in the proxy, this event will be relayed by the store.
Finally, to update the grid's column model, you have the reconfigure method. For example, you could modify your grid class in the following way to make it reconfigure itself automatically from the server response:
Ext.define('Base.GridPanel', {
extend: 'Ext.grid.Panel'
// ...
// You can add your listener in initComponent, if you're
// reluctant to extend a method docuemented as private...
,bindStore: function(store) {
// unbind previously bind store, if any
var previous = this.getStore();
if (previous) {
previous.un('metachange', this.onMetaChange, this);
}
// bind to the meta change event
this.getStore().on('metachange', this.onMetaChange, this);
this.callParent(arguments);
}
,onMetaChange: function(store, meta) {
var columns = meta.columns;
if (columns) {
this.reconfigure(null, columns);
}
}
});
Update
The onMetaChange method is called when the metachange event is fired, because I have registered it as a listener with this line:
this.getStore().on('metachange', this.onMetaChange, this);
The event itself is fired when the proxy detects some meta data in the server response. Concretely, that happens when a metaData property (or whatever name you may have configured as the metaProperty of the proxy) exists in the server response.
The listener is effectively passed the raw metaData object, that is present in the response, as its second argument (named meta in my example). So your server can put any information you need in it (e.g. new field labels, tooltip texts, etc.).
bindStore is a method that is already present in GridPanel. Here I override it because I need a place to register my event listener on the store. As its name suggests, this method is called to bind a store to the component. It can be the initial store, or a new one. That's one I've preferred to override this method instead of initComponent. In case the store is changed later in the component life, my custom listener will be unbound from the old store and attached to the new one.
The arguments keyword is an idiosyncrasy of Javascript. It represents all the arguments that have been passed to a function. callParent is a sweety provided by Ext to call the parent method; it takes an array as the arguments that will be passed to the parent. So this.callParent(arguments) calls the parent method without having to know what were precisely all the arguments of the overridden method. That's easier, and that's also more resilient to future changes, if the arguments of the method were to change...
I'd be glad to point you to a comprehensive guide about overriding in Ext... Unfortunately I couldn't find one with a quick search :-/
I'm using Kendo UI Autocomplete with an ASMX Service which returns a string array like this :
<ArrayOfString>
<string>One string</string>
...
</ArrayOfString>
All works fine except that the items list opens twice. One click close one list and the "second behind" is still open.
When the list's opening we can see the second list opens behind the first.
Any idea ?
JS Code:
<input id="autoCompleteTest" />
<script>
var dataSource = new kendo.data.DataSource({
serverFiltering: true,
transport: {
read: {
data: {
startswith: function(){
return $("#autoCompleteTest").data("kendoAutoComplete").value();
}
},
url: "WebService.asmx/GetStrings",
type: "POST",
}
},
schema: {
// specify the the schema is XML
type: "xml",
// the XML element which represents a single data record
data: "/ArrayOfString/string",
// define the model - the object which will represent a single data record
model: {
// configure the fields of the object
fields: {
// the "title" field is mapped to the text of the "title" XML element
value: "text()"
}
}
}
});
$("#autoCompleteTest").kendoAutoComplete({
minLength: 3,
dataValueField : "value",
dataTextField : "value",
dataSource: dataSource
});
</script>
C# Code:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public String[] GetStrings(string startswith)
{
using (var dataContext = new DataClassesDataContext())
{
var query = from x in dataContext.product where x.shortName.StartsWith(startswith) select x.shortName;
return query.ToArray();
}
}
I've run into a similar issue and posted here
Please confirm that your autocomplete control is not located inside of another control that forces the Kendo control to render a second time.
do you client code when dom is ready for kendo multiselect:
$(document).ready(function () {
..yourcode.});
see: http://docs.telerik.com/kendo-ui/controls/editors/multiselect/overview#accessing-an-existing-multiselect