Three, Four or more level of hierarchy on a grid

34 posts, 0 answers
  1. Mithun
    Mithun avatar
    2 posts
    Member since:
    Nov 2007

    Posted 22 Feb 2013 Link to this post

    Hi,

    This demonstration very nicely shows how to implement two level hierarchy on a kendo grid. http://demos.kendoui.com/web/grid/hierarchy.html

    I tried using the same coding structure to implement three or four levels of hierarchy but couldn't get it to work properly. It works, but the third level grid overwrites and overlaps the second level grid. Please could you let me know if three, four or more levels of hierarchy is possible on kendo web grid and if yes, I'll be grateful if you could point me to an example.

    Many Thanks
    MB
  2. Vladimir Iliev
    Admin
    Vladimir Iliev avatar
    2206 posts

    Posted 26 Feb 2013 Link to this post

    Hi Mithun,

     
    It's possible to implement more than two nested grids using the same approach from the online demo, however currently there is no such demo which we can provide. Also from the provided information it's not clear for us what is the exact reason for overwriting/overlapping the parent grid - could you please provide your current grid code and more details how to reproduce the issue on our side?

    Kind Regards,
    Vladimir Iliev
    the Telerik team
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  3. Mithun
    Mithun avatar
    2 posts
    Member since:
    Nov 2007

    Posted 03 Mar 2013 Link to this post

    Hi Vladimir ,

    Thanks for getting back to me. Yes I did realize at a later stage that n level nested grids is indeed possible. What was happening in my case is the third level grid was ending up with same name as the second level grid; therefore, it was overlapping. I changed the dynamic naming logic on all levels and made sure that they are always unique and it worked like a charm after that!

    Many thanks for offering help.

    Much Appreciated,
    Mithun
  4. Stephen
    Stephen avatar
    158 posts
    Member since:
    Jan 2009

    Posted 30 May 2013 Link to this post

    Hello,

    I am having a problem making this happen.  I would like to have a grid with a tabstrip in it's detailtemplate.  That would contain another grid.  That grid would have a tabstrip in its detailtemplate which would in turn contain another grid.

    GRID 1
        TabStrip
        -GRID 2
            TabStrip
            -GRID 3

    I am using razor with server binding and I receive the following error:

    Warning 1 Inline markup blocks (@<p>Content</p>) cannot be nested.  Only one level of inline markup is allowed.

    Here is my code:
    @{ Html.Kendo().Grid(Model)
        .Name("gvLaboratories")
        .Columns(columns =>
        {
            columns.Bound(l => l.ID);
            columns.Bound(l => l.Description);
        })
        .DetailTemplate(l =>
        {
            Html.Kendo().TabStrip()
                .Name("ts" + l.ID)
                .SelectedIndex(0)
                .Items(items =>
                {
                    items.Add().Text("User Facilities").Content(@<text>
                                     
                        @(Html.Kendo().Grid(l.User_Facilities)
                            .Name("gvUserFacilities" + l.ID)
                            .Columns(columns =>
                            {
                                columns.Command(command => { command.Edit(); }).Width(50);
                                columns.Bound(f => f.ID);
                                columns.Bound(f => f.Description);
                                columns.Command(command => { command.Destroy(); }).Width(50);
                            })
                            .DetailTemplate(f =>
                            {
                                Html.Kendo().TabStrip()
                                    .Name("ts" + f.ID)
                                    .SelectedIndex(0)
                                    .Items(childitems =>
                                    {
                                        childitems.Add().Text("User Facility Admins").Content(@<text>       
     
                                            @(Html.Kendo().Grid(f.Users_Roles)
                                                .Name("gvUserFacilityAdmins" + f.ID)
                                                .Columns(columns =>
                                                {
                                                    columns.Bound(a => a.User_ID).Template(a => a.User_ID.ToString()).Title("User ID");
                                                    columns.Bound(a => a.User.BNL_ID).Title("BNL ID");
                                                    columns.Bound(a => a.User.Pool.First_Name).Title("First Name");
                                                    columns.Bound(a => a.User.Pool.Last_Name).Title("Last Name");
                                                    columns.Bound(a => a.User.Account).Title("BNL Account");
                                                    columns.Command(command => { command.Destroy(); }).Width(50);
                                                })
                                                .ToolBar(toolbar => toolbar.Create())
                                                .Editable(editable => editable.Mode(GridEditMode.PopUp))
                                                .Sortable()
                                                .DataSource(dataSource => dataSource
                                                    .Server()
                                                    .Model(model => model.Id(a => a.User_ID))
                                                    .Read(read => read.Action("UserFacilities", "LabAdmin", new { facilityID = f.ID }))
                                                    .Create(create => create.Action("AddUserFacilityAdmin", "LabAdmin"))
                                                    .Destroy(destroy => destroy.Action("DeleteUserFacilityAdmin", "LabAdmin"))
                                                )
                                            )
     
                                        </text>);
                                    })
                                    .Render();
                            })
                            .ToolBar(toolbar => toolbar.Create())
                            .Editable(editable => editable.Mode(GridEditMode.PopUp))
                            .Sortable()
                            .DataSource(dataSource => dataSource
                                .Server()
                                .Model(model =>
                                {
                                    model.Id(f => f.ID);
                                    model.Field(field => field.ID).DefaultValue("");
                                    model.Field(field => field.Description).DefaultValue("");
                                })
                                .Create(create => create.Action("AddUserFacility", "LabAdmin"))
                                .Read(read => read.Action("UserFacilities", "LabAdmin", new { labID = l.ID }))
                                .Update(update => update.Action("UpdateUserFacility", "LabAdmin"))
                                .Destroy(destroy => destroy.Action("DeleteUserFacility", "LabAdmin"))
                            )
                            .RowAction(row =>
                            {
                                if (row.DataItem.ID.ToString() == Request.QueryString["facilityID"])
                                {
                                    row.DetailRow.Expanded = true;
                                }
                            })                       
                        )
                                     
                    </text>);
                })
                .Render();
        })
        .Pageable()
        .Sortable()
        .DataSource(dataSource => dataSource
            .Server()
            .Model(model => model.Id(l => l.ID))
            .Read(read => read.Action("UserFacilities", "LabAdmin"))
        )
        .RowAction(row =>
        {
            if (row.DataItem.ID.ToString() == Request.QueryString["labID"])
            {
                row.DetailRow.Expanded = true;
            }
        })
        .Render();
    }

    How else should I code the third grid if I can't use the inline markup blocks?

    Thanks,

    Steve

  5. Daniel
    Admin
    Daniel avatar
    2231 posts

    Posted 03 Jun 2013 Link to this post

    Hello Stephen,

    This is a limitation of the Razor view engine. Tags cannot be nested. In order to avoid the exception I can suggest to use a helper:

    .DetailTemplate(f => myDetailDetailViewTemplate(this, f))
    @helper myDetailDetailViewTemplate(WebViewPage page, MyModel f)
    {
       @{
            Html.Kendo().TabStrip()
                .Name("ts" + f.ID)
                .SelectedIndex(0)
                .Items(childitems =>
                {
                    childitems.Add().Text("User Facility Admins").Content(@<text>
                    ...
                             
         
    }

    or the action overload of the Content method and the Render method for the inner controls:
    Html.Kendo().TabStrip()
        .Name("ts" + f.ID)
        .SelectedIndex(0)
        .Items(childitems =>
        {
            childitems.Add().Text("User Facility Admins").Content(() =>
                    Html.Kendo().Grid(f.Users_Roles)
                        ...
                        .Render()
                )


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

    Posted 05 Jun 2013 Link to this post

    Hello,

    Thanks for the info.  I tried the action overload of the Content method (which is what I would prefer to use) but I was getting multiple errors so I tried the helper method which is the one I have seen most frequently used.  I am getting an error there as well.  It says there is an argument missing on this line: 
    @{ Html.Kendo().TabStrip()

    Any ideas?

    Thanks,

    Steve

  7. Stephen
    Stephen avatar
    158 posts
    Member since:
    Jan 2009

    Posted 05 Jun 2013 Link to this post

    Ok so I changed it from being in a code block to the normal syntax and that worked:
    @(Html.Kendo().TabStrip()
         .......
     )

    But the problem I am having now is a similar issue I experienced previously with a 2-level grid.  Both levels of grid are editable but when I click and edit or add, before the popup would show the tab item would collapse.  This was fixed by adding a parameter that indicates which row should be expanded and expand it in the master Grid RowAction callback.

    I have that done here as well but now that it is in the helper template it is not working, at least not reliably.

    Here is my full view code:
    @helper myDetailViewTemplate(WebViewPage page, PASSLibrary.User_Facilities f)
    {
        @(Html.Kendo().TabStrip()
                .Name("tabstrip" + f.ID)
                .SelectedIndex(0)
                .Items(childitems =>
                {
                    childitems.Add().Text("User Facility Admins").Content(
                        @<text>       
                            @(Html.Kendo().Grid(f.Users_Roles)
                                .Name("gridUserFacilityAdmins" + f.ID)
                                .Columns(columns =>
                                {
                                    columns.Bound(a => a.User_ID).Template(a => a.User_ID.ToString()).Title("User ID");
                                    columns.Bound(a => a.User.BNL_ID).Title("BNL ID");
                                    columns.Bound(a => a.User.Pool.First_Name).Title("First Name");
                                    columns.Bound(a => a.User.Pool.Last_Name).Title("Last Name");
                                    columns.Bound(a => a.User.Account).Title("BNL Account");
                                    columns.Command(command => { command.Destroy(); }).Width(50);
                                })
                                .ToolBar(toolbar => toolbar.Create())
                                .Editable(editable => editable.Mode(GridEditMode.PopUp))
                                .Sortable()
                                .DataSource(dataSource => dataSource
                                    .Server()
                                    .Model(model => model.Id(a => a.User_ID))
                                    .Read(read => read.Action("UserFacilities", "LabAdmin", new { facilityID = f.ID }))
                                    .Create(create => create.Action("AddUserFacilityAdmin", "LabAdmin"))
                                    .Destroy(destroy => destroy.Action("DeleteUserFacilityAdmin", "LabAdmin"))
                                )
                            )
                        </text>
                    );
                })
        )
    }
     
    @{ Html.Kendo().Grid(Model)
        .Name("gridLaboratories")
        .Columns(columns =>
        {
            columns.Bound(l => l.ID);
            columns.Bound(l => l.Description);
        })
        .DetailTemplate(
            @<text>                  
                @(Html.Kendo().Grid(item.User_Facilities)
                    .Name("gridUserFacilities" + item.ID)
                    .Columns(columns =>
                    {
                        columns.Command(command => { command.Edit(); }).Width(50);
                        columns.Bound(f => f.ID);
                        columns.Bound(f => f.Description);
                        columns.Command(command => { command.Destroy(); }).Width(50);
                    })
                    .DetailTemplate(f => myDetailViewTemplate(this, f))
                    .ToolBar(toolbar => toolbar.Create())
                    .Editable(editable => editable.Mode(GridEditMode.PopUp))
                    .Sortable()
                    .DataSource(dataSource => dataSource
                        .Server()
                        .Model(model =>
                        {
                            model.Id(f => f.ID);
                            model.Field(field => field.ID).DefaultValue("");
                            model.Field(field => field.Description).DefaultValue("");
                        })
                        .Create(create => create.Action("AddUserFacility", "LabAdmin"))
                        .Read(read => read.Action("UserFacilities", "LabAdmin", new { labID = item.ID }))
                        .Update(update => update.Action("UpdateUserFacility", "LabAdmin"))
                        .Destroy(destroy => destroy.Action("DeleteUserFacility", "LabAdmin"))
                    )
                    .RowAction(row =>
                    {
                        if (row.DataItem.ID.ToString() == Request.QueryString["facilityID"])
                        {
                            row.DetailRow.Expanded = true;
                        }
                    })
                )
            </text>
        )
        .Pageable()
        .Sortable()
        .DataSource(dataSource => dataSource
            .Server()
            .Model(model => model.Id(l => l.ID))
            .Read(read => read.Action("UserFacilities", "LabAdmin"))
        )
        .RowAction(row =>
        {
            if (row.DataItem.ID.ToString() == Request.QueryString["labID"])
            {
                row.DetailRow.Expanded = true;
            }
        })
        .Render();
    }

    Can you see anything missing or does this not work when it is in a helper template?  If so, would it work using the other method of overloading the Content method?

    Thanks for all of the help.

    Steve




  8. Daniel
    Admin
    Daniel avatar
    2231 posts

    Posted 07 Jun 2013 Link to this post

    Hello Steve,

    There should not be any difference if the Grid is added with a helper. Which row is not expanded correctly? If the "gridLaboratories" Grid row is not expanded then you should pass "labID" also with the "gridUserFacilityAdmins" read request. 

    Regards,
    Daniel
    Telerik
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  9. Stephen
    Stephen avatar
    158 posts
    Member since:
    Jan 2009

    Posted 07 Jun 2013 Link to this post

    Hi,

    Yes it is the "gridLaboratories".  What would the syntax be for sending multiple route values?  I see the read.Action overload can take a routeDictionary instead of object type for the route values so maybe that's what to do but I'm not sure how to form that.

    Currently I have:
    .Read(read => read.Action("UserFacilities", "LabAdmin", new { facilityID = f.ID }))
    Thanks,

    Steve

  10. Daniel
    Admin
    Daniel avatar
    2231 posts

    Posted 10 Jun 2013 Link to this post

    Hello Steve,

    You should pass the ID as parameter to the helper and then add it to the "gridUserFacilityAdmins" Grid route values:

    .DetailTemplate(f => myDetailViewTemplate(this, f, item.ID))
    @helper myDetailViewTemplate(WebViewPage page, PASSLibrary.User_Facilities f, int labID){
            ...           
            .Read(read => read.Action("UserFacilities", "LabAdmin", new { facilityID = f.ID, labID  =  labID}))
    Regards,
    Daniel
    Telerik
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  11. Stephen
    Stephen avatar
    158 posts
    Member since:
    Jan 2009

    Posted 11 Jun 2013 Link to this post

    perfect thanks!
  12. Stephen
    Stephen avatar
    158 posts
    Member since:
    Jan 2009

    Posted 12 Jun 2013 Link to this post

    Another question :)

    In this same scenario with the nested grids, in the popup editor of the second grid, how can I show the popup editor without the field for the primary key from the first grid?

    For example, I have my main grid listing Laboratories and my nested grid showing the Facilities in that Laboratory.  So once I have expanded a particular Laboratory and I want to add a new Facility, I already now what the Laboratory_ID is for this new Facility since I am in that grid.  I can set the default value for that field in the model (as shown below) but how do I not show that field in the editor?
    .DataSource(dataSource => dataSource
        .Server()
        .Model(model =>
        {
            model.Id(f => f.ID);
            model.Field(field => field.ID).DefaultValue("");
            model.Field(field => field.Description).DefaultValue("");
            model.Field(field => field.Laboratory_ID).DefaultValue(item.ID);
        })
    Thanks again,

    Steve



  13. Daniel
    Admin
    Daniel avatar
    2231 posts

    Posted 14 Jun 2013 Link to this post

    Hello Steve,

    In PopUp editing you could use an attribute on the property (ScaffoldColumn or HiddenInput) or create a custom editor template as demonstrated in this code-library in order to not show an editor for a field.

    Regards,
    Daniel
    Telerik
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  14. Stephen
    Stephen avatar
    158 posts
    Member since:
    Jan 2009

    Posted 14 Jun 2013 Link to this post

    Ok I am able to do this with the custom editor template but then since the Laboratory_ID field is not there it is not passing the value back.  I thought if I had the default value set in the grid then it would pass it but I guess when you use the custom editor and leave out that field it doesn't do that.  So in this case, how do I get it to update the model with the Laboratory_ID?  DO I have to modify my Controller method and manually pass it as a parameter?

    Currently my datasource on the grid looks like this:
    .DataSource(dataSource => dataSource
        .Server()
        .Model(model =>
        {
            model.Id(f => f.ID);
            model.Field(field => field.ID).DefaultValue("");
            model.Field(field => field.Description).DefaultValue("");
            model.Field(field => field.Laboratory_ID).DefaultValue(item.ID);
        })
        .Create(create => create.Action("AddUserFacility", "LabAdmin"))
        .Read(read => read.Action("UserFacilities", "LabAdmin", new { labID = item.ID }))
        .Update(update => update.Action("UpdateUserFacility", "LabAdmin"))
        .Destroy(destroy => destroy.Action("DeleteUserFacility", "LabAdmin"))
    )
    and my Controller method looks like this:
    [Authorize(Roles = "Lab_Admin")]
    [HttpPost]
    public ActionResult AddUserFacility(User_Facilities user_facility)
    {
        try
        {
            using (PASSEntities context = new PASSEntities())
            {
                context.User_Facilities.Add(user_facility);
                context.SaveChanges();
            }
            return RedirectToAction("UserFacilities");
        }
        catch
        {
            return View();
        }
    }
    And here is my custom editor template:
    @model PASSLibrary.User_Facilities
     
    @Html.HiddenFor(model => model.ID)
     
    <div class="editor-label">
        @Html.Label("ID")
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.ID)
        @Html.ValidationMessageFor(model => model.ID)
    </div>
     
    <div class="editor-label">
        @Html.Label("Description")
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Description)
        @Html.ValidationMessageFor(model => model.Description)
    </div>


  15. Daniel
    Admin
    Daniel avatar
    2231 posts

    Posted 18 Jun 2013 Link to this post

    Hello,

    If you do not wish to show the "Laboratory_ID" and it is needed to send it to the server then you should use a hidden input:

    @Html.HiddenFor(model => model.ID)
    @Html.HiddenFor(model => model.Laboratory_ID)

    Regards,
    Daniel
    Telerik
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  16. Stephen
    Stephen avatar
    158 posts
    Member since:
    Jan 2009

    Posted 18 Jun 2013 Link to this post

    Hi Daniel,

    Thanks for that.  I added the hidden to the custom edit template and it works for me on the edit but on the add I get an error that it cannot find the view, which of course is there, so it seems like it is maybe not passing the Laboratory_ID for the add?  Any other insight on that?  My code is still the same as above with of course the hidden added to the editor template.

    Thanks,

    Steve



  17. Daniel
    Admin
    Daniel avatar
    2231 posts

    Posted 20 Jun 2013 Link to this post

    Hello Steve,

    I am not sure what could be causing this problem. Even if the parameter is not passed the exception should be different. Could you provide the code for the controller so I can check the exact setup?

    Regards,
    Daniel
    Telerik
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  18. Stephen
    Stephen avatar
    158 posts
    Member since:
    Jan 2009

    Posted 25 Jun 2013 Link to this post

    Sure thanks.  Here is the controller code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using PASSLibrary;
     
    namespace PASSAdmin.Controllers
    {
        public class LabAdminController : Controller
        {
     
            public ActionResult Index()
            {
                return View();
            }
             
            #region User Facilities
     
            [Authorize(Roles = "Lab_Admin")]
            public ActionResult UserFacilities()
            {
     
                var context = new PASSEntities();
     
                IEnumerable<Laboratory> labList = (from l in context.Laboratories
                                        join ur in context.Users_Roles on l.ID equals ur.Laboratory_ID
                                        join u in context.Users on ur.User_ID equals u.ID
                                        join r in context.Roles on ur.Role_ID equals r.ID
                                        where u.Account == User.Identity.Name.Substring(4) && r.Name == "Lab_Admin"
                                        select l).ToList();
     
                return View(labList);
            }
     
            [Authorize(Roles = "Lab_Admin")]
            [HttpPost]
            public ActionResult AddUserFacility(User_Facilities user_facility)
            {
                try
                {
                    using (PASSEntities context = new PASSEntities())
                    {
                        context.User_Facilities.Add(user_facility);
                        context.SaveChanges();
                    }
                    return RedirectToAction("UserFacilities");
                }
                catch
                {
                    return View();
                }
            }
     
            [Authorize(Roles = "Lab_Admin")]
            [HttpPost]
            public ActionResult DeleteUserFacility(string id, User_Facilities user_facility)
            {
                try
                {
                    using (PASSEntities context = new PASSEntities())
                    {
                        context.Entry(user_facility).State = System.Data.EntityState.Deleted;
                        context.SaveChanges();
                    }
                    return RedirectToAction("UserFacilities");
                }
                catch
                {
                    return View();
                }
            }
     
            [Authorize(Roles = "Lab_Admin")]
            [HttpPost]
            public ActionResult UpdateUserFacility(string id, User_Facilities user_facility)
            {
                try
                {
                    using (PASSEntities context = new PASSEntities())
                    {
                        context.Entry(user_facility).State = System.Data.EntityState.Modified;
                        context.SaveChanges();
                        return RedirectToAction("UserFacilities");
                    }
                }
                catch
                {
                    return View();
                }
            }
            #endregion
     
            #region User Facility Admins
     
            [Authorize(Roles = "Lab_Admin")]
            [HttpPost]
            public ActionResult AddUserFacilityAdmin(Users_Roles user_role)
            {
                try
                {
                    using (PASSEntities context = new PASSEntities())
                    {
                        context.Users_Roles.Add(user_role);
                        context.SaveChanges();
                    }
                    return RedirectToAction("UserFacilities");
                }
                catch
                {
                    return View();
                }
            }
     
            [Authorize(Roles = "Lab_Admin")]
            [HttpPost]
            public ActionResult DeleteUserFacilityAdmin(int id, Users_Roles user_role)
            {
                try
                {
                    using (PASSEntities context = new PASSEntities())
                    {
                        context.Entry(user_role).State = System.Data.EntityState.Deleted;
                        context.SaveChanges();
                    }
                    return RedirectToAction("UserFacilities");
                }
                catch
                {
                    return View();
                }
            }
            #endregion
     
        }
    }

    Please let me know if you need anything else.  Obviously there is an issue since its not working, but I think as you pointed out I am also having another problem in my solution with the error messages.  I have client side validation enabled and unobtrusive javascript enabled in my web config but I keep getting errors like I have described when I should be getting other error messages.

  19. Daniel
    Admin
    Daniel avatar
    2231 posts

    Posted 27 Jun 2013 Link to this post

    Hello Steve,

    From the code it seems that the described problem will occur if an exception is thrown when saving the changes. A ViewResult for the current action is returned when an exception is thrown and there does not seem to be a view named "AddUserFacility". Could you check if an exception is thrown? 

    Regards,
    Daniel
    Telerik
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  20. Stephen
    Stephen avatar
    158 posts
    Member since:
    Jan 2009

    Posted 27 Jun 2013 Link to this post

    An exception is thrown but I am not handling it properly (a separate problem).  When I debug and check the exception it tells me that "The ID field is required."  When I don't use a custom editor template it works fine.  So somehow with the custom editor template it is not seeing that the ID field is filled in....

    Here is my custom editor template again:
    @model PASSLibrary.User_Facilities
     
    @Html.HiddenFor(model => model.ID)
    @Html.HiddenFor(model => model.Laboratory_ID)
     
    <div class="editor-label">
        @Html.Label("ID")
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.ID)
        @Html.ValidationMessageFor(model => model.ID)
    </div>
     
    <div class="editor-label">
        @Html.Label("Description")
    </div>
    <div class="editor-field">
        @Html.TextBoxFor(model => model.Description, new { style = "width: 250px;" })
        @Html.ValidationMessageFor(model => model.Description)
    </div>
  21. Daniel
    Admin
    Daniel avatar
    2231 posts

    Posted 01 Jul 2013 Link to this post

    Hello Steve,

    If the value for the ID field should be entered  by the user then you should remove the hidden input. Otherwise, the ModelBinder will always populate the value from the hidden input because it is first.

    Regards,
    Daniel
    Telerik
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  22. Stephen
    Stephen avatar
    158 posts
    Member since:
    Jan 2009

    Posted 02 Jul 2013 Link to this post

    Hi,

    Ok I understand what you are saying and that makes sense to me when it is in "add" mode but what about when it is in "edit" mode.  It uses the same custom edit template so doesn't the hidden need to be there for the "edit"?

    Thanks,

    Steve
  23. Daniel
    Admin
    Daniel avatar
    2231 posts

    Posted 04 Jul 2013 Link to this post

    Hello Steve,

    If the user should enter the value only when creating a new item then you could check the Id value and render only the HiddenInput or the editor e.g.

    @if (!String.IsNullOrEmpty(Model.ID))
    {
        @Html.HiddenFor(model=> model.ID)
    }
    else
    {
        <div class="editor-label">
            @Html.Label("ID")
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.ID)
            @Html.ValidationMessageFor(model => model.ID)
        </div>
    }
    Generally speaking, the ID of the model should assigned on the server and not by the user.

    Regards,
    Daniel
    Telerik
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  24. Stephen
    Stephen avatar
    158 posts
    Member since:
    Jan 2009

    Posted 08 Jul 2013 Link to this post

    Ok that makes sense.

    In this particular case though I don't think I need to do that because I am using jquery to disable the ID field if it is an edit.

    Thanks!
  25. Stephen
    Stephen avatar
    158 posts
    Member since:
    Jan 2009

    Posted 16 Jul 2013 Link to this post

    Ok posting one more time in this thread...hopefully.

    I've got everything working now the way I want but there are two small things happening that I would like to fix.

    1.  When I add or delete an item from the nested grid, the parent grid collapses instead of remaining open.  I thought I had fixed this issue early on but it seems to be happening again now.

    2.  When I click "Delete" on the nested grid, I get the "Delete this item" pop up twice.

    Here is my view code:

    @{ Html.Kendo().Grid(Model)
        .Name("gridLaboratories")
        .Columns(columns =>
        {
            columns.Command(command => { command.Edit(); }).Width(50);
            columns.Bound(l => l.ID);
            columns.Bound(l => l.Description);
            columns.Command(command => { command.Destroy(); }).Width(50);
        })
        .DetailTemplate(l =>
        {
            Html.Kendo().TabStrip()
                .Name("tabstrip" + l.ID)
                .SelectedIndex(0)
                .Items(items =>
                {
                    items.Add().Text("Lab Admins").Content(@<text>       
     
                        @(Html.Kendo().Grid(l.Users_Roles)
                            .Name("gridLabAdmins" + l.ID)
                            .Columns(columns =>
                            {
                                columns.Bound(a => a.User.BNL_ID).Title("BNL ID");
                                columns.Bound(a => a.User.Pool.First_Name).Title("First Name");
                                columns.Bound(a => a.User.Pool.Last_Name).Title("Last Name");
                                columns.Bound(a => a.User.Account).Title("BNL Account");
                                columns.Command(command => { command.Destroy(); }).Width(50);
                            })
                            .ToolBar(toolbar => toolbar.Create())
                            .Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("SystemAdmin/LabAdmin"))
                            .Sortable()
                            .DataSource(dataSource => dataSource
                                .Server()
                                .Model(model => model.Id(a => a.ID))
                                .Read(read => read.Action("Laboratories", "SystemAdmin", new { labID = l.ID }))
                                .Create(create => create.Action("AddLabAdmin", "SystemAdmin"))
                                .Destroy(destroy => destroy.Action("DeleteLabAdmin", "SystemAdmin"))
                            )
                        )
     
                    </text>);
                })
                .Render();
        })
        .ToolBar(toolbar => toolbar.Create())
        .Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("SystemAdmin/Laboratory"))
        .Pageable()
        .Sortable()
        .DataSource(dataSource => dataSource
            .Server()
            .Model(model =>
            {
                model.Id(l => l.ID);
                model.Field(field => field.ID).DefaultValue("");
                model.Field(field => field.Description).DefaultValue("");
            })
            .Create(create => create.Action("AddLaboratory", "SystemAdmin"))
            .Read(read => read.Action("Laboratories", "SystemAdmin"))
            .Update(update => update.Action("UpdateLaboratory", "SystemAdmin"))
            .Destroy(destroy => destroy.Action("DeleteLaboratory", "SystemAdmin"))
        )
        .RowAction(row =>
        {
            if (row.DataItem.ID.ToString() == Request.QueryString["labID"])
            {
                row.DetailRow.Expanded = true;
            }
        })
        .Render();
    }
     
    <script type="text/javascript">
    $(document).ready(function () {
        var gridMode = getURLParameter("gridLaboratories-mode");
        if (gridMode == "edit") {
            $("#gridLaboratoriesPopUp").find('input[name="ID"]').attr("disabled", true);
        }
    });
     
    function getURLParameter(name) {
        return decodeURI((RegExp(name + '=' + '(.+?)(&|$)').exec(location.search) || [, null])[1]);
    }
    </script>

    And here is my controller code:

    public class SystemAdminController : Controller
    {
     
        public ActionResult Index()
        {
            return View();
        }
     
        #region Laboratories
     
        [Authorize(Roles = "System_Admin")]
        public ActionResult Laboratories()
        {
            var context = new PASSEntities();
            return View(context.Laboratories.ToList());
        }
     
        [Authorize(Roles = "System_Admin")]
        [HttpPost]
        public ActionResult AddLaboratory(Laboratory laboratory)
        {
            try
            {
                using (PASSEntities context = new PASSEntities())
                {
                    context.Laboratories.Add(laboratory);
                    context.SaveChanges();
                }
                return RedirectToAction("Laboratories");
            }
            catch
            {
                return View();
            }
        }
     
        [Authorize(Roles = "System_Admin")]
        [HttpPost]
        public ActionResult DeleteLaboratory(string id, Laboratory laboratory)
        {
            try
            {
                using (PASSEntities context = new PASSEntities())
                {
                    context.Entry(laboratory).State = System.Data.EntityState.Deleted;
                    context.SaveChanges();
                }
                return RedirectToAction("Laboratories");
            }
            catch
            {
                return View();
            }
        }
     
        [Authorize(Roles = "System_Admin")]
        [HttpPost]
        public ActionResult UpdateLaboratory(string id, Laboratory laboratory)
        {
            try
            {
                using (PASSEntities context = new PASSEntities())
                {
                    context.Entry(laboratory).State = System.Data.EntityState.Modified;
                    context.SaveChanges();
                    return RedirectToAction("Laboratories");
                }
            }
            catch
            {
                return View();
            }
        }
        #endregion
     
        #region Lab Admins
     
        public class EmployeeInfo
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public decimal UserID { get; set; }
        };
     
        public JsonResult GetEmployeeByBNLID(string bnlID)
        {
            var context = new PASSEntities();
            User employee = context.Users.SingleOrDefault(user => user.BNL_ID == bnlID);
     
            EmployeeInfo employeeInfo = new EmployeeInfo
            {
                FirstName = employee.Pool.First_Name,
                LastName = employee.Pool.Last_Name,
                UserID = employee.ID
            };
     
            return Json(employeeInfo);
        }
     
        [Authorize(Roles = "System_Admin")]
        [HttpPost]
        public ActionResult AddLabAdmin(Users_Roles user_role)
        {
            try
            {
                using (PASSEntities context = new PASSEntities())
                {
                    context.Users_Roles.Add(user_role);
                    context.SaveChanges();
                }
                return RedirectToAction("Laboratories");
            }
            catch
            {
                return View();
            }
        }
     
        [Authorize(Roles = "System_Admin")]
        [HttpPost]
        public ActionResult DeleteLabAdmin(Users_Roles user_role)
        {
            try
            {
                using (PASSEntities context = new PASSEntities())
                {
                    context.Entry(user_role).State = System.Data.EntityState.Deleted;
                    context.SaveChanges();
                }
                return RedirectToAction("Laboratories");
            }
            catch
            {
                return View();
            }
        }
        #endregion
    }









  26. Daniel
    Admin
    Daniel avatar
    2231 posts

    Posted 18 Jul 2013 Link to this post

    Hello,

    The destroy command does not use the Read action since the Grid does not need to be rendered again and so the ID should also be sent with the destroy request:

    .Destroy(destroy => destroy.Action("DeleteLabAdmin", "SystemAdmin", new { labID = l.ID }))
    public ActionResult DeleteLabAdmin(Users_Roles user_role, int labID)
    {
        try
        {
            using (PASSEntities context = new PASSEntities())
            {
                context.Entry(user_role).State = System.Data.EntityState.Deleted;
                context.SaveChanges();
            }
            return RedirectToAction("Laboratories", new {labID = labID});
        }
    The most likely reason for the problem with the delete confirmation is that the event was not stopped in the earlier versions of the widgets. Which version are you currently using? Could you check if updating to the latest release resolves the problem? Regards,
    Daniel
    Telerik
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  27. Stephen
    Stephen avatar
    158 posts
    Member since:
    Jan 2009

    Posted 18 Jul 2013 Link to this post

    Ok thanks.  That worked for keeping the nested grid open after delete.  I was having the same issue with the Add for the nested grid (and for Add, Update, and Delete on a different view) so I added the same code and that worked there as well so does that mean that the create and edit commands also do not use the Read action?  And just so I understand exactly what is happening, is the added code for the Add, Create, and Delete actions forcing the grid to expand those rows because it is just a pass-through in the controller so when I redirect back to the grid that info will be on the querystring so the row action can use it to expand the proper row.
    .RowAction(row =>
    {
        if (row.DataItem.ID.ToString() == Request.QueryString["labID"])
        {
            row.DetailRow.Expanded = true;
        }
    })

    As for the double delete confirmation, I have the latest version of the Kendo MVC controls 2013.Q2.  Note that it only happens with the nested grid and not the parent grid.  Is it somehow referencing the delete from the parent grid?
  28. Daniel
    Admin
    Daniel avatar
    2231 posts

    Posted 22 Jul 2013 Link to this post

    Hello Steve,

    The read action should be used for edit and create to render the Grid again in edit mode. After updating or creating the item however, the Update and Create actions are used so the ID should again be added to the route values.
    I reproduced the problem with the double confirmation and it seems that the event is not stopped when server editing is used. We will look into it and will fix it for one of the next internal builds.

    Regards,
    Daniel
    Telerik
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  29. Stephen
    Stephen avatar
    158 posts
    Member since:
    Jan 2009

    Posted 22 Jul 2013 Link to this post

    Great thank you!
  30. Andrew
    Andrew avatar
    1 posts
    Member since:
    Mar 2015

    Posted 01 Jul 2015 in reply to Mithun Link to this post

    Hello , i am faced with a similar problem  where my 3rd level grid seems to overwrite my second level..

     Your solution , you mentioned the dynamic naming , can you tell me how i can get his done?

     

    Thanks in advance...

Back to Top