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

Master/Detail grid: how to get master's id into detail grid's custom popup editor

16 Answers 1947 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Mathieu
Top achievements
Rank 1
Mathieu asked on 26 Jul 2014, 07:46 PM
Hey,

I have a grid in master/detail like below.

CourseVM has an "Id" property as primary key (int)

As you can see, the detail grid uses a popup editor (custom editortemplate defined in /shared/EditorTemplates/CourseEntryVM.cshtml).

On that custom popup editor template, I need to have access to the master id (from CourseVM) in order to do some filtering for a dropdownlist, but I don't know how to have that Id.

Can anyone help me ?

Thanks

@(Html.Kendo().Grid<CourseVM>()
    .Name("CourseGrid")
    .DataSource(ds => ds
        .Ajax()
        .Events(events => events.Error("courseGridError"))
        .Model(model => model.Id(o => o.Id))
        .Read(read => read.Action("Course_Read", "Course"))
        .Destroy(destroy => destroy.Action("Course_Destroy", "Course"))
        .ServerOperation(false)
)
    .Columns(columns =>
    {
        columns.Bound(c => c.Id).Hidden();
        columns.Bound(c => c.Number);
        columns.Bound(c => c.OrganisationDisplay);
        columns.Bound(c => c.BeginDate);
        columns.Bound(c => c.EndDate);
        columns.Command(commands =>
        {
            commands.Custom("Aanpassen").Click("courseEdit");
            commands.Destroy().Text("Verwijderen");
        }).Title("Commands").Width(200);
    })
    .ToolBar(toolbar =>
    {
        toolbar.Custom().Text("Nieuwe cursus inrichten").Action("Create", "Course");
    })
    .Pageable()
    .Sortable()
    .ClientDetailTemplateId("courseDetailTemplate")
    .Selectable(selectable => selectable.Mode(GridSelectionMode.Single))
    )
 
    <script id="courseDetailTemplate" type="text/kendo-tmpl">
    @(Html.Kendo().TabStrip()
            .Name("tabStrip_#=Id#")
            .SelectedIndex(0)
            .Animation(animation => animation.Open(open => open.Fade(FadeDirection.In)))
            .Items(items =>
            {
                items.Add().Text("Inschrijvingen").Content(
                    @<text>
                        @(Html.Kendo().Grid<CourseEntryVM>()
                                .Name("entryGrid_#=Id#")
                                .Columns(columns =>
                                {
                                    columns.Bound(c => c.StudentDisplay);
                                    columns.Bound(c => c.EntryDate);
                                  })
                                  .DataSource(dataSource => dataSource
                                      .Ajax()
                                      .Model(model =>
                                      {
                                          model.Id(c => c.StudentPersonAccountId);
                                      })
                                      .PageSize(30)
                                      .Read(read => read.Action("Entry_Read", "Course", new { courseId = "#=Id#" }))
                                      .Create(create => create.Action("Entry_Create", "Course", new { courseId = "#=Id#" }))
                                      .ServerOperation(false)
                                  )
                                  .ToolBar(toolbar =>
                                  {
                                      toolbar.Create().Text("Inschrijving toevoegen");
                                  })
                                  .Editable(editable => editable.Mode(GridEditMode.PopUp))
                                  .Pageable()
                                  .Sortable()
                                  .Events(events => events.Save("entryGridSaving"))
                                  .ToClientTemplate())
                    </text>
                    );
            })
                                    .ToClientTemplate()
        )
    </script>

16 Answers, 1 is accepted

Sort by
0
Vladimir Iliev
Telerik team
answered on 30 Jul 2014, 05:40 AM
Hi Mathieu,

Please check the example below how to achieve the desired behavior:

<script>   
    $(function () {
        var uid = '#=uid#';
        var selector = kendo.format("tr[data-uid='{0}']", uid);
        var currentGridElement = $(selector).closest("[data-role=grid]");
        var parentRow = currentGridElement.closest(".k-detail-row").prev();
        var parentGrid = parentRow.closest("[data-role=grid]").data("kendoGrid");
        var parentModel = parentGrid.dataItem(parentRow);
        alert(parentModel.id);
    } )
