Using ASP.NET MVC action method to return Json to a view in order to display the data in a EXT JS form. I am always getting the "record" value as null in the function everythingLoaded even though i can see the action method is returning the JSON data after the Ext.Create. What i am trying to achieve is populate the firstName and lastName param's passed back from the action method to the textbox inside the panel. Can you help? Below is the code
->App.JS
Ext.onReady(function() {
//Define Store
Ext.define('StudentModel', {
extend: 'Ext.data.Model',
idProperty: 'Id',
fields: [
{ name: 'Id', type: 'int' },
{ name: 'firstName', type: 'string' },
{ name: 'lastName', type: 'string' },
{ name: 'birthDate', type: 'date' },
{ name: 'street', type: 'string' },
{ name: 'apartment', type: 'string' },
{ name: 'city', type: 'string' },
{ name: 'state', type: 'string' },
],
validations: [{
type: 'presence',
field: 'firstName'
}]
});
var store = Ext.create('Ext.data.Store', {
model: 'StudentModel',
storeId: 'StudentStoreId',
proxy: {
type: 'ajax',
url: '/Home/GetStudentSubmissions',
reader: {
type: 'json',
rootProperty: 'data'
}
},
autoLoad: { callback: everythingLoaded }
}
);
function everythingLoaded()
{
var record = store.getAt(0);
//Here record is always null
Ext.form('MyPanel').getForm().loadRecord(record);
}
Ext.define('StudentView', {
extend: 'Ext.form.Panel',
id: 'MyPanel',
alias: 'widget.StudentView',
title: 'Student Information',
resizable: false,
collapsible: true,
store:store,
bodyPadding: '5',
buttonAlign: 'center',
border: false,
trackResetOnLoad: true,
layout: {
type: 'vbox'
},
defaults: {
xtype: 'textfield',
msgTarget: 'side',
labelAlign: 'top',
labelStyle: 'font-weight:bold'
},
items: [{
xtype: 'fieldcontainer',
layout: 'hbox',
defaultType: 'textfield',
width: '100%',
fieldDefaults: {
labelAlign: 'top',
labelStyle: 'font-weight:bold'
},
items: [{
fieldLabel: 'First Name',
name: 'firstName',
allowBlank: false
}, {
fieldLabel: 'Last Name',
name: 'lastName',
allowBlank: false
}]
}]
});
//Here count is always 0
var i = store.getCount();
Ext.create('widget.StudentView', {
renderTo: 'studentMasterForm'
});
});
-> C# Action Method
public JsonResult GetStudentSubmissions()
{
return Json(GetStudents(), JsonRequestBehavior.AllowGet);
}
public Student GetStudents()
{
Student studobj = new Student();
studobj.Id = 1;
studobj.firstName = "Aravind";
studobj.lastName = "R";
studobj.state = "NJ";
studobj.street = "Center Grove";
studobj.birthDate = new DateTime(1989, 6, 6);
studobj.apartment = "DD8";
studobj.city = "XYZ";
return studobj;
}
}
->Student Model Class
public class Student
{
public int Id { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public DateTime birthDate { get; set; }
public string street { get; set; }
public string apartment { get; set; }
public string city { get; set; }
public string state { get; set; }
}
Your c# code returns one object "Student", but it is supposed to return an object which have an array of students as its "data" property.
You need to return an object of this type:
public class ExtStore
{
public List<Student> data = new List<Student>();
}
this way for example:
public ExtStore GetStudents()
{
Student studobj = new Student();
studobj.Id = 1;
studobj.firstName = "Aravind";
studobj.lastName = "R";
studobj.state = "NJ";
studobj.street = "Center Grove";
studobj.birthDate = new DateTime(1989, 6, 6);
studobj.apartment = "DD8";
studobj.city = "XYZ";
ExtStore exs = new ExtStore();
exs.data.Add(studobj);
return exs;
}
Related
In my kendo grid the update button does not work after I edit through pop up editor ,"result" is a Ajax call response, since I do not use services I don't need the "read" part that's why I commented it,
DataSource Initialization:
dataSource = new kendo.data.DataSource({
transport: {
//read: {
// url: result,
// dataType: "json"
//},
update: {
url: "/AdminTool/update_grid",
dataType: "json"
},
parameterMap: function (options, operation) {
if (operation !== "read" && options.models) {
return { models: kendo.stringify(options.models) };
}
}
},
batch: true,
pageSize: 20,
schema: {
model: {
id: "DeviceIP",
fields: {
DeviceIP: { editable: false, nullable: true },
Producer: { type: "string" },
Model: { type: "string" },
DeviceType: { type: "string" },
Description: { type: "string" },
Username: { type: "string" },
Password: { type: "string" },
PublicIP: { type: "string" },
}
}
}
});
Kendo Grid Initialization:
$("#turbingrid").kendoGrid({
dataSource: result,
scrollable: false,
columns: [
{ field: 'DeviceIP', title: 'DeviceIP', width: '100px', id: 'DeviceIP' },
{ field: 'Producer', title: 'Producer', width: '80px', editor: ProductNameDropDownEditor, },
{ field: 'Model', title: 'Model', width: '120px' },
{ field: 'DeviceType', title: 'DeviceType', width: '100px', editor:deviceTypesList },
{ field: 'Description', title: 'Description', width: '100px' },
{ field: 'Username', title: 'Username',width:'120px' },
{ field: 'Password', title: 'Password', width: '100px' },
{ field: 'PublicIP', title: 'PublicIP', width: '120px' },
{ command: ["edit"], title: " ", width: "100px" }],
editable: "popup",
edit: function() {
document.getElementsByName("DeviceIP")[0].disabled = true;
},
editable: "popup"
});
Column Editors:
function ProductNameDropDownEditor(container, options) {
$('<input name="Producer" data-type="string"\">')
.appendTo(container)
.kendoDropDownList({
valuePrimitive: true,
dataSource: mydata,
dataTextField: "Text",
dataValueField: "Text",
});
}
function deviceTypesList(container, options) {
$('<input name="DeviceType" data-type="string" \">')
.appendTo(container)
.kendoDropDownList({
dataSource: mydata_deviceType,
dataTextField: "Text",
dataValueField: "Text",
//dataValueField: "ProductName",
});
}
My Controller:
[HttpPost]
public ActionResult update_grid(TurbineDvce frm)
{
try
{
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
The Model I want to pass
public class TurbineDvce
{
public string TurbineId { get; set; }
public string DeviceIP { get; set; }
public string Producer { get; set; }
public string Model { get; set; }
public string DeviceType { get; set; }
public string Comments { get; set; }
public string Description { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string PublicIP { get; set; }
}
Use the parameterMap function to specify what data you wish to send to the controller function when editing each individual Kendo Grid row.
You can also specify within the function different methods of returning data based on the operation type.
In your case, an example would be like:
transport: {
update: {
url:"/AdminTool/update_grid",
dataType: "json"
},
parameterMap: function (data, operation) {
if(operation !== "read" && data) {
return kendo.stringify(data);
}
}
}
your controller action method is expecting parameter name "frm". So it will be like
parameterMap: function(options, operations){
if(operation !== "read" && options{
return {frm: options}
}
}
I am trying to display a table of data returned by the following restful web api service accessible by this url. The problem is it displays only the header of the table and not the content.
/SMART/api/Build/GetAll
This url will return as output an IList of object called release, I have already tested this. The release object is structured as follows.
[Table("releases")]
public class Release
{
[Key]
public int Id { get; set; }
[StringLength(10)]
[Column("Name")]
public string Name { get; set; }
[StringLength(10)]
[Column("Type")]
public string Type { get; set; }
[Column("to_be_displayed")]
public bool ToBeDisplayed { get; set; }
}
Here is my javascript code
$.ajax({
type: 'GET',
url: '/SMART/api/Build/GetAll',
dataType: 'json',
contentType: "application/json",
success: function (data) {
alert(data);
// Get the JSON Data
var Data = new kendo.data.DataSource({
schema: {
model: {
id: "release.id",
fields: {
id: { type: "string" },
Name: { type: "string" },
Type : {type : "string"},
ToBeDisplayed: { type: "boolean" },
}
}
}
});
//Create a tab for the wip release
$('#listGrid').kendoGrid({
scrollable: false,
sortable: true,
resizable: true,
filterable: true,
autoSync: true,
dataSource: Data,
columns: [
{ field: "release.id", title: "Id" },
{ field: "release.Name", title: "Name" },
{ field: "release.ToBeDisplayed", title: "To be displayed", template: "<input name='ToBeDisplayed' type='checkbox' data-bind='checked: ToBeDisplayed' #= ToBeDisplayed ? checked='checked' : '' # class='build-tobedisplayed-checkbox'/>" },
]
});
}
});
Here is my cshtml code
<div id="listGrid" class="k-grid-content">
<div class="k-loading-mask" style="width:100%;height:100%"><span class="k-loading-text">Loading...</span><div class="k-loading-image"><div class="k-loading-color"></div></div></div>
</div>
Try the following Code:
function definitionUserGrid() {
var baseUrl = '/SMART/api/Build/GetAll';
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: baseUrl,
dataType: "json"
},
parameterMap: function (options, operation) {
if (operation !== "read" && options.models) {
return {
models: kendo.stringify(options.models)
};
}
}
},
batch: true,
pageSize: 15
});
$("#listGrid").kendoGrid({
dataSource: dataSource,
pageable: true,
reorderable: true,
resizable: true,
sortable: true,
filterable: {
mode: "row"
},
columns: [
{field: "Id",
title: "Id",
}, {
filterable: {
cell: {
enabled: true,
showOperators: false,
operator: "contains"
}
},
field: "Name",
title: "Name"
}, {
filterable: {
cell: {
enabled: true,
showOperators: false,
operator: "contains"
}
},
field: "ToBeDisplayed",
title: "To be displayed",
template: "<input name='ToBeDisplayed' type='checkbox' data-bind='checked: ToBeDisplayed' #= ToBeDisplayed ? checked='checked' : '' # class='build-tobedisplayed-checkbox'/>" },
}]
});
}
And finally:
call function definitionUserGrid()
$(function(){
definitionUserGrid();
});
I have two entities, sent from two different APIs, with a one to one relationship.
I want to load both models in the same grid panel. The problem is that I can only load one store. To load the other store, I attached a callback to the grid reload event which edits the grid DOM manually to insert data form the second store.
My Question is: Can I load both the model and the association without using DOM hacks like I did?
The entities from APIs look like this:
Get /Users/Details:
{
"Id" : "55b795827572761a08d735ac",
"Username" : "djohns",
"Email" : "admin#mail.com",
"FirstName" : "Davey",
"LastName" : "Johns"
}
And:
Get /Users/Rights:
{
"_id" : "55b795827572761a08d735ac",
"Status" : "Activated",
"Roles" : [
"portal",
"dataApp"
]
}
Notice the same id, which is used in the API as the key/foreign key).
Now these are the models:
Ext.define('Portal.model.users.UserRights', {
extend: 'Ext.data.Model',
fields: [
{
name: 'id',
mapping: 'Id'
},
{
name: 'Status'
},
{
name: 'UserId',
mapping: 'Id',
reference: 'Portal.model.users.UserDetails'
}
],
schema: {
namespace: 'Portal.model.users',
proxy: {
type: 'rest',
url: Portal.util.Util.constants.apiBaseURL + 'Users/Rights',
reader: {
type: 'json',
rootProperty: 'Objects'
}
}
}
});
And:
Ext.define('Portal.model.users.UserDetails', {
extend: 'Ext.data.Model',
fields: [
{
name: 'id',
mapping: 'Id'
},
'FirstName',
'LastName',
'Username',
'Email'
],
});
And I defined a store for user details (while the store of the user rights is inside its own model):
Ext.define('Portal.store.UsersDetails', {
extend: 'Ext.data.Store',
model: 'Portal.model.users.UserDetails',
proxy: {
type: 'rest',
url: Portal.util.Util.constants.apiBaseURL + 'Users/Details',
reader: {
type: 'json',
rootProperty: 'Objects'
}
}
});
Here is how I configured the Grid:
Ext.define('Portal.view.users.UsersGrid', {
extend: 'Ext.grid.Panel',
store: 'UsersDetails',
columns: [
{
dataIndex: 'id',
text: 'Id'
},
{
dataIndex: 'Username',
text: 'Username'
},
{
dataIndex: 'Email',
text: 'Email'
},
{
dataIndex: 'FirstName',
text: 'First Name'
},
{
dataIndex: 'LastName',
text: 'Last Name'
},
{
text: "Status",
cls: "status-column",
renderer: function (value, meta, record) {
return "loading...";
}
}
],
loadUserRights: function () {
var columns = this.getEl().select('.status-column');
var cells = this.getEl().select(".x-grid-cell-" + columns.elements[0].id + " .x-grid-cell-inner");
data = this.getStore().getData();
Ext.each(data.items, function (record, index) {
var userRights = record.userUserRights();
userRights.load({
callback: function (records, operation, success) {
if (success) {
cells.elements[index].innerText = userRights.data.items[0].data.Status;
}
}
});
});
}
});
And then I load the gird from an external function:
grid.getStore().reload({
callback: function (records, operation, success) {
grid.loadUserRights();
}
});
this is my kendogrid code :
KendoDemosFactory.controller("MyCtrl", function ($scope, $sessionStorage) {
$scope.mainGridOptions = {
dataSource: {
transport: {
read: {url:"/User/GetUserDetail",datatype:"json"},
update: { url: "/User/UpdateUser", type: "POST" },
destroy:{ url:"/User/DeleteUser",type:"POST"},
Create:{url:"/User/CreateUser",type:"POST"}
},
parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
return {models: kendo.stringify(options.models)};
}
},
batch: true,
pageSize: 5,
serverPaging: false,
serverSorting: false
},
sortable: true,
pageable: true,
navigatable: true,
toolbar: ["create", "save", "cancel"],
dataBound: function () {
this.expandRow(this.tbody.find("tr.k-master-row").first());
},
columns: [{
field: "FirstName",
title: "First Name",
width: "80px"
}, {
field: "LastName",
title: "Last Name",
width: "80px"
}, {
field: "Address",
width: "80px"
}, {
field: "Email",
width: "100px"
}, {
field: "Gender",
width: "80px"
},
{
field: "Salary",
width:"100px"
},
{ command: "destroy", title: " ", width: 100 }
],
editable:true
};
})
and here is my controller with my userlist and all the methods :
public ActionResult GetUserDetail()
{
IList<UserModel> userList = new List<UserModel>()
{
new UserModel{
id=1,
FirstName = "Pawan",
LastName = "Kapoor",
Address = "Mohali",
Email = "test#test.com",
Gender = "Male",
Salary = 25000
},
new UserModel
{
id=2,
FirstName = "Ayan",
LastName = "Banerjee",
Address = "Bangalore",
Email = "test1#test.com",
Gender = "Male",
Salary = 30000
},
}
}
[HttpPost]
public ActionResult CreateUser()
{
IList<UserModel> userList = new List<UserModel>();
return Json(userList, JsonRequestBehavior.AllowGet);
}
[HttpPost]
public ActionResult UpdateUser()
{
IList<UserModel> userList = new List<UserModel>();
return Json(userList, JsonRequestBehavior.AllowGet);
}
[HttpPost]
public ActionResult DeleteUser()
{
IList<UserModel> userList = new List<UserModel>();
return Json(userList, JsonRequestBehavior.AllowGet);
}
My kendo Grid is populating fine with editable functionality and all the CRUD controls but i am not able to bind data with the controller using CRUD Methods(they are not getting hit and any crud functionality is not getting persisted). Please help
Let me give you a few notes to correct your your code.
If you do not want to make batch update, send to controller only the current row.
parameterMap: function (options, operation) {
if (operation !== "read" && options.models) {
return { models: options.models[0] };
}
}
Correct your update action method as follows: MVC will bind the data send from grid into UserModel.
[HttpPost]
public ActionResult UpdateUser(UserModel model)
{
// do something with model
return Json(model, JsonRequestBehavior.AllowGet);
}
This link will lead you to solve your problem
i want to submit a form using Ext.Direct and iam following all the guidelines present in the documentation still im getting this weird error
Error: Ext.data.Connection.setOptions(): No URL specified
this is the javascript code of my form
Ext.define('LOGIN.view.SignIn', {
extend: 'Ext.form.Panel',
alias: 'widget.signin',
title: 'Sign-In',
items: [{
xtype: 'textfield',
name: 'UserName',
fieldLabel: 'UserName',
allowBlank: 'false'
}, {
xtype: 'textfield',
name: 'Password',
fieldLabel: 'Password',
allowBlank: 'false',
inputType: 'password'
}],
buttons: [{
text: 'Sign-In',
handler: function () {
this.up('form').getForm().submit({});
}
}, {
text: 'Sign-Up -->',
disabled: true,
handler: function () {
this.up('#LoginPanel').getLayout().setActiveItem(1);
}
}],
api: {
submit: LogIn.SignIn
}
})
what should i change?
I found out the answer digging into the framework.
I need to use the following code and define the api in the constructor because I guess this particular intialConfig isn't automatically taken
Here is the code
Ext.define('LOGIN.view.SignIn', {
extend: 'Ext.form.Panel',
alias: 'widget.signin',
title: 'Sign-In',
constructor: function (config) {
Ext.applyIf(config, {
// defaults for configs that should be passed along to the Basic form constructor go here
api: {
submit:LogIn.SignIn
}
});
this.callParent(arguments);
},
items: [{
xtype: 'textfield',
name: 'UserName',
fieldLabel: 'UserName',
allowBlank: 'false'
}, {
xtype: 'textfield',
name: 'Password',
fieldLabel: 'Password',
allowBlank: 'false',
inputType: 'password'
}],
buttons: [{
text: 'Sign-In',
handler: function () {
this.up('form').getForm().submit();
}
},
{
text: 'Sign-Up -->',
disabled: true,
handler: function () {
this.up('#LoginPanel').getLayout().setActiveItem(1);
}
}]
})
One thing to look out for here.
If you are using extdirectspring you will need to annotate your server side method with:
#ExtDirectMethod(ExtDirectMethodType.FORM_POST)
public ExtDirectFormPostResult doStuff(AddAttachmentRequest request)
{
return null;
}
It is also mandatory to use ExtDirectFormPostResult aswell. If you don't it just wont work.
If you use a normaly extdirect method then no file data will be sent.
It also looks like the type you need on the other end is MultipartFile eg something like:
public class AddAttachmentRequest {
private long id;
private MultipartFile file;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public MultipartFile getFile() {
return file;
}
public void setFile(MultipartFile file) {
this.file = file;
}
}