Understanding Angular2 Dependency Injection in modules - javascript

I have written a feature module , and below is the code
app.ticket.service.ts, this is my service which i would like to inject
'use strict';
import { Injectable } from '#angular/core'
Injectable()
export class AppTicketService {
SaveTicket(): string {
return "service saved ticket";
}
}
app.tickets.module.ts, this is my feature module
'use strict';
import { NgModule } from '#angular/core';
import { SharedModule } from '../shared/app.shared.module';
import { AppCreatTicketComponent } from './app.create-ticket.component';
//-- import services
import { AppTicketService } from './app.ticket.service';
//-- import routing
import { ticketRouting } from './app.ticket.routing';
#NgModule({
declarations:[ AppCreatTicketComponent],
imports:[ SharedModule,
ticketRouting],
exports:[],
providers:[AppTicketService]
})
export class TicketsModule { }
app.create-ticket.component.ts , this is my component ,
which belongs to feature module
'use strict';
import { Component , OnInit , Inject} from '#angular/core';
//-- import service
import { AppTicketService } from './app.ticket.service';
#Component({
templateUrl: '/tickets/create'
})
export class AppCreatTicketComponent implements OnInit{
ngOnInit(){}
constructor(public service1 :AppTicketService) {
let test = this.service1.SaveTicket();
}
}
At runtime I am getting:
"Can't resolve all parameters for AppCreatTicketComponent:" error in browser console
What needs to be modified to resolve this issue?