</script>

Regards,
Vladimir Iliev
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Mathieu
Top achievements
Rank 1
answered on 30 Jul 2014, 07:32 AM
Dear,

thank you for your reply.

I'm a bit confused though. This seems to be an anonymous function. Do I need to place this in a specific event of the child grid ? If so, which one ?

Thanks
0
Vladimir Iliev
Telerik team
answered on 30 Jul 2014, 09:06 AM
Hi Mathieu,

The previously provided code can be placed inside any function in the child Grid popup template in order to get the parent row model. For example you can place the same code inside "Data" function which returns additional parameters with each request (the parameter can be used for filtering the data):

@(Html.Kendo().DropDownListFor(m => m.Users)
    .DataSource(d => d
        .Read(read => read.Action("Read", "User").Data("additionalData")

function additionalData() {
    var uid = '#=uid#';
    var selector = kendo.format("tr[data-uid='{0}']", uid);
    var currentGridElement = $(selector).closest("[data-role=grid]");
    var parentRow = currentGridElement.closest(".k-detail-row").prev();
    var parentGrid = parentRow.closest("[data-role=grid]").data("kendoGrid");
    var parentModel = parentGrid.dataItem(parentRow);
    return {
        parentModelId: parentModel.id
    };
}

Regards,
Vladimir Iliev
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
Hugo
Top achievements
Rank 1
commented on 31 Jan 2024, 10:50 PM

I am using UI for ASP.NET Core and I am having issues with the var uid. Using console.log the value is the string "#=uid#" not the uid of the row. I put the script at the top of the editortemplate file as suggested by Mathieu but it still did not work.
Ivan Danchev
Telerik team
commented on 02 Feb 2024, 03:06 PM

Hugo,

I've tested the scenario with UI for ASP.NET Core and had no issues accessing the uid. A sample project is attached. The uid is logged in the console.

 

Hugo
Top achievements
Rank 1
commented on 02 Feb 2024, 04:59 PM

Okay, so I see the issue with my approach now. In my Index.cshtml I have one main grid which calls the custom pop up edit template, not from a script template. Making the following changes to Index.cshtml replicates my issue.
@{
    ViewData["Title"] = "Home Page";
}


<h1>Grid:</h1>

@* @(Html.Kendo().Grid <TelerikAspNetCoreApp2.Models.ProductViewModel>()
    .Name("grid")
    .Columns(columns =>
    {
        columns.Bound(o => o.Id).Width(110);
        columns.Bound(o => o.ProductName).Width(110);
        columns.Bound(o => o.Price);
        columns.Bound(o => o.DateCreated).Format("{0:MM/dd/yyyy}").Width(200);
    })
    .Pageable()
    .Sortable()
    .Groupable()
    .Scrollable()
    .Filterable()
    .HtmlAttributes(new { style = "height:550px;" })
    .DataSource(dataSource => dataSource
        .Ajax()
        .PageSize(20)
        .Read(read => read.Action("Products", "Home"))
    )
    .ClientDetailTemplateId("template")
    .Events(ev => ev.DataBound("onDataBound"))
)
 *@
@(Html.Kendo().Grid<TelerikAspNetCoreApp2.Models.UserViewModel>()
       .Name("userIdGrid")
       .Columns(columns =>
       {
           columns.Bound(p => p.UserID);
           columns.Bound(p => p.RoleID);
           columns.Bound(p => p.ActiveFrom).Format("{0:MM/dd/yyyy}");
           columns.Command(c =>
           {
               c.Edit();
           });
       })
       .DataSource(dataSource => dataSource
           .Ajax()
           .Model(model =>
           {
               model.Id(p => p.RoleID);
               model.Field("ActiveFrom", typeof(DateTime));
               model.Field("ActiveTo", typeof(DateTime));
           })
           .Read(read => read.Action("UserRead", "Home"))
           .Update(update => update.Action("UserUpdate", "Home"))
       )
       .Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("UserSiteInput"))
       @* .ToClientTemplate() *@
)


<script id="template" type="text/kendo-tmpl">
</script>
<script>
    function onDataBound() {
        this.expandRow(this.tbody.find("tr.k-master-row").first());
    }
</script>


I commented out the "grid" and made the "user#=Id#" grid the main grid. My assumption that it would work the same if it was the main grid was wrong.
Ivan Danchev
Telerik team
commented on 06 Feb 2024, 12:45 PM

Hugo,

In this scenario, you will have to use a different approach to get the uid value:

function additionalData(e) {
    var ddlElement = $("#RoleID");
    var uid = ddlElement.parents(".k-popup-edit-form").attr("data-uid");

    console.log(uid)
}

Where RoleID is the name of the field the DropDownList is bound to:

@(Html.Kendo().DropDownListFor(m => m.RoleID)
...

0
Mathieu
Top achievements
Rank 1
answered on 30 Jul 2014, 02:44 PM
Dear Vladimir,

thank you for your reply.

I cannot get it to work though.

This is the editor template of  my child grid:

@(Html.Kendo().DropDownListFor(model => model.StudentPersonAccountId)
          .DataTextField("FullName")
          .DataValueField("Id")
          .OptionLabel("(Kies student)")
          .DataSource(source =>
          {
              source.Read(read =>
              {
                  read.Action("GetStudentsNotInCourseJson", "OptionList").Data("getCurrentCourse");
              })
                  .ServerFiltering(false);
          })
          )

And this is the getCurrentCourse function as per your post:

function getCurrentCourse() {
            var uid = '#=uid#';
            alert(uid);
            var selector = kendo.format("tr[data-uid='{0}']", uid);
            var currentGridElement = $(selector).closest("[data-role=grid]");
            var parentRow = currentGridElement.closest(".k-detail-row").prev();
            var parentGrid = parentRow.closest("[data-role=grid]").data("kendoGrid");
            var course = parentGrid.dataItem(parentRow);
            return {
                courseId: course.Id
            };
        }

You see that I "alert" the uid variable: the alert just says the text "#=uid" instead of an actual uid, so there must be something wrong.

Regards,

Mathieu
0
Mathieu
Top achievements
Rank 1
answered on 30 Jul 2014, 03:03 PM
Ok got it.

I was declaring the "getCurrentCourse" function on the main cshtml page, because I was under the impression that <script> sections in editortemplate.cshtml didn't work, so I always put it on the "main" page.

But now I found out that putting <script> section at the very top of the editortemplate.cshtml file does actually work, and then the uid variable gets resolved correctly.

Thanks for your help.
0
Vladimir Iliev
Telerik team
answered on 01 Aug 2014, 08:52 AM
Hi Mathieu,

Basically your findings are correct - the script tags that contains functions which are referenced from the widgets inside the template should be placed at the top of the template. This is required as the widgets initialization code is wrapped in document "ready" event handler. The page however is already loaded and the scripts are immediately executed - before the referenced functions on the page are loaded.

Regards,
Vladimir Iliev
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Ezequiel
Top achievements
Rank 2
answered on 15 Jun 2015, 01:48 PM

Hi.

 

I have a Master Grid, and the detail template have a TabStrip. Inside one for the tabs, I have a button in which, I have a javascript function on Click action.

 My Master Grid:

01.this.Html.Kendo().Grid<Stock>()
02.               .Name("GridStock")
03./* code removed for briefness */
04.                .Columns(column =>
05.                {
06.                    column.Bound(b => b.ProductId).Hidden(true);
07.                    column.Bound(b => b.Description).Width(30);
08.                    column.Bound(b => b.Supplier).Width(130);
09.                 })
10.                .ClientDetailTemplateId("stockDetail")

My client template:

1.<script id="stockDetail" type="text/kendo-tmpl">
2.@(this.Html.Kendo().TabStrip().Name("Tab_#=ProductId#").SelectedIndex(0)
3..Items(item =>
4.{
5.     item.Add().Text("Tab1").LoadContentFrom("Tab1", "MyController", new { id = "#= ProductId#" });
6.     item.Add().Text("Tab2").LoadContentFrom("Tab2", "MyController", new { id = "#= ProductId#" });
7.}).ToClientTemplate())
8.</script>

And on Tab2.cshtml I have this:

1.@(this.Html.Kendo().Button()
2.          .Content("New Request ")
3.          .Name("buttonRequest_"+this.Model.ProductId).HtmlAttributes(new { type = "button" })
4.          .Events(events => events.Click("OpenRequestWindow")))

On this OpenRequestWindow I want to get data from GridStock.

How can I get data from my Master Grid?

 

Thanks,

Ezequiel

 

 

0
Vladimir Iliev
Telerik team
answered on 16 Jun 2015, 06:28 AM
Hi Ezequiel,

You can find the Grid object using the jQuery "closest" method as demonstrated below: 

$("#somebutton").kendoButton({
    click: function(e) {
        var grid = this.element.closest("[data-role=grid]").getKendoGrid();
    }
});

Regards,
Vladimir Iliev
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Steven
Top achievements
Rank 1
answered on 09 Jun 2016, 06:59 PM

Thanks Vladimir,

This is exactly what I need but what is the format in razor as I would like to extend the method from the view not javascript?

*** so instead of the following

$("#somebutton").kendoButton({
    click: function(e) {
        var grid = this.element.closest("[data-role=grid]").getKendoGrid();
    }
});

*** the Razor version (as I see there is an option for defining the function directly instead of just providing the name

1.@(this.Html.Kendo().Button()
2.          .Content("New Request ")
3.          .Name("buttonRequest_"+this.Model.ProductId).HtmlAttributes(new { type = "button" })
4.          .Events(events => events.Click(Func<obj,obj> handler)))

 

I want to wire it in the Razor View because I thought I could bind it to the row id without the javascript lookup from .closest("tr")

Can't I wire the row id directly in the .Click Func definition instead of just calling a click javascript handler name?

instead of looking it up in the handler call skipping this line below:      var id = this.dataItem($(e.currentTarget).closest("tr"));

function loadModalDialogView(e) {
    var id = this.dataItem($(e.currentTarget).closest("tr"));
    var modalFormActionURL = "'/PCDB/GLDepartments/Edit/'";
    var modalTitleLabel = "Editing Department";
    var modalButtonText = "Update Department";
    showModalAction(modalFormActionURL + $(sender).closest('tr').attr('data-uid'), modalFormActionURL, modalButtonText, modalTitleLabel);
}

Steven Packham

0
Steven
Top achievements
Rank 1
answered on 09 Jun 2016, 07:11 PM

my apology I attached a mis-formated javascript function  *Note(I do not want a bunch of loadDepartmentEditModalDialogView function to manage, but just want to define the function in the razor view)

   --razor call:                         commands.Custom("Edit").Text("Edit").Click("loadDepartmentEditModalDialogView");

function loadDepartmentEditModalDialogView(e) {
    var id = this.dataItem($(e.currentTarget).closest("tr")).id;
    var modalFormActionURL = "/PCDB/GLDepartments/Edit/";
    var modalTitleLabel = "Editing Department";
    var modalButtonText = "Update Department";
    showModalAction(modalFormActionURL + id, modalFormActionURL, modalButtonText, modalTitleLabel);
}

Thanks again you guys rock.
0
Vladimir Iliev
Telerik team
answered on 13 Jun 2016, 07:17 AM
Hello Steven,

Binding it directly to the row is not possible out of the box when client rendering is used. In this case you should get the closest Grid using the example that I provide early. Please check the example below:

@(Html.Kendo().Button().Name("SomeButton").Events(e => e.Click("onClick")))
 

Regards,
Vladimir Iliev
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Steven
Top achievements
Rank 1
answered on 13 Jun 2016, 04:29 PM
That’s cool I did as suggested,
Lookup like you said of the events containing row, and its id works.


function loadAccountEditModalDialogView(e) {
    var id = this.dataItem($(e.currentTarget).closest("tr")).id;
    var modalFormActionURL = "/PCDB/GLAccounts/Edit/";
    var modalTitleLabel = "Editing Account";
    var modalButtonText = "Update Account";
    showModalAction(modalFormActionURL + id, modalFormActionURL, modalButtonText, modalTitleLabel);
}

function loadAccountDeleteModalDialogView(e) {
    var id = this.dataItem($(e.currentTarget).closest("tr")).id;
    var modalFormActionURL = "/PCDB/GLAccounts/Delete/";
    var modalTitleLabel = "Deleting Account";
    var modalButtonText = "Delete Account";
    showModalAction(modalFormActionURL + id, modalFormActionURL, modalButtonText, modalTitleLabel);
}

I think I originally used htmlattributes and set the onclick event and data wasn’t bound in then to my ‘tr’ or something, and this.dataItem always came up empty.
commands.Custom("Edit").Text("Edit").HtmlAttributes( onclick=”loadAccountEditModalDialogView()” )

But when you use the Kendo Grid’s columns.Command  .Click action the e.currentTarget gets bound to the data on the click, and this.dataItem find the data.

                    .Columns(columns =>
                    {
                        columns.Bound(m => m.AccountDepartment).Title("Account").Width(175);
                        columns.Bound(m => m.Description).Title("Description").Width(175);
                        columns.Bound(m => m.AccountType).Title("Type").Width(125);
                        columns.Bound(m => m.Schedule).Title("Schedule").Width(110);
                        columns.Bound(m => m.TotalLevel).Title("Level").Width(75);
                        columns.Bound(m => m.Sequence).Title("Seq #").Width(75);
                        columns.Command(commands =>
                        {
                            commands.Custom("Edit").Text("Edit").Click("loadAccountEditModalDialogView");
                            commands.Custom("Delete").Text("Delete").Click("loadAccountDeleteModalDialogView");
                        });
                    })
0
Bill
Top achievements
Rank 1
answered on 27 Jan 2018, 12:24 PM

Vladimir,

I am having issues running the code sample you provided.  I too am trying to return some information from a parent grid to populate a dynamic dropdown list in a child grid.

To start off... if I hard-code a return value (for testing purposes) in my script, everything works fine as far as the EditorTemplate is concerned.   Like this for example:

<script>
    function getCurrentPublisher() {
        return {
            publisherID: 107
        };
    }
</script>

If I add the code in the examples above, somewhere I get an error, and I am having trouble debugging the issue.  For instance, if I add the 1st few lines, and still hard-code my return value, the script does not error...

<script>
    function getCurrentPublisher() {
        var uid = '#=uid#';
        window.alert(uid);
        var selector = kendo.format("tr[data-uid='{0}']", uid);
        var currentGridElement = $(selector).closest("[data-role=grid]");
        var parentRow = currentGridElement.closest(".k-detail-row").prev();
        var parentGrid = parentRow.closest("[data-role=grid]").data("kendoGrid");
        
        return {
            publisherID: 107
        };
    }
</script>

As soon as I add the line that references the parentGrid/ParentRow  (after var parentGrid = parentRow.closest("[data-role=grid]").data("kendoGrid");)   like this:

var authHead = parentGrid.dataItem(parentRow);

... well then I seem to just get stuck.  The dropdown list shows a loading icon that spins indefinitely.  If I try to access my 'authHead' object and return an actual, dynamic value, then my script goes into error and my dropdown list looks like a text box.  So I am not sure that the'var authHead = parentGrid.dataItem(parentRow);' line of code is causing an error... it just never seems to move on.

Have you ever seen this before?  Can ou think of a reason why this is not working?  Also, is there a way I can show the UID of each row in the grid just for debugging purposes?  I am using Kendo MVC 2017.3.1026.

Thanks,

-Bill

0
Bill
Top achievements
Rank 1
answered on 27 Jan 2018, 02:28 PM

Vladimir,

You can ignore my prior post, thank you.  I just realized I might be able to see the ID's in Chromes inspector.  Turns out I was able to see the uid's and it helped me debug my issue!  I think I am OK, now... everything is working as expected.

Thanks,

Bill

0
chetan
Top achievements
Rank 1
answered on 21 May 2018, 11:01 AM

Hi 

I have problem in Master and child grid  dynamically Binding because i am using Uniqueidentifier datatype of ID 

in clienttemplateID()  have to show Invalid Template .

so please give me suggestion 

        @(Html.Kendo().Grid<ShipmentModel.Delivery.DoCreation_Viewmodel>()
            .Name("gridmain1")
            .Columns(columns =>
            {

               // columns.Bound(p => p.shipmentid_Guid).Width(100);
                columns.Bound(p => p.mawbno).Width(120);
                columns.Bound(p => p.hawbno).Width(120);
                columns.Bound(p => p.ShipperName).Width(120);
                columns.Bound(p => p.ConsigneeName).Width(120);
                columns.Bound(p => p.NetWeight).Width(120);
                columns.Bound(p => p.NetQty).Width(120);
                columns.Bound(p => p.AvailableQty).Width(120);
                columns.Bound(p => p.AvailableWeight).Width(120);

                columns.Bound(p => p.Commodity).Width(150);
                columns.Bound(p => p.branchname).Width(150);



            })

            .Pageable(p => p.PageSizes(new List<object> { 5, 10, 20, 100 }))
            .Sortable()
            .Scrollable()
            
            .ClientDetailTemplateId("templatedelivery")
            .Filterable(f => f.Mode(GridFilterMode.Row))
            .HtmlAttributes(new { style = "height:400px;" })
            .DataSource(dataSource => dataSource
            .Ajax()
            .PageSize(20)
            .Read(read => read.Action("DeliveryCreationlist", "Test"))


            )
             .Events(events => events.DataBound("dataBound"))
            .Resizable(resize => resize.Columns(true))
            .Reorderable(reorder => reorder.Columns(true))
        )

Child Gride is

<script type="text/x-kendo-template" id="templatedelivery">
    @(Html.Kendo().Grid<ShipmentModel.Delivery.DoCreation_Viewmodel>()
            .Name("grddel_#=shipmentid_Guid#")
            .Columns(columns =>
            {
                columns.Bound(p => p.shipmentid_Guid).Width(100);
                columns.Bound(p => p.mawbno).Width(120);
                columns.Bound(p => p.hawbno).Width(120);
                columns.Bound(p => p.ShipperName).Width(120);
                columns.Bound(p => p.ConsigneeName).Width(120);
                columns.Bound(p => p.NetWeight).Width(120);
                columns.Bound(p => p.NetQty).Width(120);
                columns.Bound(p => p.AvailableQty).Width(120);
                columns.Bound(p => p.AvailableWeight).Width(120);

                columns.Bound(p => p.Commodity).Width(150);
                columns.Bound(p => p.branchname).Width(150);
            })

          //  .Filterable(f => f.Mode(GridFilterMode.Row))
            .HtmlAttributes(new { style = "height:400px;" })
            .DataSource(dataSource => dataSource
            .Ajax()
           // .Model(model => model.Id(c => c.shipmentid_Guid))
        .PageSize(20)
        .Read(read => read.Action("ChildDelivery_Read", "Test", new { shipmentid_Guid = "#=shipmentid_Guid#" }))
        )
        .Pageable()
        .Sortable()
        .ToClientTemplate()


    )


</script>

 

0
Stefan
Telerik team
answered on 22 May 2018, 07:22 AM
Hello, Chetan,

Thank you for the details.

I tried making an example using Uniqueidentifier datatype as ID, but the Grid was rendered as expected.

Could you please share with us the error message, and also the values of the shipmentid_Guid, as we can check if there are any, not allowed characters used as id.

I will be expecting the additional details and gladly assist further.

Regards,
Stefan
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Tags
Grid
Asked by
Mathieu
Top achievements
Rank 1
Answers by
Vladimir Iliev
Telerik team
Mathieu
Top achievements
Rank 1
Ezequiel
Top achievements
Rank 2
Steven
Top achievements
Rank 1
Bill
Top achievements
Rank 1
chetan
Top achievements
Rank 1
Stefan
Telerik team
Share this question
or