Very confusing Ionic error - either 2 declarations or none - javascript

(I’m from Germany, so I’m sorry if my English is a little messy…)
Hello,
I am trying to create an Ionic-App, which has a register/login function based on this tutorial:
https://devdactic.com/login-ionic-2/
If I copy the code from the shown app.module.ts exactly like this, I’ll always get the error
“No component factory found for LoginPage. Did you add it to
#NgModule.entryComponents?”
when I try to execute the Code (ionic serve or ionic serve -l).
To fix this error, I added the LoginPage to the declarations and entryComponents in the app.module.ts, so my Code looks like this:
import { AuthServiceProvider } from './../providers/auth-service/auth-service';
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 { LoginPage } from '../pages/login/login';
#NgModule({
declarations: [
MyApp,
LoginPage
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
LoginPage
],
providers: [
StatusBar,
SplashScreen,
{provide: ErrorHandler, useClass: IonicErrorHandler},
AuthServiceProvider
]
})
export class AppModule {}
Now I could open the App, login and visit the “member-area” behind the login and everything seemed to work fine.
But if I try to logout, I get a new error.
“Type LoginPage is part of the declarations of 2 modules: AppModule
and LoginPageModule!”
This message makes sense, because it’s true, that I declared LoginPage twice, so I removed the login.module.ts (because I know that I need the declarations in the app.module.ts apparently).
And this is the confusing point: After I did this, I got another new error, which says
“Component LoginPage is not part of any NgModule or the module has not
been imported to your module”!
Summarized: I may declare “LoginPage” only once – if I do it twice, I’ll get an error. If I remove ONE of them, I’ll get another error, that I declared it nowhere…
And now I am really, really desperate how to solve this problem and how to escape the vicious circle! :-(
If I set the RegisterPage (instead of the LoginPage) as root after logout, this works fine. But if I try to set the RegisterPage as root in the beginning (before login), I’ll get the same issue as at the beginning…
On the internet I found only cases with either the “2 declarations”-error OR the “not part of any”-error, but never both, so I really hope, that someone can help me to solve my problem…
Thank you very much in advance!
Here are some extracts of my Code and error messages:
Screenshot of error no. 1
Screenshot of error no. 2
Screenshot of error no. 3
app.component.ts
import { Component } from '#angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { RegisterPage } from '../pages/register/register';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage:any = RegisterPage;
constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen) {
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
statusBar.styleDefault();
splashScreen.hide();
});
}
}
home.ts
import { Component } from '#angular/core';
import { NavController, IonicPage } from 'ionic-angular';
import { AuthServiceProvider } from '../../providers/auth-service/auth-service';
#IonicPage()
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
username = '';
email = '';
constructor(private navCtrl: NavController, private auth: AuthServiceProvider) {
let info = this.auth.getUserInfo();
this.username = info['username'];
this.email = info['email'];
}
public logout() {
this.auth.logout().subscribe(succ => {
this.navCtrl.setRoot('LoginPage');
// (if I replace 'LoginPage' with 'RegisterPage', it'll work)
});
}
}

Seems that you should move LoginPage out from declarations (as it is declared in module) and add LoginPageModule under imports.
import { LoginPageModule } from '../pages/login/login.module';
#NgModule({
declarations: [
MyApp
],
imports: [
LoginPageModule,
BrowserModule,
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp
],
providers: [
StatusBar,
SplashScreen,
{
provide: ErrorHandler,
useClass: IonicErrorHandler
},
AuthServiceProvider
]
})

Related

Angular ssr, page rerender issue

