Provider injection is not possible

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

Answer №1

StorageManager is a crucial service that acts as a bridge between the data storage and the application. It plays the role of a StorageServiceProvider during configuration phase and transforms into a StorageService during the execution phase.

When injected as a StorageServiceProvider, it represents an instance of the DataStore class. On the other hand, when injected as a StorageService, it serves as the return value of the $get method within the dashboards object.

The use of provider, factory, and service services becomes necessary when the service instance relies on other services. However, if no external dependencies are present, the constant or value services can be utilized instead.

Although the DataStore class may seem excessive as it primarily provides accessor methods for a plain object, it can be simplified as a constant service. This way, it remains accessible under the same name during both configuration and execution phases:

app.constant('StorageService', {
  home: { ... },
  ...
});

Answer №2

Incorporating routes directly within a controller is a feasible option.

Initially, we must include the $stateProvider in the controller.

...
app.config(function ($urlRouterProvider, $stateProvider) {
  app.stateProvider = $stateProvider;
  $urlRouterProvider.otherwise('/home');
});

export default app;

Subsequently, we establish states within the controller.

import app from '../app';
...
const DashboardCtrl = function ($scope, $timeout, StorageService) {
...
  forEach($scope.dashboards, function (dashboard) {
    app.stateProvider.state({
      name: dashboard.name,
      url: dashboard.url,
      component: dashboard.component
    });
  });
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exporting a variable to multiple files for use as a string property

My goal is to send a base URL to each file, which will be combined with the existing full path stored as a property in another object. However, I encounter an error message indicating an invalid URL when attempting to use the path. Here is the setup on th ...

Issue with getStaticProps in Next.js component not functioning as expected

I have a component that I imported and used on a page, but I'm encountering the error - TypeError: Cannot read property 'labels' of undefined. The issue seems to be with how I pass the data and options to ChartCard because they are underline ...

Tips for testing the setTimeout function within the ngOnInit using Jasmine

Could someone please assist me with writing a test for an ngOnInit function that includes a setTimeout() call? I am new to jasmine test cases and unsure of the correct approach. Any guidance would be greatly appreciated. app.component.ts: ngOnInit(): void ...

Creating an environment variable using the package.json script

I'm trying to set the process.env.ENV variable as either TEST or null using a script in my package.json file. The command below is not working when I run it through package.json (though it works fine when directly executed in cmd). script { "star ...

Problem with using Twitter Bootstrap in IE11 when Browser Profile Enterprise is enabled

I am facing an issue with a Bootstrap 3 web page. Some machines have IE configured to load intranet pages in Enterprise profile mode, while others have the default Desktop profile set in IE11. This configuration has caused the layout to break completely. ...

Adjust the height of the div element to match the screen height with AngularJS controller

Can someone please assist me in resolving this issue? I'm currently working on a div element that displays data (positioned on the left side of the screen). I want to add a scrollbar exclusively to this div. I managed to achieve this by using the fol ...

Having trouble with axios not transferring data to Express server in React (File upload)?

Hey there! I've encountered an issue with my React client and Express Server. When attempting to send data from the React client to the Express Server, it's not reaching its destination despite trying two different approaches. First Approach: U ...

How can you apply a class to a different element by hovering over one element?

Is there a way to darken the rest of the page when a user hovers over the menu bar on my website? I've been playing around with jQuery but can't seem to get it right. Any suggestions? I'm looking to add a class '.darken' to #conte ...

Having trouble displaying the output on my console using Node.js

Hey there, I'm new to this community and also new to the world of nodejs technology. I have encountered a problem that may seem minor to you but is quite big for me. Here's what's going on: In my code snippet, I want a user to input 3 value ...

What is the most effective way to retrieve the count of users who have logged in within the past three months by utilizing Jquery

I am seeking to retrieve the count of users who have logged in the last three months utilizing a JSON API and Jquery. This is my current progress: $.getJSON('users.json', function(data) { var numberOfUserLogged = 0; var d1 = ...

Utilizing d3.js to filter a dataset based on dropdown selection

I am working with a data set that contains country names as key attributes. When I select a country from a dropdown menu, I want to subset the dataset to display only values related to the selected country. However, my current code is only outputting [obje ...

Determining the Size and Color of Squares in a Treemap Based on Content with D3.js

I encountered an issue with a treemap visualization. I came across an example that is similar to my situation, which can be viewed here: In the demo, you can see that the size of each square in the treemap is determined by the content size. However, all s ...

Using images instead of checkboxes in AngularJS is a great way to

I need to customize all checkboxes and radio buttons using images. One way to achieve this is by adding a span tag after each input(checkbox / radio). <label for="rememberme"> <input type="checkbox" class="unique" id="rememberme"/> <spa ...

Steps for dynamically loading the content of a Bootstrap 4 Modal

I am currently in the process of developing a website that will showcase a wide range of images. The design is set up as a landing page with all content contained within the main HTML page - there is only an index.html file for now. This website will serv ...

Selenium is encountering an issue where it is unable to automatically download files, as the download confirmation

While reviewing someone else's code, I encountered an issue with automatically downloading PDF files from a web page using selenium. Despite setting the browser.helperApps.neverAsk.saveToDisk property to the PDF mime type, I am still getting the fire ...

Transferring a list of files from Callback folder

I am struggling with a function that is supposed to retrieve and list all the files in a specific folder. However, I am facing issues when trying to push out these files through an array. Something seems to be going wrong in my code as I receive an error w ...

Insert title into PDF document

I am currently working on a react application that generates PDF documents easily. The libraries I have utilized are: jspdf html2canvas Below is the code snippet that demonstrates my approach: index.js: <div className="App"> < ...

Struggling to design a button that can delete tasks from the list, but encountering issues with the filter function

Although I am able to push values, I seem to be struggling with the filtering process. Can anyone provide guidance on whether I am using the filter method incorrectly or if there is another issue at play? import { useState } from 'react'; const ...

Invoking a function containing an await statement does not pause the execution flow until the corresponding promise is fulfilled

Imagine a situation like this: function process1(): Promise<string> { return new Promise((resolve, reject) => { // do something const response = true; setTimeout(() => { if (response) { resolve("success"); ...

Working with Nested Models in Mongoose - Updating and inserting documents

In my express application, I have a basic document structure that includes a 'checked_in' flag. Here is the schema for the 'Book' model: module.exports = Book = mongoose.model('Book', new Schema({ name: String, checked_in: ...