Load Treelist on Treeview Expand event

10 posts, 2 answers
  1. Harpreet
    Harpreet avatar
    9 posts
    Member since:
    Jun 2020

    Posted 04 Jul 2020 Link to this post

    Hi All,

    I am having a requirement to load a treelist when i click on any of the node in treeview (i.e. to bind treelist on treeview expand event).

    I tried various method but nothing worked for me (even i try to bind dummy data)

    My code is as below

    <div class="control-container">
        @(Html.Kendo().TreeView()
                        .Name("treeview-kendo")
                        .TemplateId("treeview")
                        .DataSource(dataSource => dataSource
                            .Model(m => m
                            .Id("parentId")
                            .HasChildren("HasChildren"))
                            .Read(read => read
                            .Action("BindingTreeView", "BrowseProgram")))
                        .DataTextField("ShortName")
                        .Deferred()
                        .Events(events => events.Expand(
                            @<text>
       function (e) {
        var data = this.dataItem(e.node);
        if (data.id != null) {
            $.ajax({
                url: "/BrowseProgram/GetContractData",
                type: "POST",
                dataType: "json",
                data: {
                    'levelId': data.id
                },
                success: function (response) {
                    if (response != null) {
                        var dataSourcer = new kendo.data.TreeListDataSource({
                            data: response
                        });
                        $("#treelist").kendoTreeList({
                            dataSource: dataSourcer
                        });
                    }
                    else {
                        alert("Something went wrong");
                    }
                },
                error: function () {
                    alert("Some error occurred!!");
                }
            });
        }
    }


                            </text>
                    ))
                  )
    </div>

     

    Controller Code

    public JsonResult GetContractData(int? levelId, [DataSourceRequest] DataSourceRequest request)
           {
               if (levelId != null)
               {
                   IEnumerable<ContractListViewModel> objContractListViewModel = null;
                   long contactId = 331489;
                   string userType = "Secured";
                   objContractListViewModel = ApiHelper.GetRequest<IEnumerable<ContractListViewModel>>(string.Format(Constants.ApiUrls.TreeViewGetLevelContractsWithCacheLevelContractInfo, levelId, contactId, userType));
                   var result = objContractListViewModel.AsQueryable().ToTreeDataSourceResult(request, f => f.ContractId, f => f.ParentContractId, f => f); 
                   return Json(result, JsonRequestBehavior.AllowGet);
               }
               else
                   return null;
           }
           public JsonResult BindingTreeView(int? parentId)
           {
               IEnumerable<TreeViewModel> objTreeView = null;
               long contactId = 331489;
               string userType = "Secured";
               if (parentId != null)
               {
                   objTreeView = ApiHelper.GetRequest<IEnumerable<TreeViewModel>>(string.Format(Constants.ApiUrls.TreeViewGetChildLevelsFiltered, parentId, contactId, userType));
               }
               else
               {
                   objTreeView = ApiHelper.GetRequest<IEnumerable<TreeViewModel>>(string.Format(Constants.ApiUrls.GetTreeViewRootLevelsAndContracts, contactId, userType));
               }
               var result = objTreeView.Select(p => new
               {
                   parentId = p.LevelId,
                   p.ShortName,
                   p.HasChildren,
                   p.WrapUpIndicator
               });
     
               return Json(result, JsonRequestBehavior.AllowGet);
           }

    Kendo Treelist

         @(Html.Kendo().TreeList<Aon.Ars.Retail.AonWrap.Web.Models.ContractListViewModel>
    ()
    .Name("treelist")
    .Columns(columns =>
    {
        columns.Add().Field(e => e.ContractNumber).Title(@AonWrapStringResources.Generic_Contract_Number);
        columns.Add().Field(e => e.ContractorName).Title(@AonWrapStringResources.Generic_Contractor);
        columns.Add().Field(e => e.ContractType).Title(@AonWrapStringResources.BrowseProgram_TypeStatus).TemplateId(Constants.ContractTypeTemplate).Width(100);
        columns.Add().Field(e => e.VerifiedInsuranceCostStatus).Title(@AonWrapStringResources.BrowseProgram_VerifiedInsCost).TemplateId(Constants.VerifiedTemplate).Width(100);
        columns.Add().Field(e => e.EnrollmentStatus).Title(@AonWrapStringResources.Generic_Label_Enroll).TemplateId(Constants.EnrollmentTemplate).Width(90);
        columns.Add().Field(e => e.PayrollStatus).Title(@AonWrapStringResources.Generic_Label_Payroll).TemplateId(Constants.PayrollTemplate).Width(90);
        columns.Add().Field(e => e.COIStatus).Title(@AonWrapStringResources.BrowseProgram_ReqCOIs).TemplateId(Constants.COIStatusTemplate).Width(90);
        columns.Add().Field(e => e.WorkCompleteStatus).Title(@AonWrapStringResources.Generic_Label_Work_Complete).TemplateId(Constants.WorkTemplate).Width(105);
    })
    .Sortable()
     
    .Height(540)
    .Deferred()
    )
  2. Answer
    Viktor Tachev
    Admin
    Viktor Tachev avatar
    2497 posts

    Posted 07 Jul 2020 Link to this post

    Hello Harpreet,

     

    Thank you for describing the requirements and sharing your implementation. As I understand the required behavior you would like the TreeList to show data that is relevant to the expanded TreeView node. Please correct me if I am mistaken.

    In order to implement the behavior I would suggest using the TreeView expand event and in the handler call the TreeList dataSource.read() method

    For the TreeList configure a Read Action for the DataSource like in the binding to remote data example. The Read will call the GetContractData method. In order to pass the relevant Id from the TreeView use the Data option of the Read action. Sending additional data is illustrated in the following article.

    https://docs.telerik.com/aspnet-mvc/html-helpers/data-management/grid/faq#how-can-i-send-values-to-my-action-method-when-binding-the-grid

     

    The article is referring to the Grid component, however, the approach is applicable for the TreeList as well.

     

    Regards,
    Viktor Tachev
    Progress Telerik

    Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
    Our thoughts here at Progress are with those affected by the outbreak.
  3. Harpreet
    Harpreet avatar
    9 posts
    Member since:
    Jun 2020

    Posted 07 Jul 2020 in reply to Viktor Tachev Link to this post

    Thanks Victor it worked for me :)
  4. Harpreet
    Harpreet avatar
    9 posts
    Member since:
    Jun 2020

    Posted 07 Jul 2020 Link to this post

    Hi Viktor,

    One more thing regarding the Treelist control.I have the data with the haschildren field same as that of Treeview control but in treelist I am not able to find haschildren property as it has only parentid property.

    So in that case i need to get all the data in one go and that will impact the performance.

    So is there any way to do the same thing as I did in treeview like haschildren and load the children data on expand event.

     

    Thanks

    Harpreet S Garcha

  5. Answer
    Viktor Tachev
    Admin
    Viktor Tachev avatar
    2497 posts

    Posted 09 Jul 2020 Link to this post

    Hello Harpreet,

     

    In order to load the TreeList items on demand you can include a hasChildren boolean property in the Model and return it with the data. The approach is illustrated in the following example :

    https://demos.telerik.com/aspnet-mvc/treelist/remote-data-binding

     

    You can see the definition of the Model below. Note that the hasChildren property is using camel case.

    public class EmployeeDirectoryRemoteModel
    {
    	[ScaffoldColumn(false)]
    	public int EmployeeId { get; set; }
    
    	[Required]
    	[DisplayName("First name")]
    	public string FirstName { get; set; }
    
    	[Required]
    	[DisplayName("Last name")]
    	public string LastName { get; set; }
    
    	[ScaffoldColumn(false)]
    	public int? ReportsTo { get; set; }
    
    	public string Address { get; set; }
    
    	public string City { get; set; }
    
    	public string Country { get; set; }
    
    	public string Phone { get; set; }
    
    	[Required]
    	[Range(0, 9999)]         
    	[DataType("Integer")]
    	public int? Extension { get; set; }
    
    	[ScaffoldColumn(false)]
    	public bool hasChildren { get; set; }
    	public string Position { get; set; }
    
    	private DateTime? birthDate;
    	[DataType(DataType.Date)]
    	[DisplayName("Birthday")]
    	public DateTime? BirthDate
    	{
    		get
    		{
    			return birthDate;
    		}
    		set
    		{
    			if (value.HasValue)
    			{
    				birthDate = value.Value;
    			}
    			else
    			{
    				birthDate = null;
    			}
    		}
    	}
    
    
    	private DateTime? hireDate;
    	[DataType(DataType.Date)]
    	[DisplayName("Hire Date")]
    	public DateTime? HireDate
    	{
    		get
    		{
    			return hireDate;
    		}
    		set
    		{
    			if (value.HasValue)
    			{
    				hireDate = value.Value;
    			}
    			else
    			{
    				hireDate = null;
    			}
    		}
    	}
    
    	public EmployeeDirectory ToEntity()
    	{
    		return new EmployeeDirectory
    		{
    			EmployeeID = EmployeeId,
    			FirstName = FirstName,
    			LastName = LastName,
    			ReportsTo = ReportsTo,
    			Address = Address,
    			City = City,
    			Country = Country,
    			Phone = Phone,
    			Extension = Extension,
    			Position = Position,
    			HireDate = HireDate,
    			BirthDate = BirthDate
    		};
    	}
    }

     

    Regards,
    Viktor Tachev
    Progress Telerik

    Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
    Our thoughts here at Progress are with those affected by the outbreak.
  6. Harpreet
    Harpreet avatar
    9 posts
    Member since:
    Jun 2020

    Posted 09 Jul 2020 in reply to Viktor Tachev Link to this post

    Thank You So much Viktor for the help :)
  7. Harpreet
    Harpreet avatar
    9 posts
    Member since:
    Jun 2020

    Posted 17 Aug 2020 Link to this post

    Hi Viktor,

    Is there any way I can capture the sort event as well as the column on which the sorting is applying and in which direction (ascending or descending) in treelist.

  8. Viktor Tachev
    Admin
    Viktor Tachev avatar
    2497 posts

    Posted 18 Aug 2020 Link to this post

    Hello Harpreet,

     

    I am afraid that currently there is no built-in sort event for the TreeList widget. Nevertheless, you can check what sorting is applied to the widget by utilizing the requestEnd event of the DataSource. The dojo below outlines the approach:

    https://dojo.telerik.com/IJELuyib

     

    That said, if you would like to have a built-in sort event in the TreeList I suggest submitting a feature request in our feedback portal. We monitor it and prioritize items based on the customer demand and the potential impact a feature would have on a widget.

    https://feedback.telerik.com/kendo-jquery-ui

     

    Regards,
    Viktor Tachev
    Progress Telerik

  9. Harpreet
    Harpreet avatar
    9 posts
    Member since:
    Jun 2020

    Posted 14 Oct 2020 in reply to Viktor Tachev Link to this post

    Hi Viktor,

     

    I Implemented the above code and its working fine but I am facing one problem as I have to remove the current sort order before refreshing the datasource, so for that I write the below code and because the datasource.sort my controller function called twice.

     treelist.dataSource.sort({});
    treelist.dataSource.read({ levelId: data.id });

     

    So is there any other way to remove current sorting?

     

    Thanks

  10. Viktor Tachev
    Admin
    Viktor Tachev avatar
    2497 posts

    Posted 15 Oct 2020 Link to this post

    Hello,

     

    An alternative approach you can use to intercept the sort action is to subscribe to the click event of the header cells. In the event handler you can access the data-field attribute of the th element  to check what was the sorted field and data-dir attribute to detect the sort order.

    The updated dojo below illustrates the approach:

    https://dojo.telerik.com/IJELuyib/10

     

    Regards,
    Viktor Tachev
    Progress Telerik

    Five days of Blazor, Angular, React, and Xamarin experts live-coding on twitch.tv/CodeItLive, special prizes, and more, for FREE?! Register now for DevReach 2.0(20).

Back to Top