A button is displayed on the page. When the user selects the button the child component will appear, however, the following error appears - Error: Uncaught (in promise): Error: No component factory found for ModalComponent. Did you add it to #NgModule.entryComponents?
The structure I have set up is as follows and this is in conjunction with Ionic 3 -
app (folder)
- app.module
- app.component
components (folder)
- modal-component.ts
pages (folder)
- pageOne (folder)
- pageOne.module
- pageOne.ts
I put the modal component in the pageOne.module
pageOne.module
#NgModule({
declarations: [
pageOne,
modalComponent
],
entryComponents: [
modalComponent
],
imports: [
IonicPageModule.forChild(pageOne),
],
exports: [
pageOne,
]
})
export class pageOneModule {}
pageOne.ts
#IonicPage()
#Component({
selector: 'pageOne',
templateUrl: 'pageOne.html',
})
export class pageOne {}
Are you bootstrapping your module?
put this somewhere where it will load
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { pageOneModule } from './pages/pageOne/pageOne.module';
document.addEventListener('DOMContentLoaded', () => {
platformBrowserDynamic().bootstrapModule(pageOneModule)
.catch(err => console.log(err));
});
I would also suggest using the angular cli, It does this kind of stuff for you.
Your Page module isn't setup right for lazy loading. I'm not sure exactly what's causing the exact error but when you lazy load you don't export or declare the entry components. Change your page module to:
#NgModule({
declarations: [
pageOne,
modalComponent ],
imports: [ IonicPageModule.forChild(pageOne) ]
})
export class pageOneModule {}
Now, you didn't post your modal component code so I'm not sure if it's something you made or not. If it's something like the Material2 Modals, those need to be in entryComponents. Also, your Nav stacks should use the string name of the page now, not a import to make sure you are loading the same object vs cloning it.
Related
In our Angular 8 project, we have a container component for user registration (user.registartion). Also, we have a reusable component for updating the user information (user.component). Both components has to show a 'user policy' pop-up which is also a reusable component (policy.component). The following picture shows my project structure.
But I can't show the Policy popup in both components. It showing the following error on the user registration page.
How can I access the 'Policy' Component from both the User registration and the User Information component?
You need to create a Shared Module to share components across many modules (and everything you want shared, like pipes, directives etc). There is an example in the docs how to use one:
// ...
#NgModule({
imports: [ CommonModule ],
declarations: [ ... your components etc... ],
exports: [ ... your components etc... ]
})
export class SharedModule { }
Remember to import CommonModule to the imports array in your shared module, and export your components. Then import the shared module to your other modules.
You need to import SharedModule on UserRegistrationModule... something like this:
#NgModule({
// ...
imports: [
CommonModule,
SharedModukle, // <---
],
// ...
})
export class UserRegistrationModule {}
This is driving me crazy, hopefully someone can shed some light on the problem. I am Lazy loading my Ionic components everything works fine in development, however when I go to compile AOT throws an error. I spent about 4 hours trying different ways to load this in I am lost, keep getting the same error.
From what I read and found in examples this should be correct. What am I missing here?
'tester' is not a known element: 1. If 'tester' is an Angular component, then verify that it is part of this
module. 2. To allow any element add 'NO_ERRORS_SCHEMA' to the '#NgModule.schemas' of this component. ("
<ion-list *ngIf="!id"> <ion-list-header> [ERROR -><tester></tester>
// components/tester/tester.ts
import { Component } from '#angular/core';
#Component({
selector: 'tester',
templateUrl: 'tester.html'
})
export class TesterComponent {
text: string;
constructor() {
console.log('Hello TesterComponent Component');
this.text = 'Hello World';
}
}
// components/components.module.ts
import { NgModule } from '#angular/core';
import { TesterComponent } from './tester/tester';
import {IonicModule} from "ionic-angular";
#NgModule({
declarations: [TesterComponent],
imports: [IonicModule],
exports: [TesterComponent,
]
})
export class ComponentsModule {}
// pages/faq/faq.module.ts
import { NgModule } from '#angular/core';
import { IonicPageModule } from 'ionic-angular';
import { FaqPage } from './faq';
import {ComponentsModule} from "../../components/components.module";
#NgModule({
declarations: [
FaqPage
],
imports: [
IonicPageModule.forChild(FaqPage), ComponentsModule
],
})
export class FaqPageModule {}
// pages/faq/faq.html
<tester></tester>
EDIT
Thanks to #Joel Joseph - Apparently the view needs to reside in the same directory as your parent component. I had the view .html file in a shared directory hence the problem.
templateUrl: '../shared/view/list.html'
changed to
templateUrl: 'list.html'
and it compiles fine now. Will leave this up incase anyone else has this issue.
Thanks to #Joel Joseph - Apparently the view needs to reside in the same directory as your parent component. I had the view .html file in a shared directory hence the problem.
templateUrl: '../shared/view/list.html'
changed to
templateUrl: 'list.html'
and it compiles fine now. Will leave this up incase anyone else has this issue.
I am using Ionic 3 and angular 5. I have one feature module 'Settings':
import { NgModule } from '#angular/core';
import { IonicPageModule } from 'ionic-angular';
import { SettingsPage } from './test';
#NgModule({
declarations: [
SettingsPage,
],
imports: [
IonicPageModule.forChild(SettingsPage),
],
})
export class SettingsPageModule {}
Under Settings module I want to add 5 more pages.
I checked a lot of post and cannot found out how to do that. Is it even possible ?
The Ionic3 standard way, if you use lazy loading, is: one module per page.
If you use the CLI, ionic generate page command will do the job for you and create a folder with 4 files whenever you create a new page.
If you don't want pages to live each in a separate directory, one way could be to create the new page-related files in the same directory.
But, if you want multiple pages in one module, it's not going to work, at least in my experience - e.g. if you try to place two pages in the same directory and load them from the same module, you'll get this error message:
Error: /.../src/pages/pagegroup/pageX.ts has a #IonicPage decorator, but it does not have a corresponding "NgModule" at /.../src/pages/pagegroup/pageX.module.ts
Below I'm explaining a working solution to have multiple pages, each with its own module, in a single directory.
Let's assume you start from this:
src
settings
settings.html
settings.module.ts
settings.scss
settings.ts
...and you want to add a page named "CustomSettingsPage".
Depending on how complex this page is, you must add the following 2 to 4 files, in the same directory (src/settings) - the optional ones are between square braces:
[custom-settings.html]
custom-settings.module.ts
[custom-settings.scss]
custom-settings.ts
The module and page .ts files will have a similar structure:
custom-settings.module.ts
import { NgModule } from '#angular/core';
import { IonicPageModule } from 'ionic-angular';
import { CustomSettingsPage } from './custom-settings';
#NgModule({
declarations: [
CustomSettingsPage,
],
imports: [
IonicPageModule.forChild(CustomSettingsPage),
],
exports: [
CustomSettingsPage
]
})
export class CustomSettingsPageModule {}
custom-settings.ts
import { Component } from '#angular/core';
import { IonicPage } from 'ionic-angular';
#IonicPage()
#Component({
selector: 'page-custom-settings',
template: `<your html template here>`
})
export class CustomSettingsPage {
// your page code here
};
Instead of template: you could use templateURL: 'custom-settings.html' - in that case, you should create the corresponding custom-settings.html template file in the same directory.
If you want to add the CSS rules for this page, you can create an optional custom-settings.scss file like:
.page-custom-settings {
/* your rules here */
}
or, you can add those CSS rules to the existing settings.scss file: this is really up to you.
I believe what you want is "modals"
https://ionicframework.com/docs/components/#modals
You can add individual pages under your settings.
I'm late to this question but just in case someone needs it in the future!
I'm not sure if you are referring to this but you can have several pages into one module having a folder tree like, for example:
pages
settings
childPage 1
child1.page.(html|scss|ts)
childPage 1
child1.page.(html|scss|ts)
settings.module.ts
settings.page.(html|scss|ts)
then in your Setting Routing Module you do like
import ...
const routes: Routes = [{
path: '',
redirectTo: 'pathtoRedirect', // if you need it
pathMatch: 'full'
}, {
path: '',
component: SettingsPage
}, {
path: 'child-page-1',
component: ChildPage1
}, {
path: 'child-page-2',
component: ChildPage2
}]
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class SettingsPageModule {}
Then in your App Routing Module you can do something like:
import ...
const routes: Routes = [{
...
}, {
path: 'settings',
loadChildren: () => import('./pages/settings/settings.module').then(m => m.SettingsPageModule),
}, {
...
}]
#NgModule({
...
})
export class AppRoutingModule{}
This should work. What a component needs is for it to be in ANY module. It's true "module per page strategy" is included as best practice, however, sometimes I simply don't want to have many files that actually can be deleted and managed under the same module.
From this point, you can have a different folder tree if you feel like it, or even create a deeper nested route like
/settings
/settings/children/:id
/settings/children/otherchildren/childrenpage
Now it would be up to you and your project needs!
Hope this is useful for somebody!
I've started learning to use Angular and so far it seems fairly straight forward. I opted to convert one of my existing website themes over to familiarize myself with the process but ran into a question regarding proper usage.
My understanding thus far is that each page is a component. I have my index content in app.component.html, and then each sub page is a separate component as well. I would however like to separate the header/footer HTML and include it as I have in the past with PHP.
My question is, should the header/footer be individual components or should they just be singular HTML files, included using ng-include? I realize either would work but can't figure out which is the traditional implementation with Angular developers.
I am trying the following approach but the header/footer component's don't seem to load. They work fine from app.component.html but not from index.html.
index.html
<body>
<app-header></app-header>
<app-root></app-root>
<app-footer></app-footer>
</body>
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { HeaderComponent } from './header/header.component';
import { FooterComponent } from './footer/footer.component';
import { ProductComponent } from './product/product.component';
import { ProductsComponent } from './products/products.component';
#NgModule({
declarations: [
AppComponent,
HeaderComponent,
FooterComponent,
ProductComponent,
ProductsComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
You should create Header and footer components and use it in AppComponent.
This is helpful if you want to use i18n tools like translate or if you want to change the header or footer if user is logged in.
The app Structure should be something like this.
AppComponent
|
|----> HeaderComponent
|----> Router-Outlet ---> Page content should be in the container.
|----> FooterComponent
This is how you need to have the files. You cannot have the components in index.html as the angular bootstraps for app not for other components.
https://angular.io/guide/architecture#services
I'm following the docs on angular.io to inject dependencies like services, etc. I did everything they said and when I try to run it, the console keeps telling me:
Uncaught ReferenceError: LedgerService is not defined
I am doing nothing crazy except creating a simple component with a service where both constructors have console.log commands (constructors in both the component and service). I've done everything Angular says to do in their 2 paragraphs that details this feature of Angular.
The component itself is being injected into the main app module (with the service being injected into the component) and both the component and service were created with the Angular CLI. So there isn't much I've even done at all minus trying to inject the service. So I'm not sure where it is going wrong but it is definitely not working and just shows a blank page (when it previously had basic content by default).
I created both units, tried to specify providers in both the app.module and the component.ts file and neither works and yields the same error--when Angular claims either could work. I've also specified it as a private service within the constructor of the component.ts file.
Everything I've seen relating to this is always for Angular 1 or 2. Neither of which are even remotely similar to Angular 4/5.
If you really want to see this code, fine but it's literally just framework and nothing else:
bookkeeper.component.ts:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-bookkeeper',
templateUrl: './bookkeeper.component.html',
styleUrls: ['./bookkeeper.component.css'],
providers: [LedgerServiceService]
})
export class BookkeeperComponent implements OnInit {
constructor(private service: LedgerServiceService) { }
ngOnInit() {
console.log("Ledger component works!");
}
}
app.module.ts:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { InterfaceComponent } from './interface/interface.component';
import { BookkeeperComponent } from './bookkeeper/bookkeeper.component';
#NgModule({
declarations: [
AppComponent,
InterfaceComponent,
BookkeeperComponent
],
imports: [
BrowserModule
],
providers: [
LedgerServiceService
],
bootstrap: [AppComponent]
})
export class AppModule { }
ledger-service.service.ts:
import { Injectable } from '#angular/core';
#Injectable()
export class LedgerServiceService {
constructor() {
console.log("wtf");
}
}
LedgerService is actually called LedgerServiceService because I initially created LedgerService manually and then tried to use the AngularCLI to generate a service and named it LedgerService and it created a service called LedgerServiceService. Naming is not what is wrong. I only initially called it simply LedgerService because I figured it would be confusing.
Your examples are missing the import.
Anywhere we use a custom type, we also need to import that type.
For that reason, in both the module and component you will need to add:
import { LedgerServiceService } from './your-path-here'
You can see this in the examples they give on https://angular.io/guide/dependency-injection