I'm trying to import a component into my injectable service, but it seems that I'm doing something wrong. This happens for other pages in similar situations as well. The current situation seems to happen because the LoginPage that I'm trying to import into SessionService requires SessionService, which smells of an infinite loop somewhere. Any ideas on how I should resolve it other than not including the page component in the injectable SessionService?
My current architecture is built so that I need to redirect to login page if session does not exist. Ionic NavController requires a page component for pushing onto navigation stack. Alternate ways of solving the redirection problem are welcome, but I would also like to understand why this is happening.
Uncaught Error: Can't resolve all parameters for LoginPage: (?, ContentService).
session.service.ts
#Injectable()
export class SessionService {
constructor(private content: ContentService) {}
}
login.page.ts
#Component({
templateUrl: './login.page.html'
})
export class LoginPage {
constructor(public session: SessionService,
public content: ContentService) {
}
and for those who requested it, content.service.ts
#Injectable()
export class ContentService {
constructor(private authHttp: AuthHttp) {
}
}
app.module.ts
#NgModule({
declarations: [
LoginPage
],
entryComponents: [
LoginPage
],
providers: [
SessionService,
ContentService
]
})
export class AppModule {
}
I'm using Angular 2.2.1 with Ionic 2.0.0-rc.4.
content.service.ts
#Injectable()
export class ContentService {...}
Add this also like SessionService
Related
I have just setup a hybrid AngularJS / Angular 5 application with downgradeModule. I have converted a very small component from AngularJS to Angular but it is never being created. I have put console.logs throughout the component to see if certain bits are called and others not. The file is loaded but the component never is.
I have read what feels like hundreds of tutorials but I must be missing something.
Note that I got this far in converting the component, realised it was not being created, then stopped porting the rest. Hence why driverImage is not currently on the converted component.
Here is a stackblitz with a test component that shows it not working https://angularjs-q1vrpe.stackblitz.io/
Bootstrap
import * as angular from "angular";
import { downgradeModule } from "#angular/upgrade/static";
import { platformBrowserDynamic } from "#angular/platform-browser-dynamic";
import { StaticProvider } from "#angular/core";
import { MainAngularModule } from "./app.module";
import "./index.module";
const bootstrapFn = (extraProviders: StaticProvider[]) => {
console.log("1"); <--- never output!
const platformRef = platformBrowserDynamic(extraProviders);
return platformRef.bootstrapModule(MainAngularModule);
};
const downgradedModule = downgradeModule(bootstrapFn);
angular.module('angularJsModule', ['myApp', downgradedModule]);
angular.bootstrap(document, ['angularJsModule']);
App.Module (MainAngularModule)
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { UpgradeModule } from '#angular/upgrade/static';
#NgModule({
imports: [
BrowserModule,
UpgradeModule
],
declarations: [Ng2TestComponent, DriverImageComponent],
entryComponents: [Ng2TestComponent, DriverImageComponent]
})
export class MainAngularModule {
// Empty placeholder method to satisfy the `Compiler`.
ngDoBootstrap() { }
}
index.module (Stripped most of the dependencies out for brevity)
angular
.module("myApp", [
"constants",
"ngMaterial",
"ngSanitize", ... ]);
The newly converted Component:
import { Component, Input, OnInit, OnChanges } from '#angular/core';
import { IDriver } from "../interfaces/IDriver";
console.log("here"); // --> This is hit
#Component({
selector: "driver-image",
template: `<div class="driver-image" ng-style="{'background-image' : 'url('+$ctrl.driverImage+')'}"></div>`
})
export class DriverImageComponent implements OnInit, OnChanges {
#Input() driver: IDriver;
#Input() small: boolean;
constructor() {
console.log("1"); // --- Not hit
}
ngOnInit() {
console.log("ONINITNINTT"); // --> Not hit
}
ngOnChanges() { }
}
The related modules.ts
import { downgradeComponent } from "#angular/upgrade/static";
...
.component("driverImage", downgradeComponent({ component: DriverImageComponent }))
The answer is actually really simple, it just took me forever to see it.
Contrary to what you might believe, you need to change your AngularJS component to be registered as a directive, NOT, a component.
without a Stackblitz this is pretty hard to reproduce (btw do you have any errors in the console?). I just write down some suggestions that you can try. If you tell me what worked, I'll update my answer
instead of import { platformBrowser } from "#angular/platform-browser"; use this one instead import { platformBrowserDynamic } from '#angular/platform-browser-dynamic'; (can't quite tell you the difference but platform-browser does not work in my projects)
Ok while writing this I think I found the answer. Your problem is you are not loading the component that should be downgraded in your Angular 5 application - everything you want to downgrade still needs to be properly loaded in Angular 5 itself. So try adding a entryComponents: [DriverImageComponent] to your App.Module
Edit:
Ok based on your comment it looks like your Application is not even bootstrapped. Are you sure you are using your component on the page that you are currently using? If the component is not being used, it will not be loaded and Angular won't be bootstrapped.
There are certain scenarios where you need to force this bootstrapping in the beginning.
Create an Bootstrap component
import { Component } from '#angular/core';
#Component({
selector: 'my-bootstrap',
template: '',
})
export class BootstrapComponent {}
Add it to your App.Module
declarations: [
BootstrapComponent,
],
entryComponents: [
BootstrapComponent,
],
Force it to be loaded in your main index.html by adding <my-bootstrap></my-bootstrap in the beginning of the <body>
I'm migrating an AngularJS project to Angular 5 using ngUpgrade but I'm running into a problem when trying to inject an AngularJS service in one of my new components.
I followed Angular's upgrade guide and created a serviceProvider that uses the $injector (see code below) but I keep getting this error:
core.js:1449 ERROR Error: Uncaught (in promise): Error: Trying to get the AngularJS injector before it being set.
I suspect I need to use forwardRef somewhere to fix this, but I'm unable to find out how and where (and why).
Following the example of the upgrade guide I created a serviceProvider as follows:
ajs-upgraded-providers.ts:
// The AngularJS service I want to use
import { AuthenticationService } from '../ajs/services/authentication.service';
export function authenticationServiceFactory($injector) {
return $injector.get('authentication');
}
export const authenticationServiceProvider = {
provide: AuthenticationService,
useFactory: authenticationServiceFactory,
deps: ['$injector']
};
Then I provide that to the app's NgModule:
app.module.ts:
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
UpgradeModule,
],
providers: [
authenticationServiceProvider,
],
bootstrap: [
AppComponent,
],
})
export class AppModule {
}
I bootstrap that module using ngUpgrade:
main.ts
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { UpgradeModule } from '#angular/upgrade/static';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
// Import our AngularJS module
import '../ajs/app';
platformBrowserDynamic()
.bootstrapModule(AppModule)
.then(platformRef => {
// Use the upgrade module to bootstrap the hybrid
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap(document.documentElement, ['myAngularJSApp']);
});
If I understand correctly, this should allow me to directly inject the AngularJS service into my component like so:
login.component.ts
import { Component } from '#angular/core';
import { AuthenticationService } from '../ajs/services/authentication.service';
#Component({
selector: 'my-login-page',
templateUrl: './login-page.component.html'
})
export class LoginPageComponent {
constructor(private authenticationService: AuthenticationService) {
console.log('authentication', authenticationService);
}
}
Can I do anything to simplify this even more? I tried to follow the upgrade guide as closely as possible, so why doesn't this work?
You need to add
providers: [AuthenticationService]
in Component declaration, like this:
import { Component } from '#angular/core';
import { AuthenticationService } from '../ajs/services/authentication.service';
#Component({
selector: 'my-login-page',
templateUrl: './login-page.component.html',
providers: [AuthenticationService]
})
export class LoginPageComponent {
constructor(private authenticationService: AuthenticationService) {
console.log('authentication', authenticationService);
}
}
I am in the process of upgrading angularjs app to angular 5 as outlined in this guide
I have the hybrid app bootstrapped from angular code, that went well. As a next step I created an angular5 component which depends on an angular5 service. I have downgraded the component and declared as directive in angularjs. The problem I see is the service doesn't get injected into the component. If I remove the service dependency from the component it works fine.
Here is my code and the error
Component
#Component({
selector: 'test-detail',
template: `
<h2>Windstorm details! {{test}}</h2>
<div><label>id: </label>1</div>
`
})
export class TestComponent {
private test:string;
constructor( private testService:TestService){
}
ngOnInit(){
this.test = this.testService.test();
}
}
Service:
import { Injectable } from '#angular/core';
#Injectable()
export class TestService{
test(){
return "hello";
}
}
NG5 Module
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { UpgradeModule } from '#angular/upgrade/static';
import {TestComponent} from '../ng5/directives/test.directive';
import {TestService} from '../ng5/services/test.service';
import { HttpClientModule } from '#angular/common/http';
#NgModule({
imports: [
BrowserModule,
UpgradeModule,
HttpClientModule
],
declarations:[
TestComponent
] ,
entryComponents: [
TestComponent
],
providers:[
TestService
]
})
export class AppModule {
constructor(private upgrade: UpgradeModule) {
}
ngDoBootstrap() {
this.upgrade.bootstrap(document.documentElement, ['MyApp']);
}
}
AngularJS Module:
angular.module("MyApp").directive('testDetail', downgradeComponent({ component: TestComponent }) as angular.IDirectiveFactory);
The error I get when launching the page is
uncaught Error: Can't resolve all parameters for TestComponent: (?).
at syntaxError (compiler.js:485)
at CompileMetadataResolver.webpackJsonp.529.CompileMetadataResolver._getDependenciesMetadata (compiler.js:15699)
at CompileMetadataResolver.webpackJsonp.529.CompileMetadataResolver._getTypeMetadata (compiler.js:15534)
at CompileMetadataResolver.webpackJsonp.529.CompileMetadataResolver.getNonNormalizedDirectiveMetadata (compiler.js:15019)
at CompileMetadataResolver.webpackJsonp.529.CompileMetadataResolver._getEntryComponentMetadata (compiler.js:15847)
at compiler.js:15317
at Array.map (<anonymous>)
at CompileMetadataResolver.webpackJsonp.529.CompileMetadataResolver.getNgModuleMetadata (compiler.js:15317)
at JitCompiler.webpackJsonp.529.JitCompiler._loadModules (compiler.js:34404)
at JitCompiler.webpackJsonp.529.JitCompiler._compileModuleAndComponents (compiler.js:34365)
I am answering my own question. Declaring service the following way resolved the issue
providers:[
{ provide: 'TestService', useClass: TestService }
]
i wanted to provide authonification to my ionic2 app, so i followed the official documentation and applied it to a brand new ionic2 app ionic start my_app blank
once i serve my app, this error fires :
Error: Can't resolve all parameters for Auth: (?).
at syntaxError (http://localhost:8100/build/main.js:107898:34)
at CompileMetadataResolver._getDependenciesMetadata (http://localhost:8100/build/main.js:121235:35)
at CompileMetadataResolver._getTypeMetadata (http://localhost:8100/build/main.js:121103:26)
at CompileMetadataResolver._getInjectableMetadata (http://localhost:8100/build/main.js:121089:21)
at CompileMetadataResolver.getProviderMetadata (http://localhost:8100/build/main.js:121379:40)
at http://localhost:8100/build/main.js:121308:49
at Array.forEach (<anonymous>)
at CompileMetadataResolver._getProvidersMetadata (http://localhost:8100/build/main.js:121269:19)
at CompileMetadataResolver.getNgModuleMetadata (http://localhost:8100/build/main.js:120924:50)
at JitCompiler._loadModules (http://localhost:8100/build/main.js:131988:66)
i've injected Auth with providers in app.moodule.ts as you can
import { BrowserModule } from '#angular/platform-browser';
import { ErrorHandler, NgModule } from '#angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '#ionic-native/splash-screen';
import { StatusBar } from '#ionic-native/status-bar';
import { MyApp } from './app.component';
import { Auth } from '#ionic/cloud-angular';
#NgModule({
declarations: [
MyApp,
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
],
providers: [
StatusBar,
SplashScreen,
Auth,
{provide: ErrorHandler, useClass: IonicErrorHandler }
]
})
export class AppModule {}
according to my researches, this error comes from:
Having forgot to decorate the Auth class with #Injectable() or #Inject(Auth)
i have tried doing so by injecting :
#IonicPage()
#Component({
selector: 'page-home',
templateUrl: 'home.html',
})
#Injectable()
export class HomePage {........}
OR
export class HomePage {
constructor(#Inject(Auth) public auth: Auth) {
}
.......
}
But this shows the same error though.
Having a dependency in the Auth constructor that i haven't provided in app.module.ts
as you can see, i've handled this case in my code.
A circular dependency.
which i really think is the issue here, honestly i got a clue how to check this out since i still a beginner.
Hope someone can help
When my app starts, I want the route /home to be displayed by default.
The "useAsDefault: true" property to the route definition is not implemented yet on the Angular 2 version I use.
To solve the problem I thought doing this in app.component.ts (which is what you find in many examples on the net):
export class AppComponent implements OnInit {
constructor(private _router: Router) {}
ngOnInit() {
this._router.navigate(['/home']);
}
}
But I get:
"Error:(29, 12) TS2346: Supplied parameters do not match any signature of call target."
If I add the Elvis operator, it works, I don't get any error:
export class AppComponent implements OnInit {
constructor(private _router?: Router) {}
ngOnInit() {
this._router.navigate(['/home']);
}
}
Could someone help me understand why?
My app.component.ts file:
import {Component, OnInit} from '#angular/core';
import {Router, Routes, ROUTER_DIRECTIVES } from '#angular/router';
import {NavbarComponent} from "./navbar.component";
import {UsersComponent} from "./users.components";
import {PostsComponent} from "./posts.component";
import {HomeComponent} from "./home.component";
#Component({
selector: 'my-app',
templateUrl: 'app/app.component.html',
directives: [NavbarComponent, ROUTER_DIRECTIVES]
})
#Routes([
{path: '/home', component: HomeComponent},
{path: '/users', component: UsersComponent},
{path: '/posts', component: PostsComponent}
])
export class AppComponent implements OnInit {
constructor(private _router?: Router) {}
ngOnInit() {
this._router.navigate(['/home']);
}
}
If I add the Elvis operator, it works, I don't get any error
Minor: This is not called the elvis operator. Its just syntax to denote optional parameters (reference https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#3922-parameter-list)
Could someone help me understand why
the error Supplied parameters do not match any signature of call target points you to the fact that something is calling the constructor without providing all the parameters. That code is not shown in your question but you now know why (when you mark the parameter as optional you silence that error for obvious reasons)