Angular Dashboard
Creating a dashboard application on Angular 1.6 has been quite the journey. I've defined two static ui.router states within the app - 'home-dashboard' and 'other-dashboard' to register the dashboard components.
Now, the challenge lies in dynamically defining ui.router states based on dashboard data. To achieve this, I tried running a loop inside app.config. However, I faced an issue where the 'StorageService' provider needed to be injected into the config, resulting in an error:
Error: [$injector:unpr] Unknown provider: StorageService
Is there a better way to inject the provider and achieve my goal seamlessly?
Another approach I experimented with was moving '$stateProvider' into the 'dashboardController', the parent controller. By attaching it to the 'app' inside app.config like so: 'app.stateProvider = $stateProvider;' and exporting the app by placing 'return default app' at the end of app.js file. Unfortunately, this led to an error stating 'return' outside of function.
The provider 'services/storage.service.js' (which is a class simulating an API) includes the necessary functions for saving and listing dashboards:
class Storage {
constructor () {
this.dashboards = {
'home': {
id: '1',
name: 'Home',
view: 'home',
url: '/home',
component: 'homeDashboard',
widgets: [{
col: 0,
row: 0,
sizeY: 1,
sizeX: 1,
name: "Widget 1"
}, {
col: 2,
row: 1,
sizeY: 1,
sizeX: 1,
name: "Widget 2"
}]
},
'other': {
id: '2',
name: 'Other',
view: 'other',
url: '/other',
component: 'otherDashboard',
widgets: [{
col: 1,
row: 1,
sizeY: 1,
sizeX: 2,
name: "Other Widget 1"
}, {
col: 1,
row: 3,
sizeY: 1,
sizeX: 1,
name: "Other Widget 2"
}]
}
};
}
saveDashboards(dashboards) {
this.dashboards = dashboards;
}
listDashboards() {
return this.dashboards;
}
$get() {
return this.dashboards;
}
}
export { Storage };
app.js
import { DashboardCtrl } from './controllers/dashboardController';
import { homeDashboard } from './dashboards/home/homeDashboard.component';
import { otherDashboard } from './dashboards/other/otherDashboard.component';
import { aWidget } from './widgets/a_widget/aWidget.component';
import { Storage } from './services/storage.service.js';
import { Object2Array } from './filters/object2Array.js';
const app = angular.module('dashboardApp', [
'ui.router',
'ui.bootstrap',
'gridster'
])
.controller('DashboardCtrl', DashboardCtrl)
.component('aWidget', aWidget)
.component('homeDashboard', homeDashboard)
.component('otherDashboard', otherDashboard)
//.factory('StorageService', () => new Storage())
.provider('StorageService', Storage)
.filter('object2Array', Object2Array);
app.config(function ($urlRouterProvider, $stateProvider, StorageService) {
const dashboards = StorageService.listDashboards();
_.forEach(dashboards, function (d) {
$stateProvider.state({
name: d.view,
url: d.url,
component: d.component
});
});
$urlRouterProvider.otherwise('/home');
});
App File Structure:
../angular-dashboard/
├── LICENSE
├── README.md
├── dist
├── package.json
├── src
│ ├── app
│ │ ├── app.js
│ │ ├── controllers
│ │ │ └── dashboardController.js
│ │ ├── dashboards
│ │ │ ├── home
│ │ │ │ ├── homeDashboard.component.js
│ │ │ │ ├── homeDashboard.controller.js
│ │ │ │ └── templates
│ │ │ │ └── homeDashboard.template.html
│ │ │ └── other
│ │ │ ├── otherDashboard.component.js
│ │ │ ├── otherDashboard.controller.js
│ │ │ └── templates
│ │ │ └── otherDashboard.template.html
│ │ ├── filters
│ │ │ └── object2Array.js
│ │ ├── services
│ │ │ └── storage.service.js
│ │ └── widgets
│ │ └── a_widget
│ │ ├── aWidget.component.js
│ │ ├── aWidget.controller.js
│ │ ├── aWidget.settings.controller.js
│ │ └── templates
│ │ ├── aWidget.settings.template.html
│ │ └── aWidget.template.html
│ ├── index.html
│ └── style
│ ├── style-common.css
│ └── style.css
└── webpack.config.js
15 directories, 22 files
UI design reference: https://i.sstatic.net/mJUN6.png