MVC TreeList Load on Demand

16 posts, 0 answers
  1. John
    John avatar
    12 posts
    Member since:
    Jul 2016

    Posted 30 Aug Link to this post

    Hi,

     

    Trying to create a TreeList view, but the data set is too large. exceed maxJson limit.  

    So I'd like to load on demand.  Bring back the 1st level where the parentId string is null and then as each node is cliked have it return the next set of data.  I've a similar thread where the suggestion was to look at the emploeedirectory example, but don't see how that works per say. 

    While trouble-shooting have noticed that trying to restrict the intial data request to just the top items where parentId is null does not work.  Tried to set default value for parentId as well but still does not work - "No Records to display"

    However, changing the default parentId to a value and retricting the data query to that same value does return the items where their parent is the specified default value. 

    I'm assuming there would be an inital query that brings back the top level items, but how would it show if there are sub items to select?  

    Secondly, when a node is clicked would there need to be a clicked event that calls the controller to update the TreeList?  

    Here is the controller method:

    public ActionResult GetBoms([DataSourceRequest] DataSourceRequest request)
            {
                var db = new EmsDashDev();
                var results = db.NHAItems.ToList<NHAItems>();
                var results1 = results.ToTreeDataSourceResult(request,
                    e => e.ComponentNumber,
                    e => e.NextHigherAssembly);
                return Json(results1);
            }

    And the view code

    @(Html.Kendo().TreeList<EMSCommitScheduleApp.Models.NHAItems>()
        .Name("treelist")
        .AutoBind(true)
        
        .Columns(columns =>
        {
            columns.Add().Field(e => e.ComponentNumber).Width(280);
            columns.Add().Field(e => e.ItemNumber).Width(160);
            columns.Add().Field(e => e.Description);
            columns.Add().Field(e => e.Qty).Width(80);
            columns.Add().Field(e => e.NextHigherAssembly).Width(280);
            columns.Add().Field(e => e.LevelZeroAssembly);
            columns.Add().Field(e => e.AssemblyIndicator).Title("Make");
        })
        .Filterable()
        .Sortable()
        .DataSource(dataSource => dataSource
            .Read(read => read.Action("GetBoms", "Home"))
            .ServerOperation(true)
            .Model(m => {
                m.Id(f => f.ComponentNumber);
                m.ParentId(f => f.NextHigherAssembly);
                m.Expanded(false);
                m.Field(f => f.ComponentNumber);
                m.Field(f => f.ItemNumber);
                m.Field(f => f.Description);
                m.Field(f => f.Qty);
                m.Field(f => f.NextHigherAssembly);
                m.Field(f => f.LevelZeroAssembly);
                m.Field(f => f.AssemblyIndicator);
            })
            
        )
        .Height(540)
    )

  2. Viktor Tachev
    Admin
    Viktor Tachev avatar
    1488 posts

    Posted 01 Sep Link to this post

    Hello John,

    Please check the following example that illustrates how you can implement the behavior you are looking for. The items in the sample are loaded per-level only.


    Try to use similar approach and you should be able to implement the behavior you are looking for.

    Regards,
    Viktor Tachev
    Telerik by Progress
    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
  3. UI for ASP.NET MVC is VS 2017 Ready
  4. John
    John avatar
    12 posts
    Member since:
    Jul 2016

    Posted 06 Sep Link to this post

    Thanks Viktor.

    Having issues working out this still given your example.  I have a compile error in the controller method 

    It does not like the signature : the type string must be a non-nullable value type in order to use it as parameter 'T'  ...

     

    public ActionResult GetBoms([DataSourceRequest] DataSourceRequest request, string? id)
            {
                var db = new EmsDashDev();
                            
                var results = db.NHAItems.Where(a => a.NextHigherAssembly == null);
                var results1 = results.ToTreeDataSourceResult(request,
                    e => e.ComponentNumber,
                    e => e.NextHigherAssembly,
                    e => id.HasValue ? true : false,
                    e => e.ToNHAItemModel()
                    );
                return Json(results);
            }

    Any thoughts on how to code this correctly to handle a string versus an int at least that seems to be where I'm getting stuck at the moment.  

  5. John
    John avatar
    12 posts
    Member since:
    Jul 2016

    Posted 06 Sep Link to this post

    And when I try to use a non-nullable type I get a Cannot convert lambda expression to type Mvc.ModelStateDictionary because it is not a delegate type.

    public ActionResult GetBoms([DataSourceRequest] DataSourceRequest request, string id)
            {
                var db = new EmsDashDev();
                            
                var results = db.NHAItems.Where(a => a.NextHigherAssembly == null);
                var results1 = results.ToTreeDataSourceResult(request,
                    e => e.ComponentNumber,
                    e => e.NextHigherAssembly,
                    e => id.HasValue ? true : false,
                    e => e.ToNHAItemModel()
                    );
                return Json(results1);
            }

     

  6. Viktor Tachev
    Admin
    Viktor Tachev avatar
    1488 posts

    Posted 08 Sep Link to this post

    Hello John,

    Try to retrieve the necessary fields before calling ToDataSourceResult(). The method would look similar to the following. Give it a try and see how it works for you.

    public ActionResult GetBoms([DataSourceRequest] DataSourceRequest request, string id)
    {
        var db = new EmsDashDev();
                     
        var results = db.NHAItems.Where(a => a.NextHigherAssembly == null);
        var results1 = results.Select(e=> new
                                            {
                                             ComponentNumber = e.ComponentNumber,
                                             NextHigherAssembly = e.NextHigherAssembly,
                                             HasValue = id.HasValue
                                            }).ToDataSourceResult(request);
        return Json(results1);
    }

     

    Regards,
    Viktor Tachev
    Telerik by Progress
    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
  7. John
    John avatar
    12 posts
    Member since:
    Jul 2016

    Posted 08 Sep in reply to Viktor Tachev Link to this post

    Hi Viktor - still no dice.

    Here is the modified code.

    public ActionResult GetBoms([DataSourceRequest] DataSourceRequest request, string id)
    {
    var db = new EmsDashDev();
    var results = db.NHAItems.Where(a => a.NextHigherAssembly == null);
    var results1 = results.Select(e => new
    {
    Component = e.ComponentNumber,
    NextHigherAssembly = e.NextHigherAssembly,
    HasValue = id.HasValue
    }).ToTreeDataSourceResult(request);


    return Json(results);
    }

    Error 1 Cannot convert lambda expression to type 'System.Linq.Expressions.LambdaExpression' because it is not a delegate type 

    Error 2 Cannot assign method group to anonymous type property 

    Still get the above errors??

  8. Viktor Tachev
    Admin
    Viktor Tachev avatar
    1488 posts

    Posted 12 Sep Link to this post

    Hello John,

    Would you try to call ToList() before the call to ToDataSourceResult and see how the behavior changes?

    In case the issue persists please send us a runnable sample where the behavior is replicated so we can examine it locally.

    Regards,
    Viktor Tachev
    Telerik by Progress
    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
  9. John
    John avatar
    12 posts
    Member since:
    Jul 2016

    Posted 12 Sep in reply to John Link to this post

    Hi Viktor,

     

    Ok - so adding toList didn't help, but changing id.HasValue to id.HasValue() did work in terms of compiling. However, even though results1 contains 15 entries the TreeList does not display any results.  

    Not sure how to send you a "working example" , but will if I know how.

     

     

  10. John
    John avatar
    12 posts
    Member since:
    Jul 2016

    Posted 12 Sep Link to this post

    Ok - A bit more progress. 

    The following code returns a data set as intended but only when I define the default value versus a null.

    public ActionResult GetBoms([DataSourceRequest] DataSourceRequest request, string id)
    {
    var db = new EmsDashDev();
    var results = db.NHAItems.ToList<NHAItems>();
    var results1 = results.Select(e => new
    {
    ComponentNumber = e.ComponentNumber,
    NextHigherAssembly = e.NextHigherAssembly
    }).ToTreeDataSourceResult(request);
    // This returns no records for some reason
    var results2 = results.ToTreeDataSourceResult(request,
    e => e.ComponentNumber,
    e => e.NextHigherAssembly,
    e => id.HasValue() ? true : false,
    e => e.ToNHAItemModel()
    );
    return Json(results1);
    }

    in the UI configuration is this then works  - m.ParentId(f => f.NextHigherAssembly).DefaultValue("some valid pn");

    However if I use m.ParentId(f => f.NextHigherAssembly).DefaultValue(null); which should represent the top level nodes it does not work.  Tried string.Empty, but it does not work either nor would I expect it to.

    So it seems to me the TreeList Widget does not handle the strings correctly when they are the id and parentId.

     

     

  11. Viktor Tachev
    Admin
    Viktor Tachev avatar
    1488 posts

    Posted 14 Sep Link to this post

    Hello John,

    The default value for ParentId will be null. This means that if the root items in your data source have the value set to null you do not need to explicitly set DefaultValue.


    Regards,
    Viktor Tachev
    Telerik by Progress
    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
  12. John
    John avatar
    12 posts
    Member since:
    Jul 2016

    Posted 14 Sep in reply to Viktor Tachev Link to this post

    Hi Viktor,

     

    I tried to explicitly specify default = null because not using anything did not produce any results.  The only time I have results is specifying a level down from the top as shown below commented out.

    .DataSource(dataSource => dataSource
    .Read(read => read.Action("GetBoms", "Home"))
    .ServerOperation(false)
    .Model(m => {
    m.Id(f => f.ComponentNumber);
    m.ParentId(f => f.NextHigherAssembly);// .DefaultValue("3890AS000116-01");
    m.Expanded(false);
    m.Field(f => f.ComponentNumber);
    m.Field(f => f.NextHigherAssembly);
    }) )

    I'm close to a working TreeList just need to resolve why not specifying a default does not work.

    Thanks,

    John

     

     

  13. Viktor Tachev
    Admin
    Viktor Tachev avatar
    1488 posts

    Posted 16 Sep Link to this post

    Hi John,

    It would be hard to pinpoint what is causing the behavior without replicating it locally.

    I tested the load-on-demand feature in TreeList and it is working as expected on my end. You can see the relevant parts of the code in the following snippets.

    @(Html.Kendo().TreeList<Kendo.Mvc.Examples.Models.TreeList.EmployeeDirectoryModel>()
        .Name("treelist")
        .Columns(columns =>
        {
            columns.Add().Field(f => f.FirstName).Width(250).Title("First Name");
            columns.Add().Field(e => e.LastName).Title("Last Name");
            columns.Add().Field(e => e.Position);
            columns.Add().Field(e => e.Extension).Title("Ext").Format("{0:#}");
        })
        .DataSource(dataSource => dataSource
            .Read(read => read.Action("Index", "EmployeeDirectory"))
            .Model(m => {
                m.Id(f => f.EmployeeId);
                m.ParentId(f => f.ReportsTo);
                m.Field(f => f.FirstName);
                m.Field(f => f.LastName);
                m.Field(f => f.ReportsTo);
            })
        )
    )


    public JsonResult Index([DataSourceRequest] DataSourceRequest request, int? id)
    {
        var result = GetDirectory().ToTreeDataSourceResult(request,
            e => e.EmployeeID,
            e => e.ReportsTo,
            e => id.HasValue ? e.ReportsTo == id : e.ReportsTo == null,
            e => e.ToEmployeeDirectoryModel()
        );
     
        return Json(result, JsonRequestBehavior.AllowGet);
    }


    You can also test the behavior by downloading the offline examples of the components. The code above is from the Remote Data Binding example.

    Regards,
    Viktor Tachev
    Telerik by Progress
    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. John
    John avatar
    12 posts
    Member since:
    Jul 2016

    Posted 16 Sep Link to this post

    Hi Viktor,

    Already be using the example you have referenced.  That being said this following block of code returns 15 records as expected.

    In your reference example what role does the hasChildren variable play in displaying records? 

    I was not able to use this statement: e=> id.HasValue  and had to use id != null as and it is my understanding it is equivalent. 

    var results2 = results.ToTreeDataSourceResult(request,
    e => e.ComponentNumber,
    e => e.NextHigherAssembly,
    e => id != null ? e.NextHigherAssembly == id : e.NextHigherAssembly == null,
    e => e.ToNHAItemModel()
    );

    Attached is a screen shot showing the 15 elements come back as expected but nothing ends up in the TreeList and thoughts as to why that may be?  What else can I do to figure out why the grid is empty?

    Thanks,

     

    John

  15. Viktor Tachev
    Admin
    Viktor Tachev avatar
    1488 posts

    Posted 20 Sep Link to this post

    Hello John,

    If there are 15 records returned from the data source and passed to ToTreeDataSourceResult() then the items should be displayed in the TreeList.

    However, it would be hard to determine why you are not seeing the items in the TreeList without replicating the problem locally. Please assemble a runnable sample where the issue is replicated and send it to us. Thus, we will be able to examine the behavior and look for its cause.


    Regards,
    Viktor Tachev
    Telerik by Progress
    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
  16. John
    John avatar
    12 posts
    Member since:
    Jul 2016

    Posted 20 Sep in reply to Viktor Tachev Link to this post

    Ok - Viktor have a runnable example project that does not work either.  How do I submit that runnable project to you???
  17. Viktor Tachev
    Admin
    Viktor Tachev avatar
    1488 posts

    Posted 21 Sep Link to this post

    Hello John,

    You can submit a support ticket and submit the project as attachment there. This way we can debug the code and look for the cause of the behavior you are seeing.


    Regards,
    Viktor Tachev
    Telerik by Progress
    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
Back to Top
UI for ASP.NET MVC is VS 2017 Ready