i have this psuedo code structure in my angular project.
wrapper.module
Wrapper.module.ts
#NgModule({
declaration: [WrapperComponent.ts]
imports: [
WrapperRouting.module
]
})
wrapper-routing.module.ts
WrapperRouting.module
routes = [
{
path: '',
component: wrapper.component.ts ,
children: [
{ path: '', loadChildren: Component1.module.ts},
{ path: '2', loadChildren: Component2.module.ts},
]
}
];
component1.module.ts
#NgModule({
declaration: [Component1Component, ShowTableComponent]
imports: [
Component1Routing.module
]
})
component1.component.ts
<show-table></show-table>
component2.module.ts
#NgModule({
declaration: [Component2Component, ShowTableComponent]
imports: [
Component2Routing.module
]
})
component2.component.ts
<show-table></show-table>
Im trying first to declar the ShowComponent in Component1.module.ts and Component2.module.ts however I got an error that ShowComponent is declared in two module.
Then, tried to put in the the parent module which is Wrapper.module.ts the error would be: ShowComponent is an Angular component, then verify that it is part of this module.
Can someone help me, much appreciated!
Can you please clarify how you are defining the parent-child relationship between all of these modules. Because there is no specific way to depict a parent-child relationship between modules in angular.
If you want to use the
<show-table></show-table>
in component1.module and component2.module, you have to add the wrapper.module in the imports array of both modules i.e. component1.module and component2.module and add the ShowComponent in the exports array of Wrapper.module.
After which your respective code will become as follows
Component1.module.ts
#NgModule({
declarations: [
Component1
],
imports: [
WrapperModule
]
})
export class Component1Module { }
Component2.module.ts
#NgModule({
declarations: [
Component2
],
imports: [
WrapperModule
]
})
export class Component2Module { }
wrapper.module.ts
#NgModule({
declarations: [
ShowComponent
],
exports: [
ShowComponent
]
})
export class WrapperModule { }
P.S. This method is used when you have to use a component from a different module in the HTML of a component. If you are using <router-outlet></router-outlet> you don't have to worry about importing the modules to use a component. You can just specify the name of the component in the routes array.
Do let me know if my answer helped you!
Related
In my Angular project, I am trying to use a component from a shared module where its child component is imported in the Dashboard module but facing this error.
If app-send-email is an Angular component, then verify that it is part of this module.
If 'app-send-email' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message.
app.routing.ts
const routes = [
{
path: 'dashboard',
loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule)
}]
dashboard.module.ts
import { SendEmailComponent } from './shared/send-email.component';
import { SharedDialogComponentModule } from '../shared/shared-dialog-component.module';
#NgModule({
imports: [SharedDialogComponentModule],
declarations: [ RecruiterSendEmailComponent ]
});
shared-dialog-component.module.ts
import { EmailDialogComponent } from '../../dashboard/shared/template/dialog/email-dialog/email-dialog.component';
#NgModule({
declarations: [EmailDialogComponent],
entryComponents: [EmailDialogComponent],
exports: [EmailDialogComponent]
})
email-dialog.component.html
<app-send-email></app-send-email>
Can anyone please help with this issue?
Well, you need to import the module SharedDialogComponentModule
import { SendEmailComponent } from './shared/send-email.component';
import { SharedDialogComponentModule } from '../shared/shared-dialog-component.module';
#NgModule({
import: [ SharedDialogComponentModule ]
declarations: [ RecruiterSendEmailComponent ]
});
I have a parent module where i'm lazy loading a child module
As you may see , i don't import my child module directly , but i'm loading it lazily under routing file :
Parent Module :
#NgModule({
imports: [
CommonModule,
ParentRoutingModule,
],
exports: [
ParentRoutingModule
],
declarations: [ParentComponent]
})
export class ParentModule { }
Parent Routing Module :
const parentRoutes: Routes = [
{path: '', component: ParentHomeComponent},
{
path: '',
loadChildren: () => ChildModule,
canLoad: [ChildModuleGuard]
},
];
#NgModule({
imports: [
CommonModule,
RouterModule.forChild(parentRoutes)
],
declarations: [],
exports: [
RouterModule
]
})
export class ParentRoutingModule { }
In my main ParentModule component ; the ParentHomeComponent i want to inject the view of my ChildHomeCOmponent , like this :
<p>
Parent-home works!
</p>
<app-Child-home></app-Child-home>
but this throws an error telling that the ChildHomeComponent isn't
part of the ParentModule (as i'm not importing it directly) ;
How to deal with that ??
I want that if the module is loaded , my child home component gets displayed under the parent home component
Suggestions ??
This is not how lazy loading works in Angular.
Non-lazy loaded modules cannot access components from lazy loaded modules.
I have a lazy load module which needs to expose providers, so I am using the forRoot convention and returning the following code:
#NgModule({
imports: [RouterModule.forChild([
{path: "", component: LazyComponent},
])],
declarations: [LazyComponent],
})
export class LazyModule {
static forRoot() {
return {
ngModule: LazyModule,
providers: [provider]
};
}
}
The problem is when I invoke the forRoot in my app module the lazy load does not work anymore. ( I don't see the separate chunk in my console )
#NgModule({
declarations: [
AppComponent,
HelloComponent
],
imports: [
BrowserModule,
AppRoutingModule,
LazyModule.forRoot() <======== this stops the lazy load module
],
bootstrap: [AppComponent]
})
export class AppModule {
}
From what I learned it should only make the providers singleton, why it does not work?
As of right now, it's not possible to execute a forRoot (or any other configuration static method of this sort) in a module that will load lazily. The problem here is that such a method returns a ModuleWithProviders while loadChildren requires a NgModuleFactory.
I faced a similar issue where I had to lazy load a module with some configurations. So, I came up with this temporary fix.
Lazy Module
#NgModule({
imports: [
RouterModule.forChild([
{path: "", component: LazyComponent},
])],
declarations: [LazyComponent],
})
export class LazyModule {
// considering the function only handle providers
static setDynamicProviders(provider?: any) {
if(LazyModule && LazyModule.__annotations__ && LazyModule.__annotations__[0]){
LazyModule.__annotations__[0].providers.push(provider);
}
return LazyModule;
}
}
Parent Module
const someService = {
provide: 'SOME_TOKEN',
useFactory: (dependecy1) => (//dome something with dependency1)
deps: [SOME_DEPENDENCY_TOKEN]
}
#NgModule({
imports: [
RouterModule.forRoot([
path: 'lazy',
loadChildren: ()=>(import('*your path to lazy module*').then(ref => ref.LazyModule.setDynamicProvider(someService)))
])
]
})
So, I am just modifying the annotations created by #NgModule Decorator. At this stage, Angular does not support lazy loading with static methods that return ModuleWithProviders.
When you import a LazyModule in your AppModule imports array it is not "lazy" anymore. A lazy module should only be referenced in a dedicated RoutingModule.
So if I understood you correctly you would like to share a Service between your LazyModules?
If so remove LazyModule from AppModule and create a SharedModule and move your Service you like to share inside the providers array in SharedModule. Import SharedModule in your AppModule with forRoot and import your SharedModule without forRoot in your LazyModules
Try below code when we define a module is Lazy RouterModule.forChild:
#NgModule({
imports: [RouterModule.forChild([
{path: "", component: LazyComponent},
])],
declarations: [LazyComponent],
})
export class LazyModule { }
But when we load in the parent module, try the below code:
#NgModule({
declarations: [
AppComponent,
HelloComponent
],
imports: [
BrowserModule,
AppRoutingModule,
RouterModule.forRoot([
{
path: '',
loadChildren: './layout/layout.module#LayoutModule',
canActivate: [AuthGuard]
}
]) <======== right way to load lazy module
],
bootstrap: [AppComponent]
})
export class AppModule {
}
Note: FullPath is like './moduleFolder/lazy.module#LayoutModule'
LayoutModule is your exported Module Name
Please let me know
I have a case, where I have two modules, who have there own Pipe-definitions. One Module is a customer module, the other a product module. In products I want to use customer pipes and vice versa.
If modules in Angular 2 import each other like the following:
Example Root Module:
#NgModule({
imports: [
BrowserModule, AModule, BModule
],
declarations: [
AppComponent
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Example Module B:
#NgModule({
imports: [BModule],
declarations: [
],
exports: []
})
export class AModule { }
Example Module A:
#NgModule({
imports: [AModule],
declarations: [
],
exports: []
})
export class BModule { }
The browser throws an error:
Uncaught Error: Unexpected value 'undefined' imported by the module
'BModule'
I could create a SharedModule, that declares both Pipes and import that module into A and BModule. But this would not be SOLID anymore, because customer pipes and product pipes just belong into there own module and not in another shared module.
Any proposals?
I googled, but did not find anything :(
I am currently using Angular 2 - RC5 with the router 3.0.0 RC1. This seems to be a pretty common error, but I can't find any solution that works. My component structure includes a "BasicContentComponent" which includes the main menu and the header and an aux outlet for the content of the child route. The "BasicContentComponent" comes from a shared module and the child routes component from specific module of that child route.
My route configuration looks like this
export const routeConfig = [
{
path: 'home',
component: BasicContentComponent,
children: [
{
path: '',
component: HomeContainer,
//canActivate: [IsAuthenticatedGuard],
outlet: 'content', // REMOVE THIS LINE
//resolve: {
// homeState: HomeResolver
//}
}
]
}
];
If I remove the "children" definition I am able to load "/home" but with this configuration I get the error.
Following are the module configurations, since the problem may also lie there.
app.module.ts
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
RouterModule.forRoot(routeConfig), //see above
SharedModule.forRoot(),
HomeModule
],
bootstrap: [AppComponent]
})
export class AppModule {}
shared.module.ts
import { Store, StoreModule } from '#ngrx/store';
#NgModule({
imports: [
RouterModule,
CommonModule,
...
StoreModule.provideStore(reducers),
],
declarations: [
BasicContentComponent,
...
],
exports: [BasicContentComponent, ...],
})
export class SharedModule {
static forRoot() : ModuleWithProviders {
return {
ngModule: SharedModule,
providers: [
MdIconRegistry,
...
IsAuthenticatedGuard,
...
HomeResolver
]
}
}
}
home.module.ts
#NgModule({
imports: [CommonModule, SharedModule],
declarations: [
HomeContainer,
HomeComponent
],
exports: [HomeContainer]
})
export class HomeModule { }
I get the following error
browser_adapter.js:84 EXCEPTION: Error: Uncaught (in promise): Error:
Cannot match any routes: 'home'
Any idea what the problem could be? Is it a route config or a modules issue? thanks
Edit
I forgot the templates:
app.component.html
<div>
<router-outlet></router-outlet>
</div>
basic-content.component.html
<md-sidenav-layout fullscreen>
<md-sidenav mode="side" align="start" [opened]="isOpened$ | async" color="warn">
<mainnav-container></mainnav-container>
</md-sidenav>
<page-header-container></page-header-container>
<div class="app-content">
<router-outlet name="content"></router-outlet> // REMOVE NAME
</div>
</md-sidenav-layout>
I got help on Gitter. If I remove the "name" attribute of the router-outlet and also remove it from the routerConfig everything works as intended. I don't fully understand why I have to remove it and how exactly the router finds the correct outlet - it makes kinda sense since the outlets are nested - but I will udpate my answer at a later point when the documentation for named outlets is more complete.
Thanks to #DzmitryShylovich on Gitter.