Burt
Burt

Reputation: 7758

Angular ng-repeat performance

I am fairly new to AngularJS and am having performance problems on an application I have built using ng-repeat.

Below I have listed a snippet from the page with performance problems (there isn't much else on the page).

The app I am working with has to be very dynamic (multi-tenant solution that is completely configurable) and for that reason the UI is dynamic.

I am assuming the problem is that there is a nested ng-repeat. THe page takes about 8 seconds to load.

There are about 10 setting groups that contain 157 (total across all groups) settings (which are tr's).

Can anyone advise me where I am going wrong and the best way to debug performance issue with Angular please?

    <form name="settingsForm" novalidate ng-submit="vm.save()">

        <h3>Settings</h3>

        <div class="alert alert-info alert-dismissible" role="alert">
            <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <strong>Deleting settings</strong> You can only delete settings that are not being used in any quotes.
        </div>

        <div class="row">
            <div class="col-sm-12">
                <div class="form-group">
                    <label for="template">Template</label>
                    <select id="template" name="template" class="form-control" ng-options="item.id as item.name for item in vm.templates" ng-model="vm.selectedTemplateId" ng-change="vm.getSettingGroups(item.id)"></select>
                </div>
            </div>
        </div>

        <fieldset ng-repeat="settingGroup in vm.settingGroups track by settingGroup.id">
            <legend>{{::settingGroup.name}}</legend>

            <div class="table-responsive">
                <table class="table">
                    <tbody>
                        <tr>
                            <th>{{::settingGroup.settingNameColumn}}</th>
                            <th>{{::settingGroup.settingValueColumn}}</th>
                            <th ng-if="settingGroup.showSettingValue2">{{::settingGroup.settingValue2Column}}</th>
                            <th>{{::settingGroup.settingDescriptionColumn}}</th>
                            <th class="text-center" ng-if="!settingGroup.lockNameField" style="width: 40px">Hidden</th>
                            <th class="text-center" style="width: 30px">
                                <span class="btn-table" ng-click="vm.addSetting(settingGroup.id, settingGroup.settingItems)" ng-show="settingGroup.canAdd">
                                    <i class="fa fa-plus text-success"></i>
                                </span>
                            </th>
                        </tr>
                        <tr ng-repeat="item in settingGroup.settingItems track by item.id">

                            <td class="form-group" ng-if="settingGroup.lockNameField">
                                {{::item.name}}
                            </td>
                            <td class="form-group" ng-if="!settingGroup.lockNameField" show-errors>
                                <input name="{{::settingGroup.name + $index}}-name" ng-model="item.name" type="text" class="form-control input-sm" ng-change="vm.modifySetting(item)" required>
                            </td>
                            <td class="form-group" show-errors>
                                <input name="{{::settingGroup.name + $index}}-value" ng-model="item.value" type="number" class="form-control input-sm" ng-change="vm.modifySetting(item)" required>
                            </td>
                            <td class="form-group" ng-if="settingGroup.showSettingValue2" show-errors>
                                <input name="{{::settingGroup.name + $index}}-value2" ng-model="item.value2" type="number" class="form-control input-sm" ng-change="vm.modifySetting(item)" required>
                            </td>
                            <td class="form-group" ng-if="settingGroup.lockNameField">
                                {{::item.description}}
                            </td>
                            <td class="form-group" ng-if="!settingGroup.lockNameField" show-errors>
                                <input name="{{::settingGroup.name + $index}}-description" ng-model="item.description" type="text" class="form-control input-sm" ng-change="vm.modifySetting(item)">
                            </td>
                            <td class="form-group text-center" ng-if="!settingGroup.lockNameField">
                                <input name="{{::settingGroup.name + $index}}-hidden" ng-model="item.hidden" ng-checked="item.hidden" type="checkbox" class="" ng-change="vm.modifySetting(item)">
                            </td>
                            <td class="text-center">
                                <span class="btn-table" ng-really-click="vm.deleteSetting(settingGroup.settingItems, $index, item)" ng-really-message="Are you sure you want to delete this setting?" ng-show="settingGroup.canDelete">
                                    <i class="fa fa-remove text-danger"></i>
                                </span>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </fieldset>
        <div class="">
            <hr />
            <button type="submit" class="btn btn-primary">Save</button>
        </div>

Upvotes: 0

Views: 1697

Answers (1)

Peter Ashwell
Peter Ashwell

Reputation: 4302

My suspicions about the performance problems:

  • That ng-change function call (vm.modifySetting) is perhaps getting called on the first render. Can you check if it is being called or not using console log or a performance tool?
  • ng-if might save on DOM elements, but it can actually lock up the DOM while it's removing / adding stuff. Although memory wise it might be better, try changing them all to ng-show and see if there's a performance improvement. Consider rewriting the elements and their listeners to not need the ng-if

Maybe look at using scalyr-ng-repeat (sly-repeat) as an option if it's not some basic mistake like above:

https://github.com/scalyr/angular

Upvotes: 2

Related Questions