To fix this issue I had to modify constructor paramter in app.create-ticket.component.ts file
Original
constructor(public service1 :AppTicketService)
Modified
constructor(#Inject(AppTicketService) private service1: AppTicketService)
You can find reason for this here

Related

Nestjs cant resolve dependencies

Can't figure out what's the problem of my code. (I'm new with nestjs, I'm trying to learn it by passing some apps to it). Console log says:
Nest can't resolve dependencies of the UrlsAfipService (?). Please
make sure that the argument at index [0] is available in the ApiModule
context.
UrlsAfipService
import { Injectable } from '#nestjs/common';
import { AfipUrls } from './urls'
#Injectable()
export class UrlsAfipService {
constructor(
private readonly afipUrls: AfipUrls,
) {}
getWSAA () {
return this.afipUrls.homo().wsaa; // <- change to prod() for production
}
getService (service: string) {
return this.afipUrls.homo().service.replace('{service}', service)
}
}
AfipUrls
export class AfipUrls {
homo() {
return {
wsaa: 'https://url.com',
service: 'https://url.com'
}
}
prod() {
return {
wsaa: 'url.com',
service: 'url.com'
}
}
}
ApiModule
import { Module } from '#nestjs/common';
import { ApiController } from './api.controller';
import { UrlsAfipService } from './urls-afip.service'
import { WsaaService } from './wsaa.service'
import { DescribeService } from './describe.service';
#Module({
controllers: [ApiController],
providers: [UrlsAfipService, WsaaService, DescribeService]
})
export class ApiModule {}
AppModule
import { Module } from '#nestjs/common';
import { ApiModule } from './api/api.module';
import { AppController } from './app.controller';
import { AppService } from './app.service';
#Module({
imports: [ApiModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
You have declared AfipUrls as a dependency for UrlsAfipService but it is not provided in any module.
So you have to add AfipUrls to the providers array of your ApiModule. Then it can be injected.
providers: [UrlsAfipService, WsaaService, DescribeService, AfipUrls]
// ^^^^^^^^
Note though, that encoding environment specific values in your code base might be a code smell. Consider creating a ConfigService that encapsulates environment specific variables that are read from environment variables or .env files using dotenv. See this answer for more information.

Bootstrap multiple root component in Angular 4

We've a JQuery application where we've a requirement to implement some modules in Angular 4. So to do that we are manually bootstrapping an Angular app. But now the case is we have created multiple angular component and now they all loading when we bootstrap AppComponent which is making application slow in loading.
So I want to bootstrap multiple root component (i.e. AppComponent, App1Component) so that and will use child components accordingly based on it.
So following is my implementation which is not working.
main.ts
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { AppModule,App1Module } from './app.module';
import { enableProdMode } from '#angular/core';
platformBrowserDynamic().bootstrapModule(AppModule)
platformBrowserDynamic().bootstrapModule(App1Module)
app.module.ts
import { NgModule } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations'
import { BrowserModule } from '#angular/platform-browser';
import { AppComponent } from './app.component';
import { AppugComponent } from './appug.component';
import { AppChild1Component } from './profile/appchild1.component';
import { AppChild2Component } from './profile/appchild2.component';
import { AppChild3Component } from './profile/appchild3.component';
import { AppChild4Component } from './profile/appchild4.component';
import { UgChild1Component } from './ug/ugchild1.component';
import { UgChild2Component } from './ug/ugchild2.component';
import { UgChild3Component } from './ug/ugchild3.component';
import { UgChild4Component } from './ug/ugchild4.component';
#NgModule({
imports: [BrowserAnimationsModule, BrowserModule, FormsModule,HttpModule],
declarations: [
AppComponent,
AppChild1Component,
AppChild2Component,
AppChild3Component,
AppChild4Component,
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
#NgModule({
imports: [BrowserAnimationsModule, BrowserModule, FormsModule,HttpModule],
declarations: [
AppugComponent,
UgChild1Component,
UgChild2Component,
UgChild3Component,
UgChild4Component,
],
bootstrap: [ AppugComponent ]
})
export class App1Module { }
app.component.ts
import { Component, OnInit, ChangeDetectorRef } from '#angular/core';
#Component({
selector: 'my-app,
template:`<h1>app</h1>`,
})
export class AppComponent implements OnInit {}
appug.component.ts
import { Component, OnInit, ChangeDetectorRef } from '#angular/core';
#Component({
selector: 'my-appug,
template:`<h1>appug</h1>`,
})
export class AppugComponent implements OnInit {}
Following is the error I'm getting on console:
Unhandled Promise rejection: The selector "my-app" did not match any elements ; Zone: <root> ; Task: Promise.then ; Value: Error: The selector "my-app" did not match any elements
Tried referencing this as well but doesn't working
Any help would be appreciated.
Well I've solved myself by just doing some configuration in main.ts and tsconfig.json
Step 1: Create your module and declare root components which you want to load when you bootstrap that module.
Ex. Here I've created user.module.ts
import { NgModule } from '#angular/core';
// root component of usermodule
import { UserAppComponent } from './userapp.component';
#NgModule({
imports:[FormsModule,HttpModule],
declarations:[UserAppComponent],
providers:[],
bootstrap:[UserAppComponent]
})
export class UserModule { }
Step 2: Go to main.ts
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { AppModule } from './app.module';
import { UserModule } from './user.module';
window.platform = platformBrowserDynamic();
window.AppModule = AppModule;
window.UserModule = UserModule;
Step 3: Go to tsconfig.json and insert your newly created module and component in "files" array
"files":[
//....your other components ...//
"myapp/user.module.ts",
"myapp/userapp.component.ts",
]
Step 4: Now you are ready to bootstrap angular module wherever you want from your .js file. Like I've bootstrap like this from my .js file. Bootstrapping may differ based on your requirement but step 1 to 3 should be same.
window.platform.bootstrapModule(window.UserModule);

How do I get data to display in Angular from API in Express?

