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);
})
)
Related
Here is the code of the grid with the dropdown that I have inserted into a Kendo grid:
#model Portal.Web.Areas.Orders.Models.IngressoMerceViewModel
#(Html.Kendo().Grid<Portal.Web.Areas.Orders.Models.IngressoMerceGridViewModel>()
.Name("grid")
.Events(e => e.DataBound(#<text>function() {for (var i = 0; i #Html.Raw("<") this.columns.length; i++) {this.autoFitColumn(i);}}</text>))
.Columns(columns =>
{
columns.Template("<input type='checkbox' />");
columns.Bound(p => p.Posizione).Title("Posizione").Width(200);
columns.Bound(p => p.Materiale).Title("Materiale").Width(200);
columns.Bound(p => p.Description).Title("Testo breve").Width(200);
columns.Bound(p => p.WarehouseLogicStore).Editable("false").Width(200)
.ClientTemplate(Html.Kendo().DropDownList()
.Name("WHLogicValue").DataTextField("Code").DataValueField("Code").DataSource(source =>
{
source.Read(read =>
{
read.Action("WarehouseLogicTypes_Read", "IngressoMerce");
});
}).ToClientTemplate().ToString()
); ;
columns.Bound(p => p.Quantity).Title("Qta Ordine").Width(200);
columns.Bound(p => p.UnitOfMeasure).Title("UM").Width(200);
columns.Bound(p => p.ReceivedQty).Title("Qta giĆ ricevute").Width(200);
columns.Template("<input type='text' />").Title("Qta ricevute");
columns.Bound(p => p.InProgressQtyCheck).Title("Qta da ricevere").Width(200);
columns.Bound(p => p.ExpectedDeliveryDate).Format("{0:dd/MM/yyyy}").Title("Data consegna prevista").Width(200);
columns.Bound(p => p.QualityCheckNeeded).Title("Check qualitativo richiesto").Width(220);
})
.Pageable()
.Sortable()
.Scrollable()
.HtmlAttributes(new { style = "height:430px;" })
.DataSource(dataSource => dataSource
.Ajax()
//.Read(read => read.Url("/orders/details").Type(HttpVerbs.Get))
.Read(read => read.Action("OrderDetails_Read", "IngressoMerce", Model))
)
.Deferred(!Model.IsAjax)
)
Unfortunately, the dropdown shows as textbox and the respective action in the ASP.net MVC controller is not firing. Here is the code for the action:
[AllowAnonymous]
public async Task<JsonResult> WarehouseLogicTypes_Read()
{
try
{
var types = await gateway.GetWarehouseLogicTypes();
return Json(types);
}
catch (Exception ex)
{
//logger.LogError(ex.Message);
throw ex;
}
}
you can insert dropdown inside kendo grid using EditorTemplates
Your Index view code should be like this
#(Html.Kendo().Grid<DemoApplication.Models.ProductsModel>()
.Name("CategoryGrid")
.Columns(columns =>
{
columns.Bound(p => p.category).ClientTemplate("#=category.CategoryName#");
columns.Bound(c => c.ProductName);
})
.Editable(editable => editable.Mode(GridEditMode.InCell))
.Scrollable()
.Sortable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Id(x => x.Id);
})
.Read(read => read.Action("ListAll", "Test"))
.PageSize(10)
))
Add Editor Template(_CategoryEditor.cshtml) inside Shared/EditorTemplates folder
your _CategoryEditor code should be like this
#model DemoApplication.Models.Category
#(Html.Kendo().DropDownListFor(m => m)
.Name("category")
.DataValueField("CategoryId")
.DataTextField("CategoryName")
.BindTo((System.Collections.IEnumerable)ViewData["Category"]))
Model code
public class ProductsModel
{
public int Id { get; set; }
[UIHint("_CategoryEditor")]
public Category category { get; set; }
public string ProductName { get; set; }
}
public class Category
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
}
Controller Code
public ActionResult Index()
{
ViewData["Category"] = GetCategories();
return View();
}
public List<Category> GetCategories()
{
List<Category> categories = new List<Category>();
categories.Add(new Category() { CategoryId = 1, CategoryName = "Category 1" });
categories.Add(new Category() { CategoryId = 2, CategoryName = "Category 2" });
categories.Add(new Category() { CategoryId = 3, CategoryName = "Category 3" });
return categories;
}
public ActionResult ListAll([DataSourceRequest] DataSourceRequest request)
{
List<ProductsModel> productsList = new List<ProductsModel>();
productsList.Add(new ProductsModel() { Id = 1, category = GetCategories().First(), ProductName = "Product 1" });
productsList.Add(new ProductsModel() { Id = 1, category = GetCategories().First(), ProductName = "Product 1" });
productsList.Add(new ProductsModel() { Id = 1, category = GetCategories().First(), ProductName = "Product 1" });
return Json(productsList.ToDataSourceResult(request));
}
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'm trying to add a dropdownlist to a kendo grid by the help of this documentation
:
http://demos.telerik.com/aspnet-mvc/grid/editing-custom
Actually I followed exactly the same way but no chance I'm wonder how the kendo grid understand it has to place a dropdownlist in the clientTemplate ?!
does clientTemplate has to be defined somewhere?
You have to define a clientTemplate by adding this to the Grid .ClientDetailTemplateId("template")
Then you can add DropDownList into the template
<script id="template" type="text/kendo-tmpl">
#(Html.Kendo().DropDownList()
//build the dropdownlist
.ToClientTemplate()
)
</script>
Demo: http://demos.telerik.com/aspnet-mvc/grid/detailtemplate
Just to add to the mix of answers, here is a late one...
Create a List in your ViewModel
Treat your Model.PropertyId as a ForeignKey
For example...
columns.ForeignKey(x => x.ChangeTypeId, Model.ChangeTypes, "Id",
"ChangeTypeName")
SAMPLE VIEW:
#(Html.Kendo().Grid<ChangeRequest>()
.Columns(columns =>
{
columns.Bound(x => x.Id)
.Visible(false);
columns.Bound(x => x.Description)
.Title("Description")
.Width(100);
columns.ForeignKey(x => x.ChangeTypeId, Model.ChangeTypes, "Id", "ChangeTypeName")
.Title("Data Type")
.Width(50);
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(100);
})
.Name("gridChangeRequest")
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Pageable()
.Sortable()
.Scrollable()
.BindTo(Model.RTUDeviceCustomRegisterModbuses)
.DataSource(dataSource => dataSource.Ajax()
.ServerOperation(true)
.PageSize(50)
.Model(model => { model.Id(m => m.Id); })
.Create(update => update.Action("Create", "ChangeRequest", new { Area = "Documents" }))
.Update(update => update.Action("Update", "ChangeRequest", new { Area = "Documents" }))
.Destroy(update => update.Action("Destroy", "ChangeRequest", new { Area = "Documents" }))
)
.HtmlAttributes(new { #class = "", #style = "height: 400px;" }))
SAMPLE VIEW MODEL:
public class ChangeRequestFormViewModel : ViewModelBase
{
#region <Constructors>
public ChangeRequestFormViewModel(IApplication application) : base(application)
{
InitializeCreateEmpty();
}
#endregion
#region <Properties>
public ChangeRequestDocument Entity { get; set; }
#region lookups
public List<ChangeType> ChangeTypes { get; set; }
#endregion
#endregion
#region <Methods>
private void InitializeCreateEmpty()
{
var builder = Application.ChangeRequestDocumentXmlDataSetBuilder; //<-- This object is specific to my (particular) application
var dataset = builder.CreateEmpty();
Entity = dataset.Form;
ChangeTypes = dataset.ChangeTypes;
}
#endregion
}
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.
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.