Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What "EditorViewData" is for in Telerik MVC Grid column definition?

i have a telerik grid as follow:

Html.Telerik().Grid<MatchViewModel>().Name("Matches").Columns(cols =>
             {
                 cols.Bound(e => e.Name);
                 cols.Bound(e => e.Date);
                 cols.Bound(e => e.GuestTeamId);
                 cols.Bound(e => e.HostTeamId);
                 cols.Bound(e => e.PostponedDate);
             ==> cols.Bound(e => e.RefereeId).EditorViewData(new { RefereeName = '' });
                 cols.Bound(e => e.StatusId);
             })

in the column reffered by arrow i wanna send referee name as additional data for EditorTemplate.i inferred from the EditorViewData method name that it can help me doing this.but i can't get it working.can anyone help me with this? thanks.

like image 543
Behnam Esmaili Avatar asked Oct 18 '12 09:10

Behnam Esmaili


2 Answers

If you have a well defined Model for your page you should not ever need to use ViewBag or ViewData, they are sloppy. EditorViewData allows you to create ViewData on-the-fly to pass extra data to your EditorTemplate.

For example, say you want to have different DropDownList values in the EditorTemplate for each item in your grid, you will need to pass extra data to do this. With EditorViewData you can add additional values from your Model for exactly that purpose without having to resort to coding up any ViewBag or ViewData objects in your Controller.

The first place I used it was a People grid that allowed editing of defined Qualifications added to a Qualifications grid inside a nested TabStrip. The trick was I didn't want the DropDownList for each person to contain any of the qualifications they already had earned. Like this...

People Grid

@using Kendo.Mvc.UI
@model PeopleViewModel
@(Html.Kendo().Grid<PersonModel>()
    .Name("PersonGrid")
    .Columns(columns => {
        columns.Bound(b => b.LastName).EditorTemplateName("_TextBox50");
        columns.Bound(b => b.FirstName).EditorTemplateName("_TextBox50");
...
        columns.Command(cmd => { cmd.Edit(); cmd.Destroy(); }).Width(180);
    })
    .ClientDetailTemplateId("personTemplate")
    .ToolBar(toolbar => toolbar.Create())
    .Selectable()
    .Editable(editable => editable.Mode(GridEditMode.InLine))
    .DataSource(dataSource => dataSource
        .Ajax()
        .Model(model =>
            {
                model.Id(a => a.Id);
            })
        .Create(create => create.Action("CreatePerson", "People"))
        .Read(read => read.Action("ReadPeople", "People"))
        .Update(update => update.Action("UpdatePerson", "People"))
        .Destroy(destroy => destroy.Action("DestroyPerson", "People"))
    )
    .Events(events => events.DataBound("dataBound"))
)
<script type="text/javascript">
    function dataBound() {
        this.expandRow(this.tbody.find("tr.k-master-row").first());
    }
</script>
<script id="personTemplate" type="text/kendo-tmpl">
    @(Html.Kendo().TabStrip()
        .Name("TabStrip_#=Id#")
        .Items(items =>
                    {
...
                        items.Add().Text("Edit Qualifications")
                        .LoadContentFrom("PersonQualifications", "People", new {personId = "#=Id#"});
...
                    })
        .ToClientTemplate()
    )
</script>

PeopleViewModel

Ignore the inheritance stuff, it is beyond this discussion. But note that I use this same Model on all the sub Views related to this top level View.

public class PeopleViewModel : PageViewModel
{
    public int PersonId { get; set; }
    public PersonModel Person { get; set; }
    public IList<QualificationModel> AllQualifications { get; set; }
...

    public PeopleViewModel(BaseViewModel baseViewModel) : base(baseViewModel)
    {}
}

PersonQualifications Controller

The data providers are injected elsewhere, but note the POCO to Model flattening - just a static method that applies a List to the Model constructor.

public ActionResult PersonQualifications(int personId)
{
    SetBaseContext(HttpContext);
    var model = new PeopleViewModel(BaseViewModel)
                     {
                        PersonId = personId,
                        AllQualifications = QualificationModel.FlattenToThis(_qualificationDataProvider.Read())
                     };
    return View(model);
}

Nested Grid (View Loaded Inside TabStrip)

@using Kendo.Mvc.UI
@model PeopleViewModel
@{
    Layout = null;
}
@(Html.Kendo().Grid<PersonQualificationModel>()
    .Name("QualificationEditGrid_" + Model.PersonId)
    .Columns(columns =>
    {
        columns.ForeignKey(f => f.QualificationId, Model.AllQualifications, "Id", "Display")
===>        .EditorViewData(new {personId = Model.PersonId})
            .EditorTemplateName("PersonQualificationDropDownList");
        columns.Command(cmd =>
                            {
                                cmd.Edit();
                                cmd.Destroy();
                                }).Width(180);
    })
    .ToolBar(toolbar => toolbar.Create())
    .DataSource(dataSource => dataSource
        .Ajax()
        .Events(events => events.Error("error_handler"))
        .Model(model => {
            model.Id(a => a.Id);
        })
        .Create(create => create.Action("CreatePersonQualification", "People"))
        .Read(read => read.Action("ReadPersonQualifications", "People", new {personId = Model.PersonId}))   
        .Destroy(destroy => destroy.Action("DestroyPersonQualification", "People"))
    )
)

The EditorTemplate (Finally!)

Ignore the first ViewData reference that helps make this EditorTemplate shared. The one we are interested in is a little further down.

@using Kendo.Mvc.UI
@(Html.Kendo().DropDownList()
    .Name(ViewData.TemplateInfo.GetFullHtmlFieldName(""))
    .DataValueField("Id")
    .DataTextField("Name")
    .OptionLabel("Select...")
    .DataSource(dataSource => dataSource
===>    .Read(read => read.Action("ReadDdlQualifications", "People", new {personId = ViewData["personId"]}))
    )
)

Controller Method (Just to be Thorough)

public JsonResult ReadDdlQualifications(int personId)
{
    var qualification = _qualificationDataProvider.ReadAvailableToPerson(personId);
    IList<IdNamePair> results = IdNamePair.FlattenToThis(qualification);
    return Json(results, JsonRequestBehavior.AllowGet);
}

Obviously there is a lot of other stuff going on in this example (I hope I left enough code in for it to make sense), but it should get across the point of when it is needed - and it is REALLY needed.

Enjoy.

like image 122
Trey Gramann Avatar answered Oct 07 '22 15:10

Trey Gramann


I ran into the same issue as Chad and as Trey mentioned, this cannot be done via passing information to EditorViewData. There is no way to pass the row data item, only page data.

As an alternative you can add this script to the editor template. Then you can access a field value from the grid row and pass it to the datasource call, filtering the dropdownlist based on each rows data.

<script type="text/javascript">

    function getParentId() {
        var row = $(event.srcElement).closest("tr");
        var grid = $(event.srcElement).closest("[data-role=grid]").data("kendoGrid");
        var dataItem = grid.dataItem(row);
        return { EmployeeId: dataItem.EmployeeId };
    }

</script>

And then add the data item to the read method on the data source.

@(Html.Kendo().DropDownList()
        .Name("Product")
        .DataValueField("ProductId")
        .DataTextField("ProductName")
        .DataSource(ds => ds
            .Read(read => read.Action("ProductsRead", "Home")
                .Data("getParentId")
                ))
)
like image 34
Joel Tipke Avatar answered Oct 07 '22 14:10

Joel Tipke