IvanSt IvanSt - 2 months ago 33
Javascript Question

AngularJS and Angular Material performance issues

I am working on a angularjs application with 7 angular material tabs. I have alot of drop down lists loading from the server(just once, at page load). The problem is i have alot of animation lag when i try to switch tabs or open a md-select element (according to chrome developer tools, between 10-30 fps at best).

I think the main issue is the large ammount of

md-option
elements generated by the
ng-repeat
in
md-selects
i have all over the app. A quick
document.getElementByTagName("md-option")
in the console reveals around 1000 DOM elements generated just for that.

How can i improve the ng-repeat speed in md-selects? Is there a way to replace the ng-repeat with md-virtual-repeat in these drop down lists?

All the constant text on the page is also loaded from a language file and i've read i can use
{{ ::variableName }}
in order to prevent angular from watching that model.

Also, each tab loads its html using
ng-include="path/to/htmlFile"
. Is there a better, faster way to do that?

<md-tab ng-click="nextTab($event)" label="{{lang.tabPD}}" md-on-select="vm.tabName='tabPD'" md-no-pagination="true">
<div ng-include="'app/modules/partials/tabPD.html'" ng-controller="PDCtrl"></div>
</md-tab>
<md-tab>
...another div with ng-include
</md-tab>
etc


Any tip you guys can give me would be deeply apreciated.

Answer

You have several solutions that all of them might dramatically improve you performance.

  • Instead ng-repeat try to use md-virtual-repeat
  • Each Tab you can put under separate ui-view so root tab container state will be abstract:true and tabs - the children. It should reduce DOM size a.e. only one tab is rendered

  • I agree that md-select eats a lot of watchers so what I did: created Item component in React**. Works fast


This is route example of tabs from my code:

.state('sidemenu.activity-drill', {
                    url: '/activity-drill/:id',
                    abstract:true,
                    views: {
                        'content': {
                            templateUrl: 'views/activities/activity-details.html',
                            controller: 'ActivityDetailsCtrl'
                        }
                    }
                })
                .state('sidemenu.activity-drill.chat',       { url: '/chat',       templateUrl: 'views/activities/activity-tab-chat.html'})
                .state('sidemenu.activity-drill.notes',      { url: '/notes',      templateUrl: 'views/activities/activity-tab-action-big-notes.html'})
                .state('sidemenu.activity-drill.ais',        { url: '/ais',        templateUrl: 'views/activities/activity-tab-action-items.html'})
                .state('sidemenu.activity-drill.minutes',    { url: '/minutes',    templateUrl: 'views/activities/activity-tab-minutes.html'})
                .state('sidemenu.activity-drill.files',      { url: '/files',      templateUrl: 'views/activities/activity-tab-media.html'})
                .state('sidemenu.activity-drill.flags',      { url: '/flags',      templateUrl: 'views/activities/activity-tab-flags.html'})
                .state('sidemenu.activity-drill.people',     { url: '/people',     templateUrl: 'views/activities/activity-tab-people.html'})
                .state('sidemenu.activity-drill.objectives', { url: '/objectives', templateUrl: 'views/activities/activity-tab-objectives.html' })
                .state('sidemenu.activity-drill.meetings',   { url: '/meetings',   templateUrl: 'views/activities/activity-tab-meetings.html' })
                .state('sidemenu.activity-drill.angular2',   { url: '/angular2',   templateUrl: 'views/activities/activity-tab-angular2.html'})

Tabs structure:

<md-tab  ng-repeat="tab in activity_details_tab_position" ui-sref="{{tab.route}}">
                <md-tab-label >
                    <span translate="{{tab.name}}"></span>                         
                </md-tab-label>
            </md-tab>
        </md-tabs>

        <div ui-view></div>

Virtual repeat example:

        <div>
            <p>{{(meeting.timestamp_start * 1000)| date:'EEE dd MMM'}}</p>
            <p>{{((meeting.timestamp_start * 1000) | date : 'HH:mm')}}</p>
        </div>

        <div>
            <div layout="row">
                <span >{{meeting.meeting_name}}</span>
            </div>
        </div>
    </div>
</md-virtual-repeat-container>

Hope it will help,

Comments