Angular 1.6.6
有一个带小部件的仪表板。我需要能够在仪表板上安装多个相同类型的小部件。
小部件对象的示例,类型 - 时钟:
"clock": {
"title": "World Clock",
"group": "Tools",
"name": "clock",
"description": "Display date and time",
"templateUrl": "widgets/clock/view.html",
"sizeX": 1,
"sizeY": 1,
"refresh": false,
"config": {
"title": "World Clock",
"timePattern": "HH:mm:ss",
"datePattern": "YYYY-MM-DD",
"location": "Europe/Amsterdam",
"showseconds": false
},
"api": {}
}
HTML模板
<div gridster="gridsterOptions">
<ul>
<li gridster-item="widget" ng-repeat="widget in $ctrl.dashboard.widgets track by $index">
<p>{{$index}}</p>
<clock-widget ng-if="widget.name==='clock'" widget=widget
on-delete="$ctrl.deleteWidget(widget)" on-update="$ctrl.updateWidget(widget)">
</clock-widget>
</li> <!-- END gridster-item, widget -->
</ul>
</div> <!-- END gridsterOptions -->
小工具clock-widget
是component。
两次添加相同的小部件后,我在浏览器控制台中看到以下错误。
Uncaught Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
如果我没有使用track by $index
我有重复错误:
Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys.
此外,我尝试为每个小部件id
属性添加一个唯一值,并按id
跟踪
<li gridster-item="widget" ng-repeat="widget in $ctrl.dashboard.widgets track by widget.id">
我再次遇到Duplicates ...
错误。
这里有什么问题?
仪表板组件控制器:
/*global angular*/
import { findIndex, forEach, cloneDeep } from 'lodash';
import widgets from '../data/widgets';
import addWidgetTemplate from '../dialogs/addWidget/addWidget.dialog.template.html';
import addWidgetController from '../dialogs/addWidget/addWidget.dialog.controller';
const injectParams = [
'$stateParams',
'$log',
'storeService',
'authService',
'eventbus',
'EVENTS',
'SweetAlert',
'$state',
'dialogs',
'$uibModal'
];
const MainDashboardCtrl = function($stateParams, $log, storeService, authService,
eventbus, EVENTS, SweetAlert, $state, $dialogs, $uibModal) {
const self = this;
self.$onInit = function () {
storeService.get($stateParams.boardID)
.then(function (_dashboard_) {
self.dashboard = _dashboard_;
if (!self.dashboard) {
self.dashboard = {};
}
if (!self.dashboard.widgets) {
self.dashboard.widgets = [];
}
const currentUser = authService.getCurrentLoginUser();
if (currentUser.permissions && currentUser.permissions.indexOf('admins') > -1) {
self.dashboardEditDisable = false;
}
if (status.uuid && status.uuid != currentUser.uuid) {
self.dashboardEditDisable = true;
} else {
self.dashboardEditDisable = false;
}
})
.catch(function (error) {
$log.error('[mainDashboardCtrl]', error);
});
};
self.deleteWidget = function (widget) {
const index = findIndex(self.dashboard.widgets, w => w.name === widget.name);
self.dashboard.widgets.splice(index, 1);
};
self.updateWidget = function (widget) {
const index = findIndex(self.dashboard.widgets, w => w.name === widget.name);
self.dashboard.widgets[index] = cloneDeep(widget);
};
// add widget
self.addWidget = function () {
$uibModal
.open({
controllerAs: '$ctrl',
controller: addWidgetController,
template: addWidgetTemplate,
resolve: {
widgets: function () {
return widgets;
}
}
})
.result.then(function (widget) {
self.dashboard.widgets.push(widget);
});
};
};
MainDashboardCtrl.$inject = injectParams;
export default MainDashboardCtrl;
仪表板模板:
<div class="search-results" access="users" access-permission-type="AtLeastOne">
<div class="header-action-area">
<h1 class="lath">
<small class="text-header-sip">
<i class="fa fa-h-square" aria-hidden="true" style="margin-right:5px;"></i>
{{$ctrl.dashboard.name}}
</small> <!-- END text-header-sip -->
<button ng-disabled="dashboardEditDisable" ng-click="$ctrl.addWidget()" class="btn btn-whiter btn-primary"
type="submit" ng-mouseover="hoverA=true" ng-mouseout="hoverA=false">
<i title="Add New Widget" class="glyphicon glyphicon-plus"></i>
</button>
</h1> <!-- END lath -->
</div> <!-- END header-action-area -->
<div gridster="gridsterOptions">
<ul>
<li gridster-item="widget" ng-repeat="widget in $ctrl.dashboard.widgets">
<clock-widget ng-if="widget.controllerAs=='clock'" widget=widget
on-delete="$ctrl.deleteWidget(widget)" on-update="$ctrl.updateWidget(widget)">
</clock-widget>
</li> <!-- END gridster-item, widget -->
</ul>
</div> <!-- END gridsterOptions -->
</div> <!-- search-results -->
小组件组件控制器:
import controller from './clock-widget.settings.controller.js';
import template from '../templates/clock-widget.settings.template.html';
import 'angular-clock/dist/angular-clock.css';
import '../style/clock-widget.css';
import timezones from '../data/timezones';
const injectParams = ['$scope', '$timeout', '$uibModal', '$log'];
const ClockWidgetCtrl = function($scope, $timeout, $uibModal, $log) {
const self = this;
const initLocation = function (widget) {
self.timezones = timezones;
self.gmtOffset = timezones[widget.config.location];
self.displayLocation = widget.config.location.split('/')[1].toUpperCase();
};
self.delete = function () {
self.onDelete({ widget: self.widget });
};
self.update = function (widget) {
initLocation(widget);
self.onUpdate({ widget });
};
self.openSettings = function () {
$uibModal
.open({
controllerAs: '$ctrl',
controller,
template,
resolve: {
widget: function () {
return self.widget;
},
timezones: function () {
return self.timezones;
}
}
})
.result.then(function (widget) {
self.update(widget);
});
};
self.$onInit = function () {
initLocation(self.widget);
};
};
ClockWidgetCtrl.$inject = injectParams;
export default ClockWidgetCtrl;
答案 0 :(得分:0)
ngRepeat
指令doesn't like相同的对象在数组中重复。
在仪表板组件控制器MainDashboardCtrl
中,a reference指向导入的widgets
对象,其中clock
对象已解析为$uibModal
模态的输入。
import widgets from '../data/widgets';
...
$uibModal
.open({
...
resolve: {
widgets: function () {
return widgets;
}
}
...
作为模态的结果,返回对clock
小部件的引用。然后将它添加到self.dashboard.widgets
数组中,该数组已包含与clock
对象相同的引用。
...
.result.then(function (widget) {
self.dashboard.widgets.push(widget);
});
...
我们需要的是添加一个添加到self.dashboard.widgets
数组的新唯一对象。
例如,clonning clock
对象:
...
.result.then(function (widget) {
self.dashboard.widgets.push(cloneDeep(widget));
});
...