Pending Review
Last Updated: 26 Nov 2014 10:50 by Telerik Admin
Bill
Created on: 25 Nov 2014 03:00
Category: MVVM
Type: Feature Request
1
Add built-in support for nested properties with the MVVM
I would like built-in support for nested properties in the model, particularly when binding controls to odata and using the expand option to fetch related data via a foreign key.

If the grid were aware of this, then setting column templates on foreign keyed data could be much easier as would using them to filter rows.  Achieving this today requires a lot of extra code and you can see an example at at http://www.telerik.com/account/support-tickets/view-ticket.aspx?threadid=880807
 
There are some other suggestions here that are similar but they each suggest something that doesn't quite make it universally useful. However, based on those suggestion it appears that this support would be useful for many things.
1 comment
Imported User
Posted on: 26 Nov 2014 10:50
Doesn't this already work? I don't have access to that ticket but I've been working on a generic kendo based front end that sits on top of a generic odata endpoint and binding by convention, I can crawl the entire db simply by crawling references.

The key I have found is that javascript as a language has no concept of type so use MVC on the server to generate your kendo templates and it will correctly generate the right stuff to allow all sorts of complex situations.

The code appears to be relatively simple too, in my situation I have a model "ComponentViewModel" and then a generic version which inherits that. 
My generic controller creates the generic version in which the actions like "Edit" generate a generic editor template for kendo in an mvc view. 

Here's how I do it ....

@using System.Text.RegularExpressions
@using App.Models
@model ComponentViewModel
@{
    var rootId = Model.TypeName + Model.ObjectId + "_Editor";
    var modelName = Model.TypeName + Model.ObjectId + "_EditorModel";
    var m = Activator.CreateInstance(Model.Type);
    var dependency = "emedia.dependency.get('" + Model.TypeName + "');";
}

<div id="@(rootId)" class="component k-content" data-type="@Model.TypeName" data-item-id="@Model.ObjectId">
    <h2><span class="k-sprite edit"></span> @Regex.Replace(Model.Type.Name, @"(?<!_)([A-Z])", " $1"): @Model.ObjectId <img src="@Url.Content("~/Content/close.png")" /></h2>
    <script>
        $(function () {
            @if(Model.CustomDependencyExists)
            {
                @Html.Raw(dependency)
            }

            var @modelName = emedia.createModel('@Model.TypeName', '@Model.ObjectId');
            var component = $("#@(rootId)");

            kendo.bind(component, @modelName);
            $(".details", component).validate();
        });
    </script>
    <form class="details">
        <div data-description="non dynamic templated stuff">
            <input type="hidden" name="ID" data-rule-required="true" data-bind="value: ID" />
        </div>
        <ul class="fieldList">
            @{ Html.RenderPartial("EditorTemplates/Object", m); }
        </ul>
        <hr />
        <button class="k-button" data-bind="events: { click: save }">Save</button>
    </form>
</div>

Then all you need to do is define your types with properties that have a a custom uihint value like this ...

[UIHint("reference")]
public int RelationshipID { get; set; }

... MVC will then render that as a reference template which in my case I defined as ...

@{ var meta = ViewData.ModelMetadata; }

<a href=""
   data-ref-type="@meta.AdditionalValues["Reference"]"
   data-bind="attr: { data-ref: @ViewData.TemplateInfo.HtmlFieldPrefix }, events: { click: refClick }">View @meta.AdditionalValues["Reference"]</a>


Then on the client you just grab your model and bind it to the root of your dynamically generated editor.

I really should blog about this somewhere!