Kendo UI Grid Master Detail ForeignKey Column on Cascade to Master Id

5 posts, 1 answers
  1. Taha
    Taha avatar
    6 posts
    Member since:
    Mar 2011

    Posted 25 Sep 2013 Link to this post

    Hi,

    I have a Master Detail Grid in Kendo UI

    I want to add rows to Detail Grid with a Foriegn Key Column that is driven by Master Id, how do i accomplish this ?

    I have highlighted the Foreign Key Column in bold

    @(Html.Kendo().Grid<PackageModel>()
                .Name("RGrid")
                .Columns(col =>
                {
                    col.Bound(c => c.Name).Visible(true);
                    col.Bound(c => c.PackageName).Visible(true).Title("Package");                               
                })
                .DataSource(ds => ds
                    .Ajax()
                    .Events(e => e.RequestStart("onDataRequestStart"))
                    .Model(m =>
                    {
                        m.Id(c => c.OId);
                    })
                    .Read(read => read.Action("ReadPackages", "RGrid", new { area = "Recommendation", gridSettings = "##settings##" }))                
                )                        
                .ClientDetailTemplateId("recostemplate")
                .Navigatable()
                .Pageable(p => p.PageSizes(true))
                .Filterable()
                .Sortable()
                .Selectable(selectable => selectable.Mode(GridSelectionMode.Single))
            )



    <script id="recostemplate" type="text/kendo-tmpl">
        @(Html.Kendo().Grid<SE.OrderBook.Web.Models.View.RecommendationModel>()
                    .Name("RecosGrid#=Id#")
                    .Columns(columns =>
                    {
                        columns.Bound(o => o.Id).Title("Id").Visible(true);
                        columns.ForeignKey(o => o.DeliverableId, commonService.GetDeliverableDropList(), "Id", "Value");
                        columns.Bound(o => o.DeliverableName).Title("Deliverable").Visible(true);
                        columns.Bound(o => o.Included).Visible(true);
                        columns.Bound(o => o.ServiceStart).Format("{0:d}").Title("Service<br />Start");
                        columns.Bound(o => o.ServiceEnd).Format("{0:d}").Title("Service<br />End");                    
                        columns.Bound(o => o.Year1).Visible(true);
                        columns.Bound(o => o.Total).Visible(true);
                        columns.Bound(o => o.PackageId).Hidden(true);
                        columns.Command(cmd => { cmd.Edit().UpdateText("Save"); /*cmd.Destroy();*/ }).Visible(true).Width("10%");                    
                    })
                    .DataSource(ds => ds
                        .Ajax()
                        .PageSize(5)
                        .Model(m =>
                        {
                            m.Id(c => c.Id);
                            m.Field(c => c.PackageId).DefaultValue("#=Id#");
                        })
                        .Read(read => read.Action("Read", "Home", new { area = "Recommendation", id = "#=Id#" }))
                        .Create(update => update.Action("Create", "Recos", new { area = "Recommendation" }))
                        .Update(update => update.Action("Update", "Recos", new { area = "Recommendation" }))
                        .Destroy(delete => delete.Action("Delete", "Recos", new { area = "Recommendation" }))
                    )
                    .ToolBar(toolbar => { toolbar.Create(); })
                    .Events(events =>
                    {
                        events.Edit("onRecoDetailsEdit");
                        events.Save("onRecoDetailsSave");
                    })
                    .Editable(e => e.Mode(GridEditMode.PopUp))
                    .Pageable()
                    .Sortable()
                    .ToClientTemplate())
    </script>


    I need to pass package Id into commonService.GetDeliverableDropList() but i am not sure how to accomplish this?

    I think solution to this is only possible at run time through AJAX, if particular than is there an example how i can populate foriegn key colum dropdown list through AJAX ?

    Waiting for Response,

    Kind Regards,




  2. Daniel
    Admin
    Daniel avatar
    2214 posts

    Posted 27 Sep 2013 Link to this post

    Hello,

    The template expression will be evaluated on the client so the strongly typed expression overload of the DefaultValue method cannot be used unless the field is a string. You could use the overload that accepts the field name and type if the field is not a string:

    m.Field("PackageId", typeof(int)).DefaultValue("#=Id#");
    Regards,
    Daniel
    Telerik
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  3. Taha
    Taha avatar
    6 posts
    Member since:
    Mar 2011

    Posted 27 Sep 2013 Link to this post

    Hi,

    Thanks for your reply,

    I want to populate Deliverable Foreign Key Column on client side using Package Id how cam accomplish this ?

    ///Set default DropListItem to "Please Select"
            function onRecoDetailsEdit(e) {
                   var packageId = e.grid.datasource.package Id
                   
                   var deliverables = $.ajax({
                    type: "POST",
                    url: '@Url.Action("GetDeliverables", "Home" })/' + packageId,

                    success: function (response) {
                               // deliverables foreign key dropdown population  
                    },
                    
                });
       
             }
  4. Daniel
    Admin
    Daniel avatar
    2214 posts

    Posted 30 Sep 2013 Link to this post

    Hello again,

    Sorry, I missed that the question was about populating the dropdownlist data based on the ID. The foreignkey column data can be set only on initialization so I can suggest to pass all the items initially and filter the dropdownlist data. With the approach that you are currently using you can get the ID from the row model if available in your scenario:

    function onRecoDetailsEdit(e) {
        var packageId = e.model.PackageIdField;
    or from the master row model:
    function onRecoDetailsEdit(e) {
      var masterRow = this.element.closest(".k-detail-row").prev(),
          masterGrid = masterRow.closest("[data-role=grid]").data("kendoGrid"),
          item = masterGrid.dataItem(masterRow),
          packageId = item.MasterPackageIdField;
    The data can be set to the dropdownlist after the requests has completed by using its dataSource data method:
    success: function (response) {
          $("#DeliverableId").data("kendoDropDownList").dataSource.data(response);
    },
    Alternative approaches are to include the packageId field in the dropdownlist data and use the dataSource filter method in the edit event to filter the data on the client or configure the dropdownlist in the editor for remote binding and pass the ID as additional data.

    Regards,
    Daniel
    Telerik
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  5. Answer
    Taha
    Taha avatar
    6 posts
    Member since:
    Mar 2011

    Posted 01 Oct 2013 Link to this post

    Hi, 

    Thanks for your reply,

    I have devised a solution based on first approach of filtering, deliverables for the package are stored in additional field as comma seprated string,  for any one interested here is the solution

    Not the best of solution but works, initial go before improving with a more robust solution

    ///Set default DropListItem to "Please Select"
            function onRecoDetailsEdit(e) {
                 $(".k-edit-form-container [data-role=dropdownlist]").each(function (index) {
                    var ddl = $(this).data("kendoDropDownList");                
                    // limit to package only
                    if (ddl && this.id == "DeliverableId") {
                        var deliverables = e.model.PackageDeliverables.split(',');
                        var filterDeliverables = [];
                        // filter deliverables on package deliverables
                        for(var idx = 0; idx < deliverables.length; idx = idx + 1) {   //alert(parseInt(deliverables[idx]));
                            filterDeliverables.push({ "field": "Value", "operator": "eq", "value": deliverables[idx] });
                        }
                        var filtersString = {};
                        if (deliverables.length > 1)
                            filtersString = { "filters": filterDeliverables, "logic": "or" };
                        else
                            filtersString = filterDeliverables;
                        ddl.dataSource.filter(filtersString);
                        ddl.refresh();
                    }
                });

                
            }
Back to Top