I am using kendo ui grid with Inline editing and it works fine but when i change editor mode to PopUp, it does not display the Customeditor fields(i.e.PickUpLocation) in edit window and show only fields other then customeditor template from model. What I am doing wrong here?
Shipping.cshtml (Main View contains Grid)
#(Html.Kendo().Grid<Comanex.Models.ShippingInstructionViewModel>()
.Name("ShippingGrid")
.Columns(c =>{
c.Bound(m => m.Id).Hidden();
c.Bound(m => m.LocationViewModel)
.ClientTemplate("#=LocationViewModel.LocationName#")
.Title("Pickup Location");
c.Bound(m => m.UnitsShipped)
c.Command(p =>
{
p.Edit();
p.Destroy();
});
})
.ToolBar(toolbar =>{toolbar.Create().Text("").HtmlAttributes(new { #title = "Add" });})
.Editable(editable => editable.Mode(GridEditMode.PopUp))
.Events(events =>{events.Edit("edit");events.Save("save");})
.DataSource(dataSource => dataSource
.Ajax()
.Create(create => create.Action("ShippingInstruction_Insert", "InHouseShipping"))
.Read(read => read.Action("ShippingInstruction_Read", "InHouseShipping"))
.Update(update => update.Action("ShippingInstruction_Update", "InHouseShipping"))
.Destroy(destroy => destroy.Action("ShippingInstruction_Delete", "InHouseShipping"))
.Model(m =>{m.Id(p => p.Id);
m.Field(p => p.LocationViewModel).DefaultValue(ViewData["DefaultPickUpLocation"] as Comanex.Models.LocationViewModel);
})
)
)
ShippingInstructionViewModel.cs (Model that display the data to grid)
public class ShippingInstructionViewModel
{
[ScaffoldColumn(false)]
public int Id { get; set; }
[Required]
[UIHint("PickUpLocationEditor")]
public LocationViewModel LocationViewModel { get; set; }
[Required]
[Display(Name = "Units Shipped")]
[DisplayFormat(DataFormatString = "{0:n0}")]
public Nullable<decimal> UnitsShipped { get; set; }
}
PickUpLocationEditor.cshtml (My Custom Editor DropDownListFor)
#model Comanex.Models.LocationViewModel
#(Html.Kendo().DropDownListFor(m => m)
.OptionLabel("Select..")
.DataValueField("LocationId")
.DataTextField("LocationName")
.AutoBind(false)
.DataSource(d =>
{
d.Read(r => r.Action("GetShippingPickUpLocations", "ProductionZone"))
.ServerFiltering(true);
})
.Events(evnt=>evnt.Cascade("onCascade")) //Need to add this Event on Parent Drop Downs
)
#Html.ValidationMessageFor(m => m)
Here in edit window, only UnitShipped field is displayed and PickUpLocation dropdownlist is not showing. Why?
By default the MVC does not generate editor template for nested objects. You can try and do the same in a separate view where EditorForModel is used (the Grid uses exactly this). To customize the popup editor check this code library.
Related
I'm trying to use a Kendo grid with inline editing but my data does not change on pressing update. Other columns have no problem, but the drop down data is not updated.
My model class is:
public class Validation
{
public string ParentParameterName { get; set; }
public string ParameterName { get; set; }
public string ParameterTitle { get; set; }
[UIHint("DataTypeList")]
public string DataType { get; set; }
[UIHint("EvetHyir")]
public string Required { get; set; }
public List<Validation> Value { get; set; }
}
My grid is:
#(Html.Kendo().Grid<Validation>()
.Name("keyJsonGrid")
.Columns(columns =>
{
columns.Bound(model => model.ParentParameterName).Title("Ana parametre ünvanı");
columns.Bound(model => model.ParameterTitle).Title("Parametre ünvanı");
columns.Bound(model => model.ParameterName).Title("Parametre Adı");
//columns.Bound(foo => foo.DataType).Title("TİP").EditorTemplateName("DataType").Sortable(false);
columns.Bound(p => p.DataType).Sortable(false).Width(180).EditorTemplateName("DataTypeList");
columns.Command(command => { command.Edit().Text("Düzenle"); command.Destroy().Text("Sil"); }).Width(250);
})
.Resizable(builder => builder.Columns(true))
.ToolBar(toolbar => toolbar.Create().Text("Yeni Ekle"))
.Editable(editable => editable
.Mode(GridEditMode.InLine)
.ConfirmDelete("Silinmesine emin misiniz?")
.DisplayDeleteConfirmation("Silinmesine emin misiniz?")
)
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(new int[] { 10, 25, 50, 75, 100 })
)
.Sortable(x => x.SortMode(GridSortMode.MultipleColumn))
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("GetJsonKeyList", "Key", new { KeyId = Model }))
.PageSize(25)
)
)
My dropdown is populated from an enum:
#(Html.Kendo().DropDownList()
// The name of the widget has to be the same as the name of the property.
.Name("DataType")
// The value of the drop-down is taken from the EmployeeID property.
.DataValueField("Text")
.DataTextField("Text")
.AutoBind(true)
// The text of the items is taken from the EmployeeName property.
.ValuePrimitive(true)
// A list of all employees which is populated in the controller.
.BindTo((System.Collections.IEnumerable)ViewData["DataTypes"])
)
Dropdown data population code:
KeyJsonDTO.DataType x = KeyJsonDTO.DataType.Integer;
ViewData["DataTypes"] = EnumToSelectList(x.GetType());
static List<SelectListItem> EnumToSelectList(Type enumType)
{
return Enum.GetValues(enumType)
.Cast<int>()
.Select(i => new SelectListItem
{
Value = i.ToString(),
Text = Enum.GetName(enumType, i),
})
.ToList();
}
When I press the "Edit" button, the dropdown does not show correct data, and when I press update data, it does not update.
I doubt you are actually using the dropdown you created. "DataType" is not the name of the field. It is the name of the editor template you save in the file system. You can use controls on page but as far as i know, only if it's a javascript grid. You need to make an editor template in the appropriate folder and change the definition of the control to be an dropdownfor(m => m). Then you don't have to name it.
I am trying to use Kendo MultiSelect in a Kendo Grid with ASP.NET MVC.
I don't specifically need the column with the MultiSelect to be visible in the grid, but I need to be able to edit it in popup view.
When the grid loads, the column with the MultiSelect has the value of [object Object] and when I click on edit to open the popup, the MultiSelect doesn't show in the popup at all.
When I change the edit mode of the grid to inline or incell and press edit, the MultiSelect appears in column with the correct preselected values for each object from the database as well as the correct bounded list of values from ViewData.
I can't figure out what I am doing wrong.
Here is my code:
The ViewModels:
public class QMKeyVM
{
[HiddenInput(DisplayValue = false)]
public int Id { get; set; }
[StringLength(100)]
public string Code { get; set; }
[StringLength(255)]
public string Title { get; set; }
[UIHint("Enum")]
public ScopeType Scope { get; set; }
[UIHint("InstituteTypes_MultiSelect")]
public List<InstituteTypeVM> InstituteTypes { get; set; }
}
public class InstituteTypeVM
{
public int Id { get; set; }
public string Name { get; set; }
}
The editor template file InstituteTypes_MultiSelect.cshtml for MultiSelect:
#(Html.Kendo().MultiSelect()
.Name("InstituteTypes")
.DataValueField("Id")
.DataTextField("Name")
.Filter("contains")
.HtmlAttributes(new { style = "width:250px;height:50px" })
.BindTo((IEnumerable<InstituteTypeVM>)ViewData["InstituteTypes"])
.HtmlAttributes(new { data_value_primitive = false })
)
The grid in the View:
#(Html.Kendo().Grid<QMKeyVM>()
.Name("QMKeysGrid")
.Columns(columns =>
{
columns.Bound(p => p.Id).Hidden();
columns.Bound(p => p.Code);
columns.Bound(p => p.Title);
columns.Bound(p => p.Scope).EditorTemplateName("Enum");
columns.Bound(p => p.InstituteTypes).EditorTemplateName("InstituteTypes_MultiSelect");
})
.Pageable(p =>
{
p.Messages(m => m.Page("Page").Empty("No entries").ItemsPerPage("per page").Display("{0} to {1} from {2}"));
p.Refresh(true);
p.Input(true);
p.PageSizes(new int[] { 20, 50, 100, 200 });
})
.ClientDetailTemplateId("qmkeydetailtemplate")
.Sortable().Groupable(g => g.Messages(m => m.Empty("Grouping")))
.Scrollable(s => s.Height("auto"))
.Resizable(resize => resize.Columns(true))
.ToolBar(tools => tools.Excel())
.Excel(excel => excel
FileName("qmkeys.xlsx")
.Filterable(true)
.ProxyURL(Url.Action("Excel_Export_Save", "Grid"))
)
.Filterable(filterable => filterable
.Extra(false)
.Operators(operators => operators
.ForString(str => str.Clear()
.Contains("Contains")
)
.ForDate(dr => dr.Clear().IsEqualTo("ForDate"))
).Messages(m => m.Filter("Apply Filter").Clear("Clear Filter").Info("")))
.ToolBar(toolbar =>
{
toolbar.Create().Text("Add QMKey");
toolbar.Custom().Text("Add Section").HtmlAttributes(new { id = "addSectionsBtn" });
toolbar.Custom().Text("Add Subsection").HtmlAttributes(new { id = "addSectionGroupsBtn" });
})
.Editable(editable => editable.Mode(GridEditMode.PopUp)
.Window(w => w.Title("Edit").Resizable().Draggable(true).Width(700))
.DisplayDeleteConfirmation("Confirm Delete"))
.Events(e => e.Edit("onEdit"))
.DataSource(dataSource => dataSource
.Ajax().ServerOperation(false)
.PageSize(200)
.Read(read => read.Action("QMKeysRead", "QMKeys"))
.Create(create => create.Action("QMKeyCreate", "QMKeys"))
.Update(update => update.Action("QMKeyUpdate", "QMKeys"))
.Destroy(destroy => destroy.Action("QMKeyDelete", "QMKeys"))
.Events(events => events.Error("GridOnError").RequestEnd("QMKeysGrid_OnRequestEnd"))
.Model(model =>
{
model.Id(p => p.Id);
})
).AutoBind(true).Deferred())
Thanks a lot.
Try to put Datasource property to fetch Data From Database
Below code will help you:
#(Html.Kendo().MultiSelect()
.Name("multiselect")
.DataTextField("ProductName")
.DataValueField("ProductID")
.Value(new[] { 2, 7 })
.DataSource(source =>
{
source.Read(read =>
{
read.Action("Products_Read", "Home");
})
.ServerFiltering(true);
})
)
I have tried to follow an example to get a foreign key into a grid. I followed this example:
http://demos.telerik.com/aspnet-mvc/grid/foreignkeycolumn
I have altered it a little bit because I want to use a Popup Editor.
Here is the Grid implementation in the View.
#(Html.Kendo().Grid<Example.Web.UI.ViewModels.ExampleItem>()
.Name("ExampleGrid")
.Columns(columns =>
{
columns.Bound(p => p.Name);
columns.Bound(p => p.Label);
columns.Bound(p => p.Type);
columns.Bound(p => p.InputType);
columns.ForeignKey(p => p.ParentId, (System.Collections.IEnumerable)ViewData["items"], "Id", "Name").Title("Parent");
columns.Command(command => { command.Edit(); command.Destroy(); });
})
.Scrollable()
.Groupable()
.Sortable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.PopUp))
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Events(events => events.Error("error_handler"))
.Model(model =>
{
model.Id(p => p.Id);
model.Field(p => p.Id).DefaultValue(Guid.NewGuid());
model.Field(p => p.ParentId).DefaultValue(null);
})
.Create(update => update.Action("EditingPopup_Create", "Example"))
.Read(read => read.Action("EditingPopup_Read", "Example"))
.Update(update => update.Action("EditingPopup_Update", "Example"))
.Destroy(update => update.Action("EditingPopup_Destroy", "Example"))
)
)
Here is the ExampeItem Model:
public class ExampleItem
{
[ScaffoldColumn(false)]
public Guid Id { get; set; }
public string Name { get; set; }
public string Label { get; set; }
public string Type { get; set; }
[DisplayName("Input Type")]
public string InputType { get; set; }
public ExampleItem Parent { get; set; }
public Guid ParentId { get; set; }
}
In my Controller I set the foreign key items like this:
ViewData["items"] = exampleItems; // This is a List<ExapleItem>
But for some reason the Parent column is empty when the Grid is loaded.
When I click on Edit a window pops up and shows me the Guid of the parent.
That Guid should be a drop down list of items. And the Parent column should show the name of the Parent item.
The idea of this grid is that you can add items to the grid, and when you do, you can choose any of the all ready added grid items as a parent item. Then creates an hierarchy in the Grid which can be sorted later on by the Parent.
Anyone know where I have gone wrong?
Not sure but as per my experience, you forgot to add editor template for the foreign key column.
As per your code you have to add default editor templates into your project.
For default editor template detail please check this for full code/demo.
You can also create your own editor template.
For ex:-
column definition for the Product
c.ForeignKey(x => x.ProductID, (List<Product>)ViewData["products"], "ID", "ProdName").EditorTemplateName("ProductIDEditor");
Here is the editor template for Product, ProductIDEditor.cshtml
#using Kendo.Mvc.UI
#(Html.Kendo().DropDownListFor(m => m)
.AutoBind(false)
.OptionLabel("Select a value...")
.DataTextField("ProdName")
.DataValueField("ID")
.DataSource(dataSource =>
{
dataSource.Read(read => read.Action("FilterProducts", "Home").Data("filterProducts"))
.ServerFiltering(true);
})
)
#Html.ValidationMessageFor(m => m)
Let me know if any concern.
So after trial and error I found the issue.
I changed my model to:
public class ProposalItem
{
[ScaffoldColumn(false)]
public int Id { get; set; }
public string Name { get; set; }
public string Label { get; set; }
public string Type { get; set; }
[DisplayName("Input Type")]
public string InputType { get; set; }
public ProposalItem Parent { get; set; }
[UIHint("GridForeignKey")]
public int? ParentId { get; set; }
}
So removed the Guid datatype from the Id. Also Decorated the ParentId with [UIHint("GridForeignKey")] which now gives me a DropdownList in the popup window.
It looks like there is a lack of Support for Guid's in KendoUI.
I will post another question as to why Guid's don't work.
Just add in :
.DataSource(source => source.Ajax()
.Model(model =>
{
model.Id(o => o.Id);
model.Field(o => o.Id).Editable(false);
model.Field(p => p.Id).DefaultValue(Guid.NewGuid());
model.Field(p => p.ParentId).DefaultValue(Guid.NewGuid());
**model.Field("ParentId", typeof(Guid));**
})
It has to do new Guid.
I have a KendoUI grid which allows the user to update the values using inline mode. The problem is that I have two double attributes that doesn't allow null values, but however the NumericTextBox give me to set an empty value, and then accept it, as you can see in the following image:
If you press "Aceptar" ("Accept") button the input stays empty, but it saves "0" in the database, and you can see it only when you refresh the page.
This is the code of the grid:
#(Html.Kendo().Grid<ReferenceThresholdVM>()
.Name("grdReference")
.Columns(columns =>
{
columns.Bound(t => t.txbTransponderName).Title("Transponder").Width(120);
columns.Bound(t => t.txbDataSourceName).Title("Variable").Width(200);
columns.ForeignKey(t => t.ddlReferenceTypeId, ReferenceTypeVM.GetComboList(), "Id", "Description").Title("Modo").Width(110);
columns.Bound(t => t.ntbThreshold).Title("Umbral").Width(100);
columns.Bound(t => t.ntbCurrentValue).Title("Valor de referencia").Format("{0:n2}").Width(170);
columns.Bound(t => t.ntbHysteresis).Title("Histeresis").Format("{0:n2}").Width(100);
columns.Bound(t => t.ntbThresholdTrigger).Title("Umbral de disparo").Format("{0:n2}").Width(150);
columns.Command(command =>
{
command.Edit().CancelText("Cancelar").UpdateText("Confirmar");
command.Destroy();
}).Width(220).HtmlAttributes(new { style = "text-align: center;" });
})
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Pageable()
.Navigatable()
.Sortable()
.Events(e => e.Save("onSave"))
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(12)
.ServerOperation(false)
.Events(events => events.Error("error_handler"))
.Model(model =>
{
model.Id(t => t.Id);
model.Field(t => t.Id);
model.Field(t => t.txbTransponderName).Editable(false);
model.Field(t => t.txbDataSourceName).Editable(false);
model.Field(t => t.ddlReferenceTypeId);
model.Field(t => t.ntbThreshold);
model.Field(t => t.ntbHysteresis);
model.Field(t => t.ntbCurrentValue).Editable(false);
model.Field(t => t.ntbThresholdTrigger).Editable(false);
})
.Read(read => read
.Action("Read_Reference", "Reference")
.Data("getFilterReference")
)
.Update("Reference_Update", "Reference")
.Destroy("Reference_Destroy", "Reference")
)
.Events(events => events.DataBound("onGrdReferenceDataBound"))
.AutoBind(false)
)
And each of this attributes is defined this way by using a UIHint that defines some behavior for the input:
[Display(Name = "Umbral")]
[UIHint("PositiveNumber")]
public double ntbThreshold
{
get;
set;
}
[Display(Name = "Histeresis")]
[UIHint("PositiveNumber")]
public double ntbHysteresis
{
get;
set;
}
and finally this is the code for the UIHint "PositiveNumber":
#model int?
#(Html.Kendo().NumericTextBoxFor(m => m)
.HtmlAttributes(new { #class = "k-numerictextbox" })
.Min(0)
.Max(int.MaxValue)
.Value(0)
)
Is there a way to disable the possibility the let the NumericTextBox empty?
The tooltip for .Value on the numeric Textbox says, "sets the initial value of the textbox". So that looks like why it is saving 0 in the db.
As per my comment, you might actually have to do something like this.
var numerictextbox = $("#numerictextbox").data("kendoNumericTextBox");
numerictextbox.value(0);
Thanks to everyone guys! I solve it by using the "Required" decorator on the attributes.
[Required] /*this is the important thing!*/
[Display(Name = "Umbral")]
[UIHint("PositiveNumber")]
public double? ntbThreshold
{
get;
set;
}
[Required]
[Display(Name = "Histeresis")]
[UIHint("PositiveNumber")]
public double? ntbHysteresis
{
get;
set;
}
So now, when you try to set an empty value it shows you a validation error. So if you want to set a 0 on the NumericTextBox, you'll have to write it.
I'm trying to follow the docs on how to make my kendo mvc grid ajaxified and able to support some in cell editing.
The problem I have is on save, I'm seeing the grid make the following request which is apparently not available. I'm not familiar with the models prefix stuff but it looks like the object is modeled in the URL properly with each property prefixed with &models, then some hash, then the parameter name and then the value.
Why doesn't this URL map to my controller action method?
"NetworkError: 404 Not Found -
http://localhost/MySite/UI/Orders/Update
?models%5B0%5D%5BId%5D=18c12470-0ca3-4e9c-b6d7-af1d6120e03f
&models%5B0%5D%5BNumber%5D=231413+
&models%5B0%5D%5BMod%5D=8ccbf70a-f368-434c-8c05-2e2f5278215d
&models%5B0%5D%5BModName%5D=M6G+++++++++++++++++++++++++++++++++++++++++++++++
&models%5B0%5D%5BDescription%5D=M6G+LMU+TTU1200
&models%5B0%5D%5BPart%5D=105442
&models%5B0%5D%5BPartDescription%5D=M6H+TELEMATICS+CONTROL+UNIT
&models%5B0%5D%5BQuantity%5D=20
&models%5B0%5D%5BDeliveryDate%5D=Tue+Apr+30+2013+00%3A00%3A00+GMT-0400+(Eastern+Daylight+Time)&_=1366818145016"
The Update method sig in the controller looks like this:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Update([Kendo.Mvc.UI.DataSourceRequest] Kendo.Mvc.UI.DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<Order> order)
{
//do update
}
And the sample Order object looks like this
public class Order
{
public Guid Id { get; set; }
public string Number{ get; set; }
public Guid Mod{ get; set; }
public string ModName{ get; set; }
public string Description { get; set; }
public int Part{ get; set; }
public string PartDescription { get; set; } // View Model Purposes Only
[Required]
[UIHint("QuantityEditor")] //QuantityEditor is the name of the custom editor template
public int Quantity { get; set; }
public DateTime DeliveryDate{ get; set; }
}
Here's the grid code ala MVC:
#(Html.Kendo().Grid(Model)
.Name("my-grid")
.Columns(columns =>
{
columns.Bound(m => m.Id)
.Hidden(true)
.HtmlAttributes(new { #class = "some-class" });
columns.Bound(m => m.Mod)
.Hidden(true)
.HtmlAttributes(new { #class = "some-class" });
columns.Bound(m => m.ModName)
.Hidden(true)
.HtmlAttributes(new { #class = "some-class" });
columns.Bound(m => m.Description).HtmlAttributes(new { #class = "some-class" });
columns.Bound(m => m.Part).HtmlAttributes(new { #class = "part can-edit" });
columns.Bound(m => m.PartDescription).HtmlAttributes(new { #class = "can-edit" });
columns.Bound(m => m.DeliveryDate).Format("{0:yyyy-MM-dd}").HtmlAttributes(new { #class = "date can-edit" });
columns.Bound(m => m.Quantity).HtmlAttributes(new { #class = "quantity can-edit" }).FooterTemplate("Total:");
})
.Scrollable(s => s.Height("auto"))
.Editable(editable => editable.Mode(GridEditMode.InCell))
.Events(events => events.DataBound("onDataBound"))
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.Update(update => update.Action("Update", "Orders"))
.Read(read => read.Action("GetAllOrders", "Orders").Data("getAdditionalData"))
.Aggregates(aggregates => { aggregates.Add(p => p.Quantity).Sum(); })
.Model(model =>
{
model.Id(m => m.Id);
model.Field(m => m.Id).Editable(false);
model.Field(m => m.Part).Editable(true);
model.Field(m => m.Quantity).Editable(true);
model.Field(m => m.DeliveryDate).Editable(true);
model.Field(m => m.PartDescription).Editable(true);
})
)
)
At 1st glance it would look like,
.Read(read => read.Action("GetAllOrders", "Controller").Data("getAdditionalData"))
Instead of Controller you need to put in the actual name of the Controller so for example "PersonController" would be "Person".
Edit- Ok from the looks of it then you've setup your Read from datasource but not your Update and instead tried to do it in events.
http://demos.kendoui.com/web/grid/editing-inline.html
I find it easier not to use inline edits and instead create a template button to redirect to an edit page thus keeping the kendo related code simple.
Looks like your grid is being called from within an MVC area. If you have Areas setup within your MVC application, it's always a good practice to reference those when making calls with Kendo UI Widgets.
Below assumes an Area called "UI":
.Update(update => update.Action("Update", "Orders", new { Area = "UI" }))