I am trying to use Nodejs/Express as my back end for producing data from a database. I currently have an api route setup so that a database query will result in its directory. So if I visit localhost:3000/api currently I will see the following:
{"status":200,"data":[{"Issuer_Id":1,"Data_Id":2,"Data_Name":"Name 1"},{"Issuer_Id":2,"Data_Id":14,"Data_Name":"Name 2"},{"Issuer_Id":2,"Data_Id":1,"Data_Name":"Name 3"}],"message":null}
This leads me to believe I have everything setup correctly on the back end.
Now how do I get this data to display on my Angular front end?
I have been through hours of tutorials and this is what I have come up with:
nav.component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from '../../data.service';
import { Series } from '../../data.service';
import {Observable} from 'rxjs/Rx';
#Component({
selector: 'app-fixed-nav',
templateUrl: './fixed-nav.component.html',
styleUrls: ['./fixed-nav.component.css']
})
export class FixedNavComponent implements OnInit{
serieses: Series[] ;
constructor(private dataService: DataService) {}
ngOnInit() {
this.dataService.getSeries().subscribe((serieses: Series[]) => this.serieses = serieses);
}
}
data.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from'#angular/common/http';
import { Http, Headers, RequestOptions, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/toPromise';
export class Series {
Issuer_Id: number;
Data_Id: number;
Data_Name: string;
}
#Injectable()
export class DataService {
constructor(private _http: Http) {}
getSeries(): Observable<Series[]> {
return this._http.get("http://localhost:3000/api/")
.map((res: Response) => res.json());
}
}
app.module.ts
import { Form1Module } from './modules/form1/form1.module';
import { FixedNavModule } from './modules/fixed-nav/fixed-nav.module';
import { HeaderModule } from './modules/header/header.module';
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
import { AppComponent } from './app.component';
import { HttpClientModule } from '#angular/common/http';
import { HttpModule } from '#angular/http';
import { DataService } from './data.service';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpModule,
HttpClientModule,
HeaderModule,
FixedNavModule,
Form1Module,
NgbModule.forRoot()
],
providers: [DataService],
bootstrap: [AppComponent]
})
export class AppModule { }
What do I need to enter in the nav.component.html to see the results?
Also note that when I refresh my angular page on lcoalhost:4200 I can see that the GET request is hitting the /apiu/ on the 3000 express server.
I am trying to help with best practices which might help get the intended result. I will amend this answer as we troubleshoot and hopefully arrive at the right answer.
So in your dataServices service I wanted to point out a couple things. Angular recommends we use the httpClient and not http and warn that http will soon be depreciated. I am fairly new to angular myself and have only ever used httpClient and have gotten great results so I recommend using that. I think this means that the promise that you are returned is changed too. Namely, you pust use a .pipe method inorder to use rxjs operators like map on the result. So this is what your dataService file would look like:
import { Injectable } from '#angular/core';
import { HttpClient } from'#angular/common/http';
import { Http, Headers, RequestOptions, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { map } from 'rxjs/operators';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/toPromise';
export class Series {
Issuer_Id: number;
Data_Id: number;
Data_Name: string;
}
#Injectable()
export class DataService {
constructor(private _http: HttpClient) {}
getSeries(): Observable<Series[]> {
return this._http.get<Series[]>("http://localhost:3000/api/")
.pipe(
map((res) => {
console.log(res);
return <Series[]> res
})
)
}
}
Note that I have imported map in a different rxjs/operators.
In actuality you dont even need to pipe or map the return since you have already declared the type of return in the get method of _http. HttpClient will cast the return into a Series[] for you so this one liner: return this._http.get("http://localhost:3000/api/") would work. I've written the code how it is however to console.log the return that your getting.
In the comments, could you tell me what is logged?
I am unable to correct your code I am providing my own setup Works for Me
In server.js
module.exports.SimpleMessage = 'Hello world';
Now in App.js
var backend = require('./server.js');
console.log(backend.SimpleMessage);
var data = backend.simpleMessage
In index html include App.js
<script src = '/App.js'></script>
alert(simpleMessage)
And you should get 'hello world'

Lazy loading in angular 1+2 hybrid apps

We have an angular 1+2 hybrid application (therefore using an angular 1 base app).
We are using upgrade adapter to downgrade our angular2 components before we bootstrap our application with the adapter. That works as expected.
However, we anticipate having large number of angular2 components (150+) so loading all the components before bootstrapping would mean a very slow initial load. I am trying to find ways to lazy load angular2 components so that we can load them as needed. Is there any way to achieve that?
Here's part of my code.
main.ts
import baseRouter from './lib/routing/baseRouter';
import router from './lib/routing/router'
import futureRoutes from './futureRoutes'
import { Adapter } from './lib/framework/upgradeAdapter';
import { Http, Headers, Response } from '#angular/http';
import { DashboardComponent } from './2x/Dashboard/dashboard.component';
var app = angular.module('myApp', [
'ui.router',
'ngStorage'
]);
app.config(router(app, futureRoutes))
.config(baseRouter)
.directive('dashboard', Adapter.downgradeNg2Component(DashboardComponent));
Adapter.bootstrap(document.body, ['myApp'], { strictDi: true });
export default app;
module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { DashboardComponent } from '../../2x/Dashboard/dashboard.component';
#NgModule({
imports: [BrowserModule],
declarations: [DashboardComponent]
})
export class AppModule { }
upgradeAdapter.ts
import { UpgradeAdapter } from '#angular/upgrade';
import { AppModule } from './module'
export const Adapter = new UpgradeAdapter(AppModule);
dashboard.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'dashboard',
templateUrl: '/dist/core/2x/Dashboard/dashboard.html',
})
export class DashboardComponent {
greeting: string;
constructor() {
this.greeting = 'Hello world';
}
}
Upon doing this, my dashboard component is available to use in the application.

Angular 2 Error: (SystemJS) Can't resolve all parameters for Member: (?).(…)

I use this seed application to narrow down an error that keeps popping up (so debugging is easier...)
I keep getting this error when trying to add a data model to my shared module (in my browser console):
Error: (SystemJS) Can't resolve all parameters for Member: (?).(…)
The Member Class in question:
import * as _ from 'lodash';
import { Injectable } from '#angular/core';
#Injectable()
export class Member {
private id: string;
[key: string]: any;
constructor(private data?: any) {
if (data) {
this.id = data.id;
_.extend(this, data.attributes);
}
}
}
My SharedModule (the Member Class isn't referenced anywhere else for now):
import { NgModule, ModuleWithProviders } from '#angular/core';
import { CommonModule } from '#angular/common';
import { FormsModule } from '#angular/forms';
import { RouterModule } from '#angular/router';
import { ToolbarComponent } from './toolbar/index';
import { NavbarComponent } from './navbar/index';
import { NameListService } from './name-list/index';
import { Member } from './models/member.model';
#NgModule({
imports: [CommonModule, RouterModule],
declarations: [ToolbarComponent, NavbarComponent],
exports: [ToolbarComponent, NavbarComponent,
CommonModule, FormsModule, RouterModule]
})
export class SharedModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: SharedModule,
providers: [NameListService, Member]
};
}
}
When I get rid of the constructor in class Member the error disappears:
import * as _ from 'lodash';
import { Injectable } from '#angular/core';
#Injectable()
export class Member {
private id: string;
[key: string]: any;
}
I am not using barrel imports as you can see since the order of the imports can cause the same error.
I am a bit stuck on how to solve this... Thanks
If the class is just to be used as a model, then don't add it to the #NgModule.providers and don't try to inject it. Just import the class into the class file where you need it, and just use it like you would any other normal class
import { Member } from './member.model';
#Component({})
class MyComponent {
member = new Member();
}
See Also:
Add Models/Entities/Objects to NgModule in Angular 2
Classes with the #Injectable() decorator get instantiated once by Angular as service providers. Angular uses reflection/type hinting to supply the instance with its dependency's.
Angular doesn't know what to give your Member class's constructor since its type is defined as any.

Categories

Resources