Grid MVVM: too much object makes the Grid work slow

7 posts, 0 answers
  1. Neeraj
    Neeraj avatar
    128 posts
    Member since:
    May 2015

    Posted 06 Feb Link to this post

    Hello,
            A sample would be hard to show because of complexity. 

    Scenario: I have a kendo-template which has Grid in MVVM . When i pass small array/dataSource it is ok but when array / dataSource size grows it slows down in operation. I have 28 array length object which is creating issue of slowness. 

    Grid data is set using below code:

    var tstDataSource = new kendo.data.DataSource({
                        data: TstData1,
                        group: [{ field: "OptionFilters.PricingPccInformation.PCCCode", dir: "asc" }]
                    });
                    tstDataSource.read();
                    tstGrid.Items.set("Tsts", tstDataSource);

    Below code is Grid template Code: 

    <script id="ImportPNRPricingFareFamilyRowTemplate" type="text/x-kendo-template">
        <tr data-bind="attr: { class: savedtst }">
            #= new Array($("\#ImportPnrPricingTSTGrid").data('kendoGrid').dataSource.group().length + 1).join('<td class="k-group-cell"></td>') #
            <td>
                #if(data.Segments!=null){#
     
                #for(var x=0; x < data.Segments.length; x++){#
                #if(data.Segments[x].FareBasis!=null){#
                <div> #=data.Segments[x].FareBasis#</div>
                #}else {#
                <div></div>
                #}#
                #}#
     
                #}#
            </td>
            <td>
                <div>
                    #if(data.ReservationSystemInternalID>0){#
                    <div>#=data.ReservationSystemInternalID#</div>
                    #}else {#
                    <div></div>
                    #}#
                </div>
            </td>
            <td>
                #if(data.OptionFilters.Customer.Name!=null){#
                <div>
                    #= data.OptionFilters.ValidatingCarrier.airline_value #
                </div>
                #}else {#
                <div></div>
                #}#
            </td>
            <td>
                #if(data.OptionFilters.Customer!=null){#
                <div id="customer_list">
                    #if(data.OptionFilters.Customer.Name!=null){#
                    #if(data.OptionFilters.Customer.ShortName!=null){#
     
                    <div class="customer-ellipsis" title="#: data.OptionFilters.Customer.Name #"> #=data.OptionFilters.Customer.ShortName# </div>
                    #}else {#
                    <div class="customer-ellipsis" title="#: data.OptionFilters.Customer.Name #"> #=data.OptionFilters.Customer.Name# </div>
                    #}#
                    #}else {#
                    <div></div>
                    #}#
                </div>
                #}else {#
                <div></div>
                #}#
            </td>
            <td>
                <div id="supplier_list">
     
                    <input data-role="dropdownlist" data-text-field="ShortName" data-template="SupplierItemTemplate" style="width:280px"
                           required="required" data-supplier-msg="Supplier is invalid" data-value-field="SupplierID"
                           data-value-primitive="false" validationMessage="Supplier is Invalid/Required" data-auto-bind="true"
                           data-bind="value: OptionFilters.SupplierInfo,source: OptionFilters.SupplierSource" />
     
                </div>
            </td>
            <td>
                #if(data.OptionFilters.PricingPccInformation!=null){#
                <div id="supplier_list">
                    #if(data.OptionFilters.PricingPccInformation.PCCCode!=null){#
     
                    <div title="#: data.OptionFilters.PricingPccInformation.PCCCode #"> #=data.OptionFilters.PricingPccInformation.PCCCode# </div>
                    #}else {#
                    <div></div>
                    #}#
                </div>
                #}else {#
                <div></div>
                #}#
            </td>
            <td>
                #if(data.Segments!=null){#
                #for(var x=0; x < data.Segments.length; x++){#
                <div> #=data.Segments[x].CabinClass#</div>
                #}#
                #}#
            </td>
            <td>
                <input data-role="dropdownlist" class="fare-template" data-option-label=" "
                       data-text-field="Name" data-template="FareItemTemplate" style="width:350px"
                       data-value-field="Id" required="required" data-auto-bind="true"
                       data-value-primitive="true" validationMessage="Fare Template is Invalid/Required"
                       data-bind="value: FareTemplateID,source: FareTypeCodeSource, events: {change : PricingTemplateOnChange,dataBound: OnDataBoundPricingTemplate}" />
            </td>
            <td>
                #if(data.Segments!=null){#
                #for(var x=0; x < data.Segments.length; x++){#
                <div><span> #=data.Segments[x].SegmentDetailsToDisplayPricing#</span></div>
                #}#
                #}#
     
            </td>
            <td>
                #if(data.Segments!=null){#
                #for(var x=0; x < data.Segments.length; x++){#
                #if(data.Segments[x].Baggage.Unit!=null){#
                <div> <span> #=data.Segments[x].Baggage.Quantity#</span> <span> #=data.Segments[x].Baggage.Unit#</span></div>
                #}#
                #}#
                #}#
     
            </td>
            <td>
                #var parentvm=data #
                #if(data.UnitQualifier=='SC'){#
                # var ptc = data.QueryPTC #
                # var paxhtml = "<div style='text-align:left;width:max-content;' class='courierfont'>" #
                    # var number= parseInt(1);#
                    #for(var x=0; x < data.PNRPassengerInfos.length; x++){#
                    #if(ptc.search("CH")>-1) { #
                    # if(parentvm.PNRPassengerInfos[x].lkpPassengerType.search("CH") > -1){ #
                    # paxhtml = paxhtml + " "+number+". " +parentvm.PNRPassengerInfos[x].PersonName +"<br\>" #
                        # number++ #
                        #}#
                        #}#
                        # if(ptc==parentvm.PNRPassengerInfos[x].lkpPassengerType){ #
                        # paxhtml = paxhtml + " "+number+". " +parentvm.PNRPassengerInfos[x].PersonName +"<br\>" #
                            # number++ #
                            #}#
     
                            #}#
                            #  paxhtml = paxhtml+ "</div>" #
                #=data.UnitQualifier# -> #=data.QueryPTC# <span style="text-align:left;" data-role="tooltip" title="#: paxhtml#"><i class="fa fa-info-circle info-icon" aria-hidden="true"></i> </span>
                #}else {#
                # var ptc = data.QueryPTC#
                # var paxhtml = "<div style='text-align:left;width:max-content;' class='courierfont'>" #
                    # var number= parseInt(1)#
     
                    #for(var x=0; x < parentvm.PNRPassengerInfos.length; x++){#
                    #if(ptc.search("CH")>-1) { #
                    # if(parentvm.PNRPassengerInfos[x].lkpPassengerType.search("CH") > -1){ #
                    # paxhtml = paxhtml + " "+number+". " +parentvm.PNRPassengerInfos[x].PersonName +"<br\>" #
                        # number++; #
                        #}#
                        #}else {#
                        # paxhtml = paxhtml + " "+number+". " +parentvm.PNRPassengerInfos[x].PersonName +"<br\>" #
                            # number=number+1; #
                            #}#
                            #}#
                            #  paxhtml = paxhtml +"</div>" #
                #=data.QueryPTC# <span style="text-align:left;" data-role="tooltip" title="#: paxhtml#"><i class="fa fa-info-circle info-icon" aria-hidden="true"></i></span>
                #}#
            </td>
            <td>
                <div data-bind="text: Quantity"></div>
            </td>
            <td>
                <div>#= data.PricingCommercialSkeleton.SupplierCommercials.SupplierHeads.CurrencyCode # #= data.PricingCommercialSkeleton.SupplierCommercials.SupplierHeads.NetFareInclTax # </div>
            </td>
            <td>
                <i class="fa fa-check hand text-primary pricing-window-buttons select" title="Select" data-bind="click: SelectFareFamily" aria-hidden="true"></i>
                <i class="fa fa-list-alt hand text-primary pricing-window-buttons minirule" title="Mini Rule" style="display:none;" data-bind="click: SelectMiniRule" aria-hidden="true"></i>
                <i class="fa fa-file-text hand text-primary pricing-window-buttons fullrule" title="Full Rule" data-bind="click: SelectFullRule" aria-hidden="true"></i>
                # if((data.lkpStatus!="D")){ #
                <i class="fa fa-trash text-danger hand pricing-window-buttons deletetst" data-bind="click: DeleteTst"></i>
                #}#
     
                <i class="fa fa-pencil-square-o hand text-primary pricing-window-buttons" style="display:none;" title="Edit" data-bind="click: EditFareFamily" aria-hidden="true"></i>
            </td>
        </tr>
    </script>
     
    <script id="TstGridTemplate" type="text/x-kendo-template">
     
        <div data-role="grid" id="ImportPnrPricingTSTGrid" style="margin-left: 0px;margin-top: 4px;" data-bind="source: Tsts, events: {dataBound: TSTGridonDataBound}"
             data-columns='[
                     { "field": "FareBasis", "title": "FareBasis"},
                     {"field": "ReservationSystemInternalID","title":"TST/TSM Ref"},
                     {"field": "ReservationSystemInternalID","title":"VC"},
                     {"field": "OptionFilters.Customer.PCCCode", "title": "Customer"},
                     {"field": "OptionFilters.SupplierInfo.DisplayName", "title": "Supplier","width":290},
                     {"field": "OptionFilters.PricingPccInformation.PCCCode", "title": "PricingPCC"},
                     {"field": "CabinClass","title":"Cabin"},
                     {"field": "OptionFilters.FareTypeCode","title":"PricingTemplate","width":360},
                     {"field": "Segments","title":"Segment" ,"width":300,"id":"grid-segment"},
                     {"field": "Baggage","title":"Baggage" },
                     {"field": "UnitQualifier","title":"PTC"},
                     {"field": "Quantity","title":"Qty"},
                     {"field": "SupplierCommercials.SupplierHeads.NetFareInclTax","title":"Total"},
                      {"title":"Action","width":145,command: [
                    { text: "Select",  title: "Action"}
     
                 ]}
                 ]' data-row-template="ImportPNRPricingFareFamilyRowTemplate" data-groupable="false" data-selectable="row"></div>
    </script>

        The 'Select' in Action, also renders a template which shows details of row (template code not shared).  please find attached file for dataSource attached to grid . 

  2. Neeraj
    Neeraj avatar
    128 posts
    Member since:
    May 2015

    Posted 06 Feb in reply to Neeraj Link to this post

    Neeraj said:

    Hello,
            A sample would be hard to show because of complexity. 

    Scenario: I have a kendo-template which has Grid in MVVM . When i pass small array/dataSource it is ok but when array / dataSource size grows it slows down in operation. I have 28 array length object which is creating issue of slowness. 

    Grid data is set using below code:

    var tstDataSource = new kendo.data.DataSource({
                        data: TstData1,
                        group: [{ field: "OptionFilters.PricingPccInformation.PCCCode", dir: "asc" }]
                    });
                    tstDataSource.read();
                    tstGrid.Items.set("Tsts", tstDataSource);

    Below code is Grid template Code: 

    <script id="ImportPNRPricingFareFamilyRowTemplate" type="text/x-kendo-template">
        <tr data-bind="attr: { class: savedtst }">
            #= new Array($("\#ImportPnrPricingTSTGrid").data('kendoGrid').dataSource.group().length + 1).join('<td class="k-group-cell"></td>') #
            <td>
                #if(data.Segments!=null){#
     
                #for(var x=0; x < data.Segments.length; x++){#
                #if(data.Segments[x].FareBasis!=null){#
                <div> #=data.Segments[x].FareBasis#</div>
                #}else {#
                <div></div>
                #}#
                #}#
     
                #}#
            </td>
            <td>
                <div>
                    #if(data.ReservationSystemInternalID>0){#
                    <div>#=data.ReservationSystemInternalID#</div>
                    #}else {#
                    <div></div>
                    #}#
                </div>
            </td>
            <td>
                #if(data.OptionFilters.Customer.Name!=null){#
                <div>
                    #= data.OptionFilters.ValidatingCarrier.airline_value #
                </div>
                #}else {#
                <div></div>
                #}#
            </td>
            <td>
                #if(data.OptionFilters.Customer!=null){#
                <div id="customer_list">
                    #if(data.OptionFilters.Customer.Name!=null){#
                    #if(data.OptionFilters.Customer.ShortName!=null){#
     
                    <div class="customer-ellipsis" title="#: data.OptionFilters.Customer.Name #"> #=data.OptionFilters.Customer.ShortName# </div>
                    #}else {#
                    <div class="customer-ellipsis" title="#: data.OptionFilters.Customer.Name #"> #=data.OptionFilters.Customer.Name# </div>
                    #}#
                    #}else {#
                    <div></div>
                    #}#
                </div>
                #}else {#
                <div></div>
                #}#
            </td>
            <td>
                <div id="supplier_list">
     
                    <input data-role="dropdownlist" data-text-field="ShortName" data-template="SupplierItemTemplate" style="width:280px"
                           required="required" data-supplier-msg="Supplier is invalid" data-value-field="SupplierID"
                           data-value-primitive="false" validationMessage="Supplier is Invalid/Required" data-auto-bind="true"
                           data-bind="value: OptionFilters.SupplierInfo,source: OptionFilters.SupplierSource" />
     
                </div>
            </td>
            <td>
                #if(data.OptionFilters.PricingPccInformation!=null){#
                <div id="supplier_list">
                    #if(data.OptionFilters.PricingPccInformation.PCCCode!=null){#
     
                    <div title="#: data.OptionFilters.PricingPccInformation.PCCCode #"> #=data.OptionFilters.PricingPccInformation.PCCCode# </div>
                    #}else {#
                    <div></div>
                    #}#
                </div>
                #}else {#
                <div></div>
                #}#
            </td>
            <td>
                #if(data.Segments!=null){#
                #for(var x=0; x < data.Segments.length; x++){#
                <div> #=data.Segments[x].CabinClass#</div>
                #}#
                #}#
            </td>
            <td>
                <input data-role="dropdownlist" class="fare-template" data-option-label=" "
                       data-text-field="Name" data-template="FareItemTemplate" style="width:350px"
                       data-value-field="Id" required="required" data-auto-bind="true"
                       data-value-primitive="true" validationMessage="Fare Template is Invalid/Required"
                       data-bind="value: FareTemplateID,source: FareTypeCodeSource, events: {change : PricingTemplateOnChange,dataBound: OnDataBoundPricingTemplate}" />
            </td>
            <td>
                #if(data.Segments!=null){#
                #for(var x=0; x < data.Segments.length; x++){#
                <div><span> #=data.Segments[x].SegmentDetailsToDisplayPricing#</span></div>
                #}#
                #}#
     
            </td>
            <td>
                #if(data.Segments!=null){#
                #for(var x=0; x < data.Segments.length; x++){#
                #if(data.Segments[x].Baggage.Unit!=null){#
                <div> <span> #=data.Segments[x].Baggage.Quantity#</span> <span> #=data.Segments[x].Baggage.Unit#</span></div>
                #}#
                #}#
                #}#
     
            </td>
            <td>
                #var parentvm=data #
                #if(data.UnitQualifier=='SC'){#
                # var ptc = data.QueryPTC #
                # var paxhtml = "<div style='text-align:left;width:max-content;' class='courierfont'>" #
                    # var number= parseInt(1);#
                    #for(var x=0; x < data.PNRPassengerInfos.length; x++){#
                    #if(ptc.search("CH")>-1) { #
                    # if(parentvm.PNRPassengerInfos[x].lkpPassengerType.search("CH") > -1){ #
                    # paxhtml = paxhtml + " "+number+". " +parentvm.PNRPassengerInfos[x].PersonName +"<br\>" #
                        # number++ #
                        #}#
                        #}#
                        # if(ptc==parentvm.PNRPassengerInfos[x].lkpPassengerType){ #
                        # paxhtml = paxhtml + " "+number+". " +parentvm.PNRPassengerInfos[x].PersonName +"<br\>" #
                            # number++ #
                            #}#
     
                            #}#
                            #  paxhtml = paxhtml+ "</div>" #
                #=data.UnitQualifier# -> #=data.QueryPTC# <span style="text-align:left;" data-role="tooltip" title="#: paxhtml#"><i class="fa fa-info-circle info-icon" aria-hidden="true"></i> </span>
                #}else {#
                # var ptc = data.QueryPTC#
                # var paxhtml = "<div style='text-align:left;width:max-content;' class='courierfont'>" #
                    # var number= parseInt(1)#
     
                    #for(var x=0; x < parentvm.PNRPassengerInfos.length; x++){#
                    #if(ptc.search("CH")>-1) { #
                    # if(parentvm.PNRPassengerInfos[x].lkpPassengerType.search("CH") > -1){ #
                    # paxhtml = paxhtml + " "+number+". " +parentvm.PNRPassengerInfos[x].PersonName +"<br\>" #
                        # number++; #
                        #}#
                        #}else {#
                        # paxhtml = paxhtml + " "+number+". " +parentvm.PNRPassengerInfos[x].PersonName +"<br\>" #
                            # number=number+1; #
                            #}#
                            #}#
                            #  paxhtml = paxhtml +"</div>" #
                #=data.QueryPTC# <span style="text-align:left;" data-role="tooltip" title="#: paxhtml#"><i class="fa fa-info-circle info-icon" aria-hidden="true"></i></span>
                #}#
            </td>
            <td>
                <div data-bind="text: Quantity"></div>
            </td>
            <td>
                <div>#= data.PricingCommercialSkeleton.SupplierCommercials.SupplierHeads.CurrencyCode # #= data.PricingCommercialSkeleton.SupplierCommercials.SupplierHeads.NetFareInclTax # </div>
            </td>
            <td>
                <i class="fa fa-check hand text-primary pricing-window-buttons select" title="Select" data-bind="click: SelectFareFamily" aria-hidden="true"></i>
                <i class="fa fa-list-alt hand text-primary pricing-window-buttons minirule" title="Mini Rule" style="display:none;" data-bind="click: SelectMiniRule" aria-hidden="true"></i>
                <i class="fa fa-file-text hand text-primary pricing-window-buttons fullrule" title="Full Rule" data-bind="click: SelectFullRule" aria-hidden="true"></i>
                # if((data.lkpStatus!="D")){ #
                <i class="fa fa-trash text-danger hand pricing-window-buttons deletetst" data-bind="click: DeleteTst"></i>
                #}#
     
                <i class="fa fa-pencil-square-o hand text-primary pricing-window-buttons" style="display:none;" title="Edit" data-bind="click: EditFareFamily" aria-hidden="true"></i>
            </td>
        </tr>
    </script>
     
    <script id="TstGridTemplate" type="text/x-kendo-template">
     
        <div data-role="grid" id="ImportPnrPricingTSTGrid" style="margin-left: 0px;margin-top: 4px;" data-bind="source: Tsts, events: {dataBound: TSTGridonDataBound}"
             data-columns='[
                     { "field": "FareBasis", "title": "FareBasis"},
                     {"field": "ReservationSystemInternalID","title":"TST/TSM Ref"},
                     {"field": "ReservationSystemInternalID","title":"VC"},
                     {"field": "OptionFilters.Customer.PCCCode", "title": "Customer"},
                     {"field": "OptionFilters.SupplierInfo.DisplayName", "title": "Supplier","width":290},
                     {"field": "OptionFilters.PricingPccInformation.PCCCode", "title": "PricingPCC"},
                     {"field": "CabinClass","title":"Cabin"},
                     {"field": "OptionFilters.FareTypeCode","title":"PricingTemplate","width":360},
                     {"field": "Segments","title":"Segment" ,"width":300,"id":"grid-segment"},
                     {"field": "Baggage","title":"Baggage" },
                     {"field": "UnitQualifier","title":"PTC"},
                     {"field": "Quantity","title":"Qty"},
                     {"field": "SupplierCommercials.SupplierHeads.NetFareInclTax","title":"Total"},
                      {"title":"Action","width":145,command: [
                    { text: "Select",  title: "Action"}
     
                 ]}
                 ]' data-row-template="ImportPNRPricingFareFamilyRowTemplate" data-groupable="false" data-selectable="row"></div>
    </script>

        The 'Select' in Action, also renders a template which shows details of row (template code not shared).  please find attached file for dataSource attached to grid . 



    forgot to share Grid dataSource Array . please find attached
  3. Neeraj
    Neeraj avatar
    128 posts
    Member since:
    May 2015

    Posted 06 Feb in reply to Neeraj Link to this post

    forgot to attach DataSource file . Please find attached 
  4. Neeraj
    Neeraj avatar
    128 posts
    Member since:
    May 2015

    Posted 06 Feb in reply to Neeraj Link to this post

    i forgot to share dataSource Array. Please Find Attached
  5. Neeraj
    Neeraj avatar
    128 posts
    Member since:
    May 2015

    Posted 06 Feb in reply to Neeraj Link to this post

    I am unable to upload file. Please check this fiddle for data Array  https://jsfiddle.net/8nfo2L4e/
  6. Neeraj
    Neeraj avatar
    128 posts
    Member since:
    May 2015

    Posted 07 Feb Link to this post

    P.S.: As in code , the gridRowTemplate has 2 dropdown. When i select value from DropDown the selection halts and it takes time to respond. I think since the dataSource is big , the change Event propogates in whole dataSource. Is that right ? any solutions?
  7. Alex Hajigeorgieva
    Admin
    Alex Hajigeorgieva avatar
    782 posts

    Posted 11 Feb Link to this post

    Hello, Neeraj,

    Thank you for the provided snippets and please accept my apology for the delay in getting back to you.

    While we try to always provide helpful responses, I would need more information to be able to piece together the entire scenario. Nonetheless, there are a couple of important points that I can address right away:

    - there are inline editors - while they may look good, it is recommended to remove them and use them only when the grid goes into edit mode:

    https://docs.telerik.com/kendo-ui/controls/data-management/grid/performance#excessive-use-of-editors-or-widgets-in-cells

    - the Kendo UI Grid works with flat data and the data in the thread is heavily nested. The suggestion is to use a ViewModel on the server to simplify the model on only include the necessary fields

    - it is unclear what takes place when the grid is dataBound, when the FareTemplateID drop-down list is data bound and also what happens in its change event

    - the tr row template seems to be missing a uid

    https://docs.telerik.com/kendo-ui/api/javascript/ui/grid/configuration/rowtemplate

    - the view model is missing

    - the grid itself is in a Kendo UI Template, it is unclear how that is used

    Finally, I have prepared a sample DOjo using just one data item, it would be great if you could extend the Dojo in such way so that all the missing points above are added as we may be able to advise on another performance hit that is not yet visible in the provided snippets:

    https://dojo.telerik.com/@bubblemaster/IyEzETEJ

    Look forward to hearing back from you.

    Kind Regards,
    Alex Hajigeorgieva
    Progress Telerik
    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Back to Top