This is a migrated thread and some comments may be shown as answers.

Simple example needed: Grid with dropdownlist

10 Answers 346 Views
Grid
This is a migrated thread and some comments may be shown as answers.
voripteth
Top achievements
Rank 1
voripteth asked on 22 Jul 2013, 08:54 PM
I've almost used up my trial time trying to figure out how to get a dropdownlist to show up like the example in:
http://demos.kendoui.com/web/grid/editing-custom.html

I see I'm not the only one struggling to get something that should be pretty simple to work.  The example is missing an explanation of how the template #=Category.CategoryName# works and where to find the definition of that template.  I'd like the see a step-by-step tutorial on how to wire up this control.  I'm sure there are MANY others who would benefit from this as well.

In my demo application I have a database value I'm reading which is an integer which I want displayed as a text in a DropDownList within a grid.  I think I'm close but I'm missing a few key points.  How do I add my own editor template?  The demo seems to suggest it is either in the view or controller for the grid.  I think I found it in the "EditorTemplates" folder but have no idea how it gets connected to the view.  Here are snippets of my project code:

My view:
@model IEnumerable<QT_Kendo2.Models.Isotope>
@{
    ViewBag.Title = "Index";
}
<h2>Isotope Library</h2>
@(Html.Kendo().Grid(Model).Name("Isotopes").Columns(c =>
{
    c.Bound(p => p.Id).Hidden();
    c.Bound(p => p.Version).Hidden();
    c.Bound(p => p.Name);
    c.Bound(p => p.LLD).Format("{0:n1}");
    c.Bound(p => p.ULD).Format("{0:n1}");
    c.Bound(p => p.HalfLife);
    c.Bound(p => p.HalfLife_Units).ClientTemplate("#=HLUnitList#");     // Convert the numeric index into text (hours, days, weeks, years)

    c.Command(command => { command.Edit(); command.Destroy(); });
})
    .ToolBar(toolbar =>
        {
            toolbar.Create();
            //    toolbar.Save();       // Used in batch mode
        })
    //.HtmlAttributes(new { style = "height:400px;" })
    .DataSource(dataSource => dataSource
        .Ajax()
        .ServerOperation(false)
        .Model(model =>
            {
            model.Id(p => p.Id);
            model.Field(p => p.Id).Editable(false);
            })
        .Create(create => create.Action("EditingIsotope_Create", "Isotope"))       // "Insert"
        .Update(update => update.Action("EditingIsotope_Update", "Isotope"))
        .Destroy(destroy => destroy.Action("EditingIsotope_Destroy", "Isotope"))
        .Events(events => events.Error("error_handler"))
     )
    .Pageable()
    .Sortable()
    .Editable(editable => editable.Mode(GridEditMode.InLine))
)
Controller:
namespace QT_Kendo2.Controllers
{
    public class IsotopeController : Controller
    {
        private QT_Db db = new QT_Db();

        public ActionResult Index()
        {
            var hlUnits = new List<string>() {"hours", "days", "weeks", "years"};
            ViewData["hlUnits"] = hlUnits;
            return View(db.Isotopes.ToList());
        }

        public ActionResult EditingCustom_Read([DataSourceRequest] DataSourceRequest request)
        {
            var dsr = new DataSourceResult();
            return Json(dsr);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult EditingIsotope_Update([DataSourceRequest] DataSourceRequest request, Isotope isotope)
        {
            if (isotope != null && ModelState.IsValid)
            {
                db.Entry(isotope).State = EntityState.Modified;
                db.SaveChanges();
            }
            return Json(ModelState.ToDataSourceResult());
        }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult EditingIsotope_Destroy([DataSourceRequest] DataSourceRequest request, Isotope isotope)
        {
            db.Isotopes.Remove(db.Isotopes.Find(isotope.Id));
            db.SaveChanges();
            return Json(ModelState.ToDataSourceResult());
        }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult EditingIsotope_Create([DataSourceRequest] DataSourceRequest request, Isotope isotope)
        {
            if (ModelState.IsValid)
            {
                db.Isotopes.Add(isotope);
                db.SaveChanges();
            }
            return Json(ModelState.ToDataSourceResult());
        }

EditorTemplates as seen in the demo.  Not sure how to add these to my project.  Just adding as a partial view doesn't work.
@model IEnumerable<QT_Kendo2.Models.Isotope>
@(Html.Kendo().DropDownListFor(m => m)
        .Name("HLUnitList")                                       // Name used by template?  #= HLUnitList
        .DataValueField("HalfLife_Units")               // Name of the index from the model
        .DataTextField("HLUnitList")                        // Name of the template again.
        .BindTo((System.Collections.IEnumerable)ViewData["hlUnits"])      // Bind to the list index to the string list
)

10 Answers, 1 is accepted

Sort by
0
voripteth
Top achievements
Rank 1
answered on 23 Jul 2013, 07:42 PM
For those of you looking for some help here is what I found so far.  Templates are described here:
http://docs.kendoui.com/getting-started/using-kendo-with/aspnet-mvc/helpers/grid/editor-templates

I put my partial view under the Shared/EditorTemplates folder as stated in step 2 of the above link.

I restructured my model so I could follow the parameters set in step 3:
@(Html.Kendo().DropDownList()
.Name("Employee") // Name of the widget should be the same as the name of the property
.DataValueField("EmployeeID") // The value of the dropdown is taken from the EmployeeID property
.DataTextField("EmployeeName") // The text of the items is taken from the EmployeeName property
.BindTo((System.Collections.IEnumerable)ViewData["employees"]) // A list of all employees which is populated in the controller
)
Step 5 is critical for making sure your partial view gets called

When I ran I actually got a dropdownlist.  Woohoo!  But it was filled with "Undefined" but at least the right number of them!  I commented out the .Name, .DataViewField and .DataTextField from step 3 and to my amazement everything worked!  My list was populated with the right text and the Update button actually saved the correct values.

I would still love to see some much better tutorials but at least I have something working.  I'd like to know why step 3 didn't work as advertised.
0
Vladimir Iliev
Telerik team
answered on 24 Jul 2013, 12:03 PM
Hi Mike,

 
From the provided information it's not clear for us what is the exact reason for this behavior (the DropDownList widget not able to bind to the ViewData), however most probably the data that is bind to contains fields with different names. Could you please provide runable project where the issue is reproduced  - this would help us identify the exact reason for this behavior. 

Kind Regards,
Vladimir Iliev
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
voripteth
Top achievements
Rank 1
answered on 24 Jul 2013, 10:00 PM
I've refactored my project a considerable amount and attached it to this message.  I think I have a better understanding of how to get the DropDownList working for the grid.  I think I'm pretty close to a solution but there is still one bug hanging me up.  Here is what I've done so far:

  1. I realized that the database model of the Isotope needed a ViewModel since it doesn't include the name of the halflife units.
  2. I modeled the class for the halflife units based on the Kendo example ClientCategoryViewModel.  Now it better maps to the .DataValueField and .DataTextField
  3. I created a separate list of HLunits_ViewModel put it into ViewData to populate the dropdownlist.
  4. The new IsotopeViewModel is a Query projection from Isotope and adds the new HLunits_ViewModel.
  5. A major challenge is how to assign the value for the text units from halflife model list into the isotopeViewModel.  The problem is that LINQ generates an error when I try to index into the collection (hlUnits) and assign that value into the ViewModel property.
    HalfLife_TimeUnitsName = hlUnits[isotope.HalfLife_TimeUnits].HalfLife_TimeUnitsName
    This gives the error "LINQ to Entities does not recognize the method 'System.String setUnits(Int32)' method, and this method cannot be translated into a store expression."
  6. To work around the problem in 4 the code iterates through the model and manually assigns HalfLife_TimeUnitsName.  The assignment appears to work but as soon as the loop is left the name values are null again.  I'm don't understand why those names aren't staying changed.
  7. The binding for the HalfLife Units uses ClientTemplate which I think is working but only shows "null" until #6 gets fixed.
    c.Bound(p => p.HLvm).Title("HalfLife Units").ClientTemplate("#=HLvm.HalfLife_TimeUnitsName#")
  8. I added code to EditingIsotope_Update to merge the ViewModel data back into the model and all the main model items are changed but none of the HLunits_ViewModel values are changed.  I don't know why.
Please take a look at the sample project.  I tried to keep things simple.  The project appears to mostly work with the follow exceptions:
  • HalfLife Units always show up as "Null"
  • Changes to HalfLife Units don't show up after update although other fields do change.
Thanks very much for the help!
0
voripteth
Top achievements
Rank 1
answered on 24 Jul 2013, 10:29 PM
I've tried to post a reply with sample code but I keep running into "Invalid Post Content".  (Not a very helpful error.)  I've opened  ticket ID: 719539 to continue discussion of this issue.

0
voripteth
Top achievements
Rank 1
answered on 24 Jul 2013, 10:30 PM
Ticket ID: 719539 opened to continue discussion of this issue.
0
Accepted
Vladimir Iliev
Telerik team
answered on 25 Jul 2013, 08:22 AM
Hi,

Thank you for the provided project.

After reviewing it it seems that the issue comes from invalid data send back to the client side as well as invalid EditorTemplate for the "HLunits_ViewModel" field. Please check the following points how to fix the project:

  • Update the dataBase query:
    var model = new QT_Db().Isotopes
        .Select(isotope => new IsotopeViewModel
        {
            Id = isotope.Id,
            Version = isotope.Version,
            Name = isotope.Name,
            LLD = isotope.LLD,
            ULD = isotope.ULD,
            HalfLife_Length = isotope.HalfLife_Length,
            HalfLife_TimeUnits = isotope.HalfLife_TimeUnits,
            HLvm = new HLunits_ViewModel
            {
                HalfLife_TimeUnits = isotope.HalfLife_TimeUnits
            }
        }).ToList();
     
    // Since the query statement wasn't able to assign the TimeUnitsName we'll do it manually
    foreach (IsotopeViewModel isotopeViewModel in model)
    {
        string units = hlUnits[isotopeViewModel.HalfLife_TimeUnits].HalfLife_TimeUnitsName;
        isotopeViewModel.HLvm.HalfLife_TimeUnitsName = units;
    }
  • Update the EditorTemplate:  
    @model QT_Kendo2.Models.HLunits_ViewModel
     
    @(Html.Kendo().DropDownListFor(m => m)
            //.Name("HLunits_ViewModel") => AUTO GENERATED WHEN EditorFor is used
            .DataValueField("HalfLife_TimeUnits")
            .DataTextField("HalfLife_TimeUnitsName")
            .BindTo((System.Collections.IEnumerable)ViewData["hlUnits"])
    )
  • Update the "EditingIsotope_Update" action:
    if (isotopeViewModel != null && ModelState.IsValid)
    {
        Isotope isotope = db.Isotopes.Find(isotopeViewModel.Id);
        if (isotope != null)
        {
            isotope.Name = isotopeViewModel.Name;
            isotope.LLD = isotopeViewModel.LLD;
            isotope.ULD = isotopeViewModel.ULD;
            isotope.HalfLife_Length = isotopeViewModel.HalfLife_Length;
            isotope.HalfLife_TimeUnits = isotopeViewModel.HLvm.HalfLife_TimeUnits;
            db.Entry(isotope).State = EntityState.Modified;
            db.SaveChanges();
        }
    }  
Kind Regards,
Vladimir Iliev
Telerik
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Accepted
voripteth
Top achievements
Rank 1
answered on 25 Jul 2013, 02:53 PM
Thanks very much for the help.  Everything works now!

For those following at home here is the summary of changes:
  • For the Index() the Query needed to call :ToList() so we got an IEnumerable object instead of a IQueryable
  • The editor template needs to use DropDownListFor otherwise the initial selection of the list isn't correct.  .Name needs to be removed
  • Typo in EditingIsotope_Update where ULD was being assigned LLD 

0
Ruud
Top achievements
Rank 1
answered on 08 Sep 2014, 05:51 PM
Hi,
I am facing the same problem. Scenario:
1. partialview with a grid which will show a column as dropdownlist in edit mode
2. editortemplate with the dropdownlistfor defined
3. viewdata is filled when opening the view (not the partial, but the hosting view)
4. when editing the grid, the dropdown list is shown, but no data in the drop down list. Not even the value of the "OptionLabel" property??

Exhausting to try to fix this, not to talk about the time wasted. Sure it has to do with lack of knowledge on my side, but the samples do not give me a easy to work with sample in this case. Only this post was helpful (thanks for that) but did not sovle it for me. Any suggestions for the above scenario, preferably a (simple!!) sample?

Best regards,
Ruud
0
Ruud
Top achievements
Rank 1
answered on 08 Sep 2014, 09:19 PM
Ok, switched the drop downlist in the editortemplate to use Ajax (I needed that anyway..); works now. Few..
0
Vladimir Iliev
Telerik team
answered on 09 Sep 2014, 05:31 AM
Hi Ruud,

From the provided information it's not clear for us what is the exact reason for this behavior - could you please open a new support thread/forum post and provide runable example where the issue is reproduced? This would help us pinpoint the exact reason for this behavior (you can use the attached demo as baseline for creating the sample project).

Regards,
Vladimir Iliev
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
Tags
Grid
Asked by
voripteth
Top achievements
Rank 1
Answers by
voripteth
Top achievements
Rank 1
Vladimir Iliev
Telerik team
Ruud
Top achievements
Rank 1
Share this question
or