Implement master details concept in asp.net mvc with kendoui using separated/not embeded grids

6 posts, 1 answers
  1. Tomas
    Tomas avatar
    41 posts
    Member since:
    Feb 2011

    Posted 27 Mar 2013 Link to this post

    I do not find any demo which show how to implement Master/Detail using two separated Grids. I found demo where Master Grid has Child grid embedded as template, while user click + icon the child grid appears inside master grid.

    I would like to have child grid on the page like master grid without embedding it into master grid. I do not find such demo anywhere.  
  2. Dimiter Madjarov
    Admin
    Dimiter Madjarov avatar
    2312 posts

    Posted 27 Mar 2013 Link to this post

    Hello Tomas,


    This functionality is not supported out of the box. Nevertheless it could be achieved manually, if you initialize two separate Grids and specify the AutoBind(false) option for the second one, which will force it to not bind the dataSource during initialization. Then you could bind it's data, when a certain event happens.

    I am not aware when do you want to bind the data for the Child Grid, but a sample scenario would be to do it, when a row is selected from the Master Grid. I am attaching a sample project, which demonstrates this.

    I hope this will work in your scenario.

     

    Kind regards,
    Dimiter Madjarov
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  3. Tomas
    Tomas avatar
    41 posts
    Member since:
    Feb 2011

    Posted 09 Apr 2013 Link to this post

    I have implemented master/detail grid folowing your example but now I have another problem. When I try to filter the detail grid(second one) I get the error. Any idea how to pass productId while filtering?

    The parameters dictionary contains a null entry for parameter 'productId' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Users_Read(Kendo.Mvc.UI.DataSourceRequest, Int32)' in 'PC.Controllers.AdminController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
    Parameter name: parameters

    The source code

    @(Html.Kendo().Grid<AdminProductViewModel>()
          .Name("Products")
          .Columns(columns =>
              {
                  columns.Bound(c => c.Id).Width(130);
                  columns.Bound(c => c.Name).Width(250);
                  columns.Bound(c => c.UsersCount).Width(50);
                  /*columns.Command(c => c.Custom("New User").SendDataKeys(true).Action("InsertUser", "Admin"));*/
              })
          .DataSource(dataSource => dataSource
                                        .Ajax()/*.ServerOperation(true)*/
                                        .Read(read => read.Action("Products_Read", "Admin"))
                                        .Model(x => x.Id(model => model.Id))
          )
          .Pageable().Sortable().Selectable()      
          .ToolBar(toolBar => toolBar.Custom().Text("Queue Info").Action("QueueInfo", "Admin"))
          .ToolBar(toolBar => toolBar.Custom().Text("Queue Manager").Action("QueueManager", "Admin"))
          .ToolBar(toolBar => toolBar.Custom().Text("Thread Info").Action("ThreadInfo", "Admin"))
          .ToolBar(toolBar => toolBar.Custom().Name("NewUser").Text("New User").Action("InsertUser", "Admin"))

         .Events(events => events.Change("change"))
         .Events(events => events.DataBound("dataBound"))
          )


    @(Html.Kendo().Grid<AdminUserViewModel>()
    .Name("Users")
    .AutoBind(false)
    .Columns(columns =>
    {
        columns.Command(commands =>
        {
            commands.Edit();
            commands.Destroy();
        }).Width(150);
        columns.Bound(c => c.Id).Width(20)/*.ReadOnly()*/;
        columns.Bound(c => c.DateStamp).Width(20).Format("{0:MMM d, yyyy}")/*.ReadOnly()*/;
        columns.Bound(c => c.Active).Width(20);
        columns.Bound(c => c.FirstName).Width(200);
        columns.Bound(c => c.LastName).Width(200);
        columns.Bound(c => c.Email).Width(200);
        columns.Bound(c => c.InitialEmail).Hidden();    

    })
    .DataSource(dataSource => dataSource
            .Ajax()
            .Read(x => x.Action("Users_Read", "Admin"))
            .Update("User_Update", "Admin")
            .Destroy("User_Delete", "Admin")
            .Model(x => x.Id(model => model.Id))
        )
    .Pageable().Sortable().Filterable().Selectable()
    .ToolBar(toolBar => toolBar.Custom().Name("Login").Text("Login").Action("LoginUser", "Admin"))

    )

    <script>
      function change(e) {
            var selectedData = this.dataItem(this.select());
            var productId = selectedData.Id;

            $("#Users").data("kendoGrid").dataSource.read({ productId: productId });
        }
    </script>

        public ActionResult Users_Read([DataSourceRequest]DataSourceRequest request, int productId)
            {
                var users = GerUsers(productId).Select(p => new AdminUserViewModel
                    {
                        Id = p.Id,
                        Active = p.Active,
                        Email = p.Email,
                        InitialEmail = p.Email,
                        FirstName = p.FirstName,
                        LastName = p.LastName,
                        DateStamp = p.DateStamp
                    });

                return Json(users.ToDataSourceResult(request));
            }
  4. Answer
    Dimiter Madjarov
    Admin
    Dimiter Madjarov avatar
    2312 posts

    Posted 11 Apr 2013 Link to this post

    Hi Tomas,


    This behavior is expected since the second Grid by default is using server operations for sorting, paging, filtering etc. and currently the productId is not passed to the Read Action except in the initial read. A possible solution would be to either disable the server operations i.e. all operations would be done on the client side.
    E.g.
    .DataSource(ds => ds
      .Ajax()
      .ServerOperation(false)
      ...
    )

    OR

    use the Data method to add a JavaScript function, which will always return the additional data required for the Read Action.
    E.g.
    .DataSource(ds => ds
       .Ajax()
       .Read(read => read.Action("Orders", "Home").Data("additionalData"))
    )

    <script>
        function additionalData() {
            return {
                employeeId : empId
            }
        }
    </script>

     

    Greetings,
    Dimiter Madjarov
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  5. Richard
    Richard avatar
    149 posts
    Member since:
    Feb 2012

    Posted 22 Jan 2017 in reply to Dimiter Madjarov Link to this post

    Dimiter:

    In the MasterChildDemo the child grid's data source is 

    .DataSource(ds => ds
      .Ajax()
      .ServerOperation(false)
      .Read(read => read.Action("Orders", "Home"))
    )

    and, as you state, read is invoked once from javascript when a row in the master grid is selected

    $("#Child").data("kendoGrid").dataSource.read({ employeeId: empId });

     

    My question is the implementation of the HomeController Orders request handler. Specifically the signature of the method.

    Why are there two similar args: employeeID and employeeId ?

    How does asp server go from receiving a POST with form data like sort=&group=&filter=&employeeId=1 to matching up with the proper ActionResult handler ?

    public ActionResult Orders(int employeeID, [DataSourceRequest] DataSourceRequest request, int employeeId)
    {
        NorthwindEntities db = new NorthwindEntities();
        var orders = db.Orders.Where(o => o.EmployeeID == employeeId).Select(p => new OrderViewModel()
        {
            OrderID = p.OrderID,
            ShipCountry = p.ShipCountry,
            ShipCity = p.ShipCity
        });
        return Json(orders.ToDataSourceResult(request));
    }
  6. Dimiter Madjarov
    Admin
    Dimiter Madjarov avatar
    2312 posts

    Posted 23 Jan 2017 Link to this post

    Hello RichardAD,

    This looks like a typo in the attached project. Only the employeeId parameter is needed to be present in the controller action.

    Regards,
    Dimiter Madjarov
    Telerik by Progress
    Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Back to Top