Demo of Batch Editing with Enum Columns?

5 posts, 1 answers
  1. Nick
    Nick avatar
    86 posts
    Member since:
    Mar 2008

    Posted 13 Feb 2013 Link to this post

    I'm just evaluating the Kendo grid for an upcoming project and I'm hunting for demos for the functionality that I need.

    I have created a grid in an asp.net razor view that takes a viewmodel.  A couple of the model properties are enums which display nicely but when clicking into the cell just render a text box with the enum value (1,2,3,etc).

    Does anyone have a demo where the edit field is an appropriate dropdown rather than the raw value of the enum?

    Thanks in advance :)

    =================================================================================

    For reference the model and view I'm using are:
    public class HomeMonitorViewModel {
     
      public int Id { get; set; }
      [Required, StringLength(255)]
      public string Name { get; set; }
      [Required, StringLength(128)]
      public string HostSystem { get; set; }
      public string Description { get; set; }
      public Data.MonitorClassification Classification { get; set; }
      public DateTime DateAdded { get; set; }
      public bool HasBeenAdministered { get; set; }
      public Data.MonitorSource Source { get; set; }
      public int MonitorAliasId { get; set; }
      public string MonitorAliasName { get; set; }
     
    }
     
    public enum MonitorClassification {
      Default = 1,
      Standard = 2,
      Bespoke = 3
    }
     
    public enum MonitorSource {
      Policy = 1,
      Adhoc = 2,
      Unknown = 3
    }
    @(Html.Kendo().Grid<ProjectBlackSun.Models.Home.HomeMonitorViewModel>()
      .Name("MonitorGrid")
      .Columns(c => {
        c.Bound(m => m.Name);
        c.Bound(m=>m.MonitorAliasName);
        c.Bound(m=>m.Description);
        c.Bound(m=>m.HostSystem);
        c.Bound(m=>m.Classification);
        c.Bound(m=>m.Source);
      })
      .ToolBar(t => {
        t.Create();
        t.Save();
      })
      .Editable(e => e.Mode(GridEditMode.InCell))
      .Pageable()
      .Sortable()
      .DataSource(d => d
        .Ajax()
        .Batch(true)
        .ServerOperation(false)
        .Events(e => e.Error("error_handler"))
        .Model(model => model.Id(monitor => monitor.Id))
        .Create("MonitorGridCreate", "Home")
        .Read("MonitorGridRead", "Home")
        .Update("MonitorGridUpdate", "Home")
        .Destroy("MonitorGridDestroy", "Home")
      )
    )
     
    <script type="text/javascript">
        function error_handler(e) {   
            if (e.errors) {
                var message = "Errors:\n";
                $.each(e.errors, function (key, value) {
                    if ('errors' in value) {
                        $.each(value.errors, function() {
                            message += this + "\n";
                        });
                    }
                });       
                alert(message);
            }
        }
    </script>



  2. Vladimir Iliev
    Admin
    Vladimir Iliev avatar
    2172 posts

    Posted 15 Feb 2013 Link to this post

    Hi Nick,

     
    Please note that KendoUI for ASP.NET MVC installation comes with offline demos which contains such example in the "Editing custom editor" demo. These demos can be found under the installation folder:

    • ...\Telerik\Kendo UI for ASP.NET MVC Q3 2012\wrappers\aspnetmvc\Examples\

    Kind Regards,
    Vladimir Iliev
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  3. Kendo UI is VS 2017 Ready
  4. Nick
    Nick avatar
    86 posts
    Member since:
    Mar 2008

    Posted 15 Feb 2013 Link to this post

    Hi Vladimir,

    Yeah, I found those yesterday and have changed my view model to get a dropdown list as the editor for one of my columns. Unfortunately this raised a new issue.

    public class HomeMonitorViewModel {
     
      public int Id { get; set; }
      [Required, StringLength(255)]
      public string Name { get; set; }
      [Required, StringLength(128)]
      public string HostSystem { get; set; }
      public string Description { get; set; }
      public Data.MonitorClassification Classification { get; set; }
      public DateTime DateAdded { get; set; }
      public bool HasBeenAdministered { get; set; }
      public Data.MonitorSource Source { get; set; }
       
      [UIHint("MonitorAlias")]
      public AliasListItemViewModel MonitorAlias { get; set; }
     
    }
     
    public class AliasListItemViewModel {
      public int AliasId { get; set; }
      public string AliasName { get; set; }
    }
    I have changed the MonitorAlias property to be a viewmodel that contains Id and Name so this can be edited from a dropdown.  The grid declaration now looks like this:

    <!-- Grid in view -->
    @(Html.Kendo().Grid<ProjectBlackSun.Models.Home.HomeMonitorViewModel>()
      .Name("MonitorGrid")
      .Columns(c => {
        c.Bound(m => m.Name);
        c.Bound(m => m.MonitorAlias).ClientTemplate("#=MonitorAlias.AliasId#");
        c.Bound(m=>m.Description);
        c.Bound(m=>m.HostSystem);
        c.Bound(m=>m.Classification);
        c.Bound(m=>m.Source);
      })
      .ToolBar(t => {
        t.Create();
        t.Save();
      })
      .Editable(e => e.Mode(GridEditMode.InCell))
      .Pageable()
      .Sortable()
      .DataSource(d => d
        .Ajax()
        .Batch(true)
        .ServerOperation(false)
        .Events(e => e.Error("error_handler"))
        .Model(model => model.Id(monitor => monitor.Id))
        .Create("MonitorGridCreate", "Home")
        .Read("MonitorGridRead", "Home")
        .Update("MonitorGridUpdate", "Home")
        .Destroy("MonitorGridDestroy", "Home")
      )
    )
     
    <!-- Custom editor template -->
    @(Html.Kendo().DropDownList()
                  .Name("MonitorAlias")
                  .DataValueField("AliasId")
                  .DataTextField("AliasName")
                  .BindTo((System.Collections.IEnumerable)ViewData["aliases"])
    )
    This work great in edit mode, the dropdown appears with my Aliases listed and I can change the value.

    My new problem is now that column displays the Id value in the grid and not the text.

    Is there some attribute or function I've missed to tell the grid to display AliasName in read mode, not AliasId?

    Thanks,
    Nick

    EDIT:

    This change also seems to have broken the Add Item functionality,  Clicking the Add New Item button now simply results in a client error "Uncaught ReferenceError: MonitorAlias is not defined"

    Does the add functionality not use the same editor template as the edit function?


  5. Answer
    Vladimir Iliev
    Admin
    Vladimir Iliev avatar
    2172 posts

    Posted 15 Feb 2013 Link to this post

    Hi Nick,


    I would suggest to flatter your model to contain only the AliasId and use the ForiegnKeyColumn functionality of the grid to match the text to the value. For convenience (and better understand this functionality) I created small demo and attached it to the current thread. 

    Kind regards,
    Vladimir Iliev
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  6. Nick
    Nick avatar
    86 posts
    Member since:
    Mar 2008

    Posted 15 Feb 2013 Link to this post

    Hi Vladimir,

    Thanks for that, the ForeignKey function works much better for me than the custom editor.

    For reference and anyone else who's interested I ended up with the following:

    Viewmodels:
    public class HomeMonitorViewModel {
      public int Id { get; set; }
      [Required, StringLength(255)]
      public string Name { get; set; }
      [Required, StringLength(128)]
      public string HostSystem { get; set; }
      public string Description { get; set; }
      public Data.MonitorClassification Classification { get; set; }
      public bool HasBeenAdministered { get; set; }
      public Data.MonitorSource Source { get; set; }
      public int MonitorAliasId { get; set; }
    }
     
    public class ClassificationListItemViewModel {
      public int Id { get; set; }
      public string Name { get; set; }
    }
     
      public class AliasListItemViewModel {
      public int AliasId { get; set; }
      public string AliasName { get; set; }
    }

    View:
    @(Html.Kendo().Grid<ProjectBlackSun.Data.Monitor>()
      .Name("MonitorGrid")
      .Columns(c => {
        c.Bound(m => m.Name);
        c.ForeignKey(m=>m.MonitorAliasId,(System.Collections.IEnumerable)ViewData["aliases"],"AliasId","AliasName");
        c.Bound(m=>m.Description);
        c.Bound(m=>m.HostSystem);
        c.ForeignKey(m=>m.Classification,(System.Collections.IEnumerable)ViewData["classifications"],"Value","Text");
        c.ForeignKey(m=>m.Source,(System.Collections.IEnumerable)ViewData["sources"],"Value","Text");
      })
      .ToolBar(t => {
        t.Create();
        t.Save();
      })
      .Editable(e => e.Mode(GridEditMode.InCell))
      .Pageable()
      .Sortable()
      .DataSource(d => d
        .Ajax()
        .Batch(true)
        .ServerOperation(false)
        .Events(e => e.Error("error_handler"))
        .Model(model => model.Id(monitor => monitor.Id))
        .Create("MonitorGridCreate", "Home")
        .Read("MonitorGridRead", "Home")
        .Update("MonitorGridUpdate", "Home")
        .Destroy("MonitorGridDestroy", "Home")
      )
    )
    And the corresponding controller actions:
    public class HomeController : Controller {
     
      private Data.MonitorContext _monitorContext;
     
      public HomeController() {
        _monitorContext = new Data.MonitorContext();
      }
     
      public ActionResult Index() {
     
        PopulateAliases();
        PopulateClassifications();
        PopulateSources();
        return View();
      }
     
      public ActionResult MonitorGridRead([DataSourceRequest] DataSourceRequest request) {
        // We need to drop into a view model to prevent circular reference errors when json serializing.
        var data = _monitorContext.Monitors.Select(x => new HomeMonitorViewModel() {
          Classification = x.Classification,
          Description = x.Description,
          HasBeenAdministered = x.HasBeenAdministered,
          HostSystem = x.HostSystem,
          Id = x.Id,
          MonitorAliasId = x.MonitorAliasId,
          Name = x.Name,
          Source = x.Source
        });
        var retval = data.ToDataSourceResult(request);
        return Json(retval);
      }
     
      [HttpPost]
      public ActionResult MonitorGridCreate([DataSourceRequest] DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<HomeMonitorViewModel> monitors) {
     
        var results = new List<Data.Monitor>();
     
        if (monitors != null && ModelState.IsValid) {
          foreach (var monitor in monitors) {
     
            Data.Monitor data = new Data.Monitor {
              Classification = monitor.Classification,
              Description = monitor.Description,
              HasBeenAdministered = true,
              HostSystem = monitor.HostSystem,
              MonitorAliasId = monitor.MonitorAliasId,
              Name = monitor.Name,
              Source = monitor.Source
            };
             
            _monitorContext.Monitors.Add(data);
            results.Add(data);
          }
          _monitorContext.SaveChanges();
        }
        return Json(results.ToDataSourceResult(request, ModelState));
      }
     
      private void PopulateAliases() {
        ViewData["aliases"] = _monitorContext.MonitorAliases
          .OrderBy(a => a.Name)
          .Select(a => new Models.Home.AliasListItemViewModel {
            AliasId = a.Id,
            AliasName = a.Name
          });
      }
     
      private void PopulateClassifications() {
        IEnumerable<SelectListItem> data = Enum.GetValues(typeof(Data.MonitorClassification))
                                               .Cast<Data.MonitorClassification>()
                                               .Select(v => new SelectListItem {
                                                 Text = v.ToString(),
                                                 Value = ((int)v).ToString()
                                               });
        ViewData["classifications"] = data;
      }
     
      private void PopulateSources() {
        IEnumerable<SelectListItem> data = Enum.GetValues(typeof(Data.MonitorSource))
                                               .Cast<Data.MonitorSource>()
                                               .Select(v => new SelectListItem {
                                                 Text = v.ToString(),
                                                 Value = ((int)v).ToString()
                                               });
        ViewData["sources"] = data;
      }
     
    }
    Please bear in mind this is dirty proof of concept stuff, tightly coupled to the EF DbContext.  Don't do this in production code!  :)



Back to Top
Kendo UI is VS 2017 Ready