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

13 posts, 0 answers
  1. Mathieu
    Mathieu avatar
    21 posts
    Member since:
    Feb 2014

    Posted 26 Jul 2014 Link to this post

    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>
  2. Vladimir Iliev
    Admin
    Vladimir Iliev avatar
    2172 posts

    Posted 30 Jul 2014 Link to this post

    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.

     
  3. UI for ASP.NET MVC is VS 2017 Ready
  4. Mathieu
    Mathieu avatar
    21 posts
    Member since:
    Feb 2014

    Posted 30 Jul 2014 in reply to Vladimir Iliev Link to this post

    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
  5. Vladimir Iliev
    Admin
    Vladimir Iliev avatar
    2172 posts

    Posted 30 Jul 2014 Link to this post

    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.

     
  6. Mathieu
    Mathieu avatar
    21 posts
    Member since:
    Feb 2014

    Posted 30 Jul 2014 in reply to Vladimir Iliev Link to this post

    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
  7. Mathieu
    Mathieu avatar
    21 posts
    Member since:
    Feb 2014

    Posted 30 Jul 2014 in reply to Mathieu Link to this post

    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.
  8. Vladimir Iliev
    Admin
    Vladimir Iliev avatar
    2172 posts

    Posted 01 Aug 2014 Link to this post

    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.

     
  9. Ezequiel
    Ezequiel avatar
    36 posts
    Member since:
    Oct 2011

    Posted 15 Jun 2015 Link to this post

    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

     

     

  10. Vladimir Iliev
    Admin
    Vladimir Iliev avatar
    2172 posts

    Posted 16 Jun 2015 Link to this post

    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
  11. Steven
    Steven avatar
    4 posts
    Member since:
    May 2016

    Posted 09 Jun in reply to Vladimir Iliev Link to this post

    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

  12. Steven
    Steven avatar
    4 posts
    Member since:
    May 2016

    Posted 09 Jun in reply to Steven Link to this post

    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.
  13. Vladimir Iliev
    Admin
    Vladimir Iliev avatar
    2172 posts

    Posted 13 Jun Link to this post

    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
  14. Steven
    Steven avatar
    4 posts
    Member since:
    May 2016

    Posted 13 Jun in reply to Vladimir Iliev Link to this post

    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");
                            });
                        })
Back to Top
UI for ASP.NET MVC is VS 2017 Ready