I am new to Angular ssr, you can see code below
Issue
If I enter to client route directly, first it shows
Rendered by server
but quickly after that it rerenders page and shows:
Rendered by browser
I think I know why this happens, but to be sure can someone provide a good explanation? also, Can I somehow avoid this behavior and force browser to render html that comes from server? should I worry about this?
client.component.ts
#Component({
selector: "client",
template: "<p>Rendered by {{ renderer }}</p>",
styleUrls: ["./dumco.component.css"]
})
export class ClientComponent implements OnInit {
renderer: string;
bla: any = [];
constructor(private http: HttpClient, #Inject(PLATFORM_ID) platformId: any) {
this.renderer = isPlatformBrowser(platformId) ? "Browser" : "Server";
}
}
app-routing.module.ts
import { NgModule } from "#angular/core";
import { RouterModule, PreloadAllModules } from "#angular/router";
import { AppComponent } from "./app.component";
import { CompfComponent } from "./compf/compf.component"
import { HomeComponent } from "./home/home.component"
export const appRoutes = [
{
path: "",
component: HomeComponent
},
{
path: "comp",
component: CompfComponent
},
{
path: "client",
loadChildren: () => import("./client/client.module").then(m => m.ClientModule),
data: { title: "Static Data - Clients" }
},
];
// preloadingStrategy: PreloadAllModules,
#NgModule({
imports: [RouterModule.forRoot(appRoutes, { onSameUrlNavigation: "reload", initialNavigation: 'enabled' })],
exports: [RouterModule]
})
export class AppRoutingModule { }
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpClientModule } from "#angular/common/http";
import { AppRoutingModule } from "./app-routing.module"
import { AppComponent } from './app.component';
import { CompfComponent } from './compf/compf.component';
import { HomeComponent } from './home/home.component';
import { TransferHttpCacheModule } from "#nguniversal/common"
#NgModule({
declarations: [
AppComponent,
CompfComponent,
HomeComponent
],
imports: [
HttpClientModule,
TransferHttpCacheModule,
BrowserModule.withServerTransition({ appId: 'serverApp' }),
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
app.server.module.ts
import { NgModule } from '#angular/core';
import { ServerModule, ServerTransferStateModule } from '#angular/platform-server';
import { AppModule } from './app.module';
import { AppComponent } from './app.component';
#NgModule({
imports: [
AppModule,
ServerModule,
ServerTransferStateModule
],
bootstrap: [AppComponent],
})
export class AppServerModule {}
This is normal behaviour for angular universal. Here is the normal flow:
You make a request to the server
Angular universal creates and renders the components (including API calls) server side to generate the HTML content. The content is sent back to the client browser. (In your example, the HTML will contain "rendered by server")
The browser renders the HTML.
Once the page is rendered and the dom document loaded, the client side angular application is boostrapped.
The client side angular app creates and render components (and makes API calls). It will render "rendered by browser" in your case.
You do not really have to worry about this. In a real situation, you'd have your components make API calls. To prevent the client side making the same calls that have already been made server side, you can use angular TransferState to serialise the API data in the HTML generated server side, so that the client side can use that data straight away instead of making API calls again.
That way, the HTML generated by the client should be the same as the one that came from the server. (Unless of course you specifically display different data server and client side, like in your example)

can't get ionic v4 CLI generated component to work

I'm currently working with the latest Ionic and I'm having a hard time trying to get a CLI generates component to work.
I start with a blank proyect and then create a new component with:
ionic generate component my-component
The command runs fine and creates the following files:
CREATE src/app/my-component/my-component.component.html (31 bytes)
CREATE src/app/my-component/my-component.component.spec.ts (664 bytes)
CREATE src/app/my-component/my-component.component.ts (293 bytes)
CREATE src/app/my-component/my-component.component.scss (0 bytes)
Then I proceed to use the new component in my main page like this:
<ion-content padding>
<my-component></my-component>
</ion-content>
The app.module.ts file is updated like this:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { RouterModule, RouteReuseStrategy, Routes } from '#angular/router';
import { IonicModule, IonicRouteStrategy } from '#ionic/angular';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { MyComponentComponent } from './my-component/my-component.component';
#NgModule({
declarations: [AppComponent, MyComponentComponent],
entryComponents: [],
imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],
providers: [
StatusBar,
SplashScreen,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
],
bootstrap: [AppComponent]
})
export class AppModule {}
When running the app in ionic lab I get the followin error:
ERROR Error: Uncaught (in promise): Error: Template parse errors:
'my-component' is not a known element
This is my system info:
ionic (Ionic CLI) : 4.2.1
Ionic Framework : #ionic/angular 4.0.0-beta.12
#angular-devkit/build-angular : 0.7.5
#angular-devkit/schematics : 0.7.5
#angular/cli : 6.1.5
#ionic/angular-toolkit : 1.0.0
Any ideas why is this happening? I worked before with Ionic 3 and never get this problem.
update:
This is my default my-component.component.ts file:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.scss']
})
export class MyComponentComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
In order to use a custom component inside another component you have to include it in exports array.
#NgModule({
....
declarations: [AppComponent, MyComponentComponent],
entryComponents: [],
exports:[MyComponentComponent]
....
})
export class AppModule {}
You can either do this way or you can make all your custom components inside another customModule and then import that module in app.component.ts page.
The name you are referring to the component is wrong. selector for your MyComponentComponent class is app-my-component, so you have to use <app-my-component></app-my-component> instead of <my-component></my-component>.

Setting up and inserting data in PouchDb on Ionic 2

Hi Guys im completely new to Ionic 2,
But i know js/ts and all that fun stuff already. Now i want to use PouchDb in my ionic app here is my home.ts file:
import { Component } from '#angular/core';
import * as PouchDB from 'pouchdb';
import cordovaSqlitePlugin from 'pouchdb-adapter-cordova-sqlite';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
}
PouchDB.plugin(cordovaSqlitePlugin);
var db = new PouchDB('test', { adapter: 'cordova-sqlite' });
function setData(data) {
var todo = {
title: data,
completed: false
};
db.post(todo, function callback(err, result) {
if (!err) {
console.log('Successfully posted a todo!');
}
});
}
function getData() {
console.log(db.allDocs);
}
Here is my first problem var db = new PouchDb....is no fuction when I put in a on startup function i get an error because my "setData" function doesnt know what "db" is. How can i fix that? And is my importing stuff right?
Next question do i have to import that stuff in my app.module.ts file too? an do i need a provider?
import { NgModule, ErrorHandler } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { AboutPage } from '../pages/about/about';
import { ContactPage } from '../pages/contact/contact';
import { HomePage } from '../pages/home/home';
import { TabsPage } from '../pages/tabs/tabs';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
#NgModule({
declarations: [
MyApp,
AboutPage,
ContactPage,
HomePage,
TabsPage
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp),
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
AboutPage,
ContactPage,
HomePage,
TabsPage
],
providers: [
StatusBar,
SplashScreen,
{provide: ErrorHandler, useClass: IonicErrorHandler}]
})
export class AppModule {}
I think thats everything for now. Thank you for your help
First, you need to install the SQLite provider.
Here is a tutorial for setting up the PouchDb In Ionic Using SQLite as the database.
https://gonehybrid.com/how-to-use-pouchdb-sqlite-for-local-storage-in-ionic-2/
If you need more help, just comment and I will improve the answer.

Angular2 Unexpected value in Service. Please add annotation

In my Angular2 app am getting the following error Error: (SystemJS) Unexpected value 'ReleasesService' declared by the module 'AppModule'. Please add a #Pipe/#Directive/#Component annotation.
My AppModule:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { routing } from './app.routes';
import { HttpModule } from '#angular/http';
import { SearchFilter } from '../app/search-filter.pipe';
import { ReleasesService } from '../app/releases/releases.service';
import { AppComponent } from './app.component';
import { HomeComponent } from '../app/home/home.component';
import { ReleasesComponent } from '../app/releases/releases.component';
import { DistroComponent } from '../app/distro/distro.component';
import { ContactComponent } from '../app/contact/contact.component';
#NgModule({
imports: [ BrowserModule, HttpModule, routing ],
declarations: [ AppComponent,
SearchFilter,
HomeComponent,
ReleasesComponent,
ReleasesService,
DistroComponent,
ContactComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
My ReleasesService:
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { IRelease } from './release';
import 'rxjs/add/operator/map';
#Injectable()
export class ReleasesService {
getReleases() {
return IRelease;
}
}
How to fix it? I reinstalled the Quickstarter (the base for my App), and having the same error when try to create the service.
declarations is only for declarable classes: Components Directives and Pipes
You can add ReleasesService to providers array
#NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent ],
providers: [ ReleasesService ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
See also
https://angular.io/guide/ngmodule-faq#what-classes-should-i-add-to-declarations
I had a similar problem, occurring while a project had angular2 as dependency and a project dependency (with the failing component) as well. Seems like angular2 metadata gets attached to the direct angular2 dependency, so the component in the project dependency wasn't declared in the angular2 of the project.
Workaround is to remove angular2 from the dependency (declaring it as devDependency there) and only use one angular2 instance.
Be sure the decorator has the caracter #.
If you don´t type # before the decorator function you will have this error message
#Component({ selector: '...', }) -> Correct
Component({ selector: '...', }) -> ERROR MESAGE: 'add a #Pipe/#Directive/#component'

Storage get() never returning value in ionic 2

Learning ionic 2, particularly using Storage.
So, I just created a blank app:
ionic start storagetest blank --v2
Following this the docs:
cordova plugin add cordova-sqlite-storage --save
npm install --save #ionic/storage
Then, my app.module.ts looks like this:
import { NgModule, ErrorHandler } from '#angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { IonicStorageModule } from '#ionic/storage';
#NgModule({
declarations: [
MyApp,
HomePage
],
imports: [
IonicModule.forRoot(MyApp),
IonicStorageModule.forRoot()
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage
],
providers: [
StatusBar,
SplashScreen,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
})
export class AppModule {}
And then went ahead to home.ts:
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { Storage } from '#ionic/storage';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(public navCtrl: NavController, storage: Storage) {
storage.ready().then(() => {
storage.set('name', 'Max');
storage.get('name').then((val) => {
console.log('Your name is', val);
})
});
}
}
There is nothing in the javascript log. It appears that get() is never returning the value. However, ready() does work, as I have put a console.log() in it.
What is wrong then?
I am running the app on Chrome, Mac OS.
storage.set is asynchronous and returns a promise.So value may not be set when get().then() is called. Try:
storage.ready().then(() => {
storage.set('name', 'Max').then(()=>
storage.get('name').then((val) => {
console.log('Your name is', val);
});
);
});
You have no error handler in then or catch() method which is probably why nothing is logged.

Categories

Resources