You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Using multiple components in different modules causing "Type X is part of the declarations of 2 modules" error #10646
[ ] bug report
[x] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
Current behavior
Right now you cannot import two directives of the same module
Expected/desired behavior
You can use same directives/components in multiple modules without errors.
What is the motivation / use case for changing the behavior?
Concept of the shared module with its shared resources is good for components that are used everywhere. But if you have a complex application (ours contain more then 50 modules and 1500 components, services and pipes all together) multiple components can be reused different way. For example QuestionListPage uses UserActiveListPanel from User module. Also PhotoListPage uses same UserActiveListPanel, and VideoListPage uses UserActiveListPanel. How do I reuse this panel? Best way is see is to provide it in directives of the component as it was before rc.5. But right now I can't do it. But I can create lets say UserShareModule and put it there... its good, but if I put everything that is used by other modules from user module, i'll LOT of things there unnecessary in most of times. Then what to do? Create UserActiveListPanelShareModule? It will create lot of such trash files. So what to do? Maybe we simply can provide same directives multiple times without having this annoying error Type X is part of the declarations of 2 modules?
If you tell me that its by design, then my answer is: in my opinion its a bad design.
Please tell us about your environment:
Angular version: 2.0.0-rc.5
Browser: [all ]
Language: [all]
Reacted by Martin, Tobias Punke, Parth Chokshi, Josh Friend, Alin Floare, HFTSOL, Juliano Petronetto, João Ribeiro, Dino Bettini, Johan Alvarez and 53 more
If you want to use a component across multiple modules, you'll need to create a "shared" module and add that component the shared module's exports. Then you add that shared module into your other modules imports.
Reacted by Juan Carlos Mordán, Mangesh, Adrian Moisa, san4ezz87, Johan Alvarez, Dan Garcia , shayanhusaini, Víctor Adrián, Gordon Sun, Pierre Cavin and 28 more
Reacted by HFTSOL, Juliano Petronetto, drpdrp, Lucas Carvalho Corrêa, Dan Garcia , Gabrijel Škoro, Nick Lechnowskyj, Brock Klein, João Machete, Vincent and 51 more
Reacted by Iyad Alfarra, Fernando Ott and mircopolo
yeah I did it and it works. The problem is that it is very very inconvenient for multiple directives/components that are used only few times by other components.
Reacted by Martin, Tobias Punke, Josh Friend, Jason Redd, derek, Adrian Moisa, HFTSOL, Juliano Petronetto, Dino Bettini, zilions and 36 more
Once you have your shared module setup it should be easier to add
components to multiple modules. In the long run it helps you to organize
your code into modules with a standard convention.
yeah I did it and it works. The problem is that it is very very
inconvenient for multiple directives/components that are used only few
times by other components.
Reacted by Víctor Adrián, Aurelio and Tyler Hinkelman
Reacted by HFTSOL, Dino Bettini, Vincent, Nicolás Fantone, Vladislav Petrosyan, Chetan Dhanvij, Pierre Raii, Victor Buchinskiy, johnnyp0201, CuBiC and 15 more
Lets bring an example. I have two modules. QuestionModule, PostModule and UserModule. QuestionModule and PostModule need UserListPanelComponent from a UserModule. How to handle such situation?
option1. Create a UserSharedModule and add there UserListPanelComponent. But it looks like we gonna put to UserSharedModule all other components too (lets say other 20 components out of 50 UserModule has), because other modules (30) also uses different components of the UserModule. QuestionModule (or any other that uses UserModule's components) loads lot of stuff that he don't really need. It loads all 20 components when it needs only one. So it seems to be a bad option.
option2. Create UserListPanelSharedModule. that shares only one component -UserListPanelComponent. Now I can load only one file and not worry that it loads all 20 components. But wait... its annoying and simply stupid to create one another separate file for each component you want to share. So, it definitely bad option.
Any good options here?
Reacted by >°))))彡, Yc. Shen, linusbrolin, HFTSOL, Oscar Lodriguez, Dino Bettini, Kenny Chen, Johan Alvarez, Ajey Charantimath, Mahdi Akbary and 60 more
This is indeed very confusing. I have moved some functionality into a module and now I am getting this error: "NgSelectOption is part of the declarations of 2 modules: InternalFormsSharedModule and SpFormsModule!" SpFormsModule is my module but I am not importing InternalFormsSharedModule anywhere. Any idea why would these two modules clash?
@jusefb this usually means you've added the NgSelectOption to your declarations instead of importing the appropriate forms module. The rule is if you created the directive, you need to declare it. If you didn't create it and it comes with a module, it doesn't go in your declarations. Instead you add that module to your imports.
For your previous comment, if you are concerned with modules sharing components that other modules don't need, then you organize further. I used the term "shared" module loosely because there doesn't have to be just one. You can create a set of small modules to import into other modules to share components.
Reacted by brudski, Tyler Hinkelman, syedarifandrabi, Andrew Blejde, Kevin Arouza, thisisbinod and Denes Papp
Reacted by easedev, Víctor Adrián and theappsmiths
Reacted by ootwch, Umed Khudoiberdiev, Rainer, Kai Ruhnau, Vijender Reddy Chintalapudi, Eric Hegnes, Jonathan Adamit, Tobias Punke, Carl Sutton, Josh Friend and 184 more
Reacted by Rainer, Aliaksandr Kazarez, Dan Garcia , Tobias Punke, Josh Friend, Jason Redd, linusbrolin, HFTSOL, piq9117, Juliano Petronetto and 69 more
Reacted by Víctor Adrián
Reacted by Kapil Kharade, Sangwin Gawande, Muhammad Asad, Nicu and Daniel Kvist
@vicb I think that you need to read more carefully before you close an issue.
Reacted by Pascal van Kooten, Umed Khudoiberdiev, Tobias Punke, Josh Friend, Jason Redd, Alin Floare, Ryeker J Herndon, Joshua Carter, Yu, linusbrolin and 75 more
Same issue here: "Type NgSelectOption is part of the declarations of 2 modules". Fulltext search through my code has not found any occurence of 'NgSelectOption', so I am pretty sure that this is caused by a third party module (?) or library... but which one?
=> Please add "better error message" to this feature request, I think it might make the migration to post rc.5 with ngmodules a lot less painful
Note: The solutions presented in #10784 did not help either...
@PunkSage@ootwch@SnareChops can someone reproduce this in a plunker? It would help in getting the issue reopened. If its a third party module that's causing it, my guess is that two modules have the NgSelectOption in their declarations instead of importing the appropriate module.
It could also happen if you haven't removed all the directives from your components and still have a lingering directive in a component used in multiple modules.
@rmcsharry ... generally the situation is simple ... you need to import (for example to module M) always a module (for example module S) when you want to use a component that is declared in that module (module S).
This is the same principle both for eager or lazy module.
@mic-mlapis It seems I am not doing a very good job of explaining a situation that appears to NOT follow these rules, yet should.
Here are the prerequisites for this problem:
1 ThisComponent is declared in Module S.
2 Module S declares two routes, A and B, each of which lazy load their own modules: ModuleLazyA, ModuleLazyB.
So in this situation, modules A and B are not importing Module S.
Module S is not importing either A or B, but is lazy loading them.
A and B are essentially children of S.
But neither A or B can see ThisComponent EVEN THOUGH it is declared in their parent module. They seem to just completely ignore it.
So I have to put ThisComponent into another module and then that module has to be imported by BOTH of the lazy modules.
Does that not seem odd to anyone else?
Why do I have to create another module just for ThisComponent...surely it makes more sense for the lazy loaded modules to have 'access' to whatever components are declared in their parent module?
If I am wrong and they CAN DO THAT, then clearly there is some extra plumbing code I need to add to make that happen.
If they CANNOT DO THAT then the statement by @jcmordan is incorrect when he said "your component will be available for all sub modules childrens of the module where you put your shared component."
I would also contend your statement "This the same principle both for eager or lazy module."
If A and B were eager loaded, then they are imported into S (not the same as lazy loaded). So in that scenario they would both get access to ThisComponent declared in their parent, S (and an extra module would not be required).
@rmcsharry ... you have to create a new module, even for this one component, we can call it SHARED, and this one will be imported to the eager module and both lazy loaded modules. The concept of modules is relative easy but what is SUPER IMPORTANT is the context in which components are declared, compiled, and used ...
And this is the reason why you need the new module ... and when lazy loaded modules will be loaded in future ... that new module will be already loaded before of course in this case. Creating a new module is about 5 lines of code so it is nothing to care about.
@mlc-mlapis Thank you for the reply but I believe you are still not understanding what I am saying, which is this:
You don't need the shared module if a parent is eager loading children. The parent can contain the component and both children will be able to use it.
You do need the shared module if a parent is lazy loading children. The children will not see the component if you declare it in the parent so in this scenario you must use a shared module.
So I would say it is something to care about - otherwise you are in danger of creating a huge shared module with maybe hundreds of components and then end up loading that on a lazy route just to get access to one single component. So how you structure shared code is quite important I think. I imagine most large Angular projects will require several shared modules, not just one, for this reason. And on routes which are not lazy loaded, they might not need a shared module at all - they can simply put the component in the parent.
Well, I join this discussion another year after your discussion.
I just wanted to specify that the components/directives that are not widely used in the app should not be included in the shared module !!!
The feature modules can also export components and directives, don't just get stuck in the shared module and put in it everything that is only used few times in all your app. This is an anti-pattern ;-) Enjoy :)
I have a shared module but I am getting the following. "ModuleX and ModuleX" 😄
Type PipeA is part of the declarations of 2 modules: ModuleX and ModuleX! Please consider moving PipeA to a higher module that imports ModuleX and ModuleX. You can also create a new NgModule that exports and includes PipeA then import that NgModule in ModuleX and ModuleX .
ModuleX has root and child providers too in addition to PipeA
I'm doing research before I start using Angular CLI (first time dealing with Angular). Based on this thread I'm deciding the best way to build my first Angular app is to create one module for every component or group of components that perform a single function, like:
All basic/primitive functionality controls have one module and one component per module.
Example:
- 1 module and component for Avatar picture.
- 1 module and component for an image file upload button.
Specialized "controls", such as a module that imports the avatar picture control (module) and the image upload control (module) together.
I believe thinking about modules as single "controls", not website "widgets" is the best way to modularize Angular apps (well, any web app really). That said, a widget of course will also be a module, so it's just a way of thinking (control modules vs widget modules, all placed on a view module).
I don't think this thread is about what is the best practice, I think most of people here are not asking for what is the best practice to do this. Other than, this is quite a specific problem that people trying to get Angular to solve.
The issue here is really dependency management and probably, especially for people managing large applications with lazy loading components (loading components on the fly, so the app gets loaded in parts)
I have been working with a web application contains 60+ screens, and based on the configurations, each client gets different screens. Each screen implementation is complex enough to warrant its own module. So, we don't want to load the whole application when the user hit the url the first time. The whole app download will probably exceed 5MB+ in size. For us to be able to manage the 'dependencies' probably, it will be easier to just declare the components in the module and let the code/framework sort out the duplications. You can argue this is custom but as there are quite a few people coming in this thread to express their 'feedback' as 'this is not good enough' (well at least I am), is probably something worth look into.
In situation like this, declaring shared module specifically for the combination of 'screens' will be mad, therefore there is no choice but to put all the shared components into one single shared module. That defects the purpose of splitting the code. Of course there is always a solution to a problem, such as declare a shared module for each, for example client, but the point is 'we are giving our feedback to improve this framework'.
This might be an old concept now as most of the web apps I have been working are just one JS file contains everything. Therefore, putting all shared component as one shared module isn't an issue at all.
@mlc-mlapis The default module wrapping sounds great, and makes sense. I find myself wondering the same thing as I keep creating a module just to wrap a component for the purpose of sharing in other modules. Seems that should be implicit.
it works fine for me
In my case: this is my component that is repeating ModalFilterOptionPage :
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Routes, RouterModule } from '@angular/router';
import { IonicModule } from '@ionic/angular';
import { ReactiveFormsModule } from '@angular/forms';
Then, only add it in your app module:
... @NgModule({
declarations: [
AppComponent,
ModalFilterOptionPage],
entryComponents: [
ModalFilterOptionPage
],
I can only agree w/ @rmcsharry, he explained the problem multiple times in detail, specifically for lazy loaded modules.
question is also if I have to import that shared module again and again in lazy loaded modules (although the shared module was already loaded by the main app.module and should be accessible), will this bloat my lazy loaded chunks w/ redundant code ?
angular-automatic-lock-bot commented on Sep 18, 2019
Activity
brandonroberts commentedon Aug 10, 2016
If you want to use a component across multiple modules, you'll need to create a "shared" module and add that component the shared module's
exports. Then you add that shared module into your other modulesimports.pleerock commentedon Aug 10, 2016
yeah I did it and it works. The problem is that it is very very inconvenient for multiple directives/components that are used only few times by other components.
brandonroberts commentedon Aug 11, 2016
Once you have your shared module setup it should be easier to add
components to multiple modules. In the long run it helps you to organize
your code into modules with a standard convention.
On Aug 10, 2016 4:26 PM, "Umed Khudoiberdiev" notifications@github.com
wrote:
pleerock commentedon Aug 11, 2016
No it really harms organization in a long run.
Lets bring an example. I have two modules.
QuestionModule,PostModuleandUserModule.QuestionModuleandPostModuleneedUserListPanelComponentfrom aUserModule. How to handle such situation?option1. Create a
UserSharedModuleand add thereUserListPanelComponent. But it looks like we gonna put toUserSharedModuleall other components too (lets say other 20 components out of 50UserModulehas), because other modules (30) also uses different components of theUserModule. QuestionModule (or any other that uses UserModule's components) loads lot of stuff that he don't really need. It loads all 20 components when it needs only one. So it seems to be a bad option.option2. Create
UserListPanelSharedModule. that shares only one component -UserListPanelComponent. Now I can load only one file and not worry that it loads all 20 components. But wait... its annoying and simply stupid to create one another separate file for each component you want to share. So, it definitely bad option.Any good options here?
jusefb commentedon Aug 11, 2016
This is indeed very confusing. I have moved some functionality into a module and now I am getting this error: "NgSelectOption is part of the declarations of 2 modules: InternalFormsSharedModule and SpFormsModule!" SpFormsModule is my module but I am not importing InternalFormsSharedModule anywhere. Any idea why would these two modules clash?
brandonroberts commentedon Aug 11, 2016
@jusefb this usually means you've added the
NgSelectOptionto yourdeclarationsinstead of importing the appropriate forms module. The rule is if you created the directive, you need to declare it. If you didn't create it and it comes with a module, it doesn't go in yourdeclarations. Instead you add that module to yourimports.For your previous comment, if you are concerned with modules sharing components that other modules don't need, then you organize further. I used the term "shared" module loosely because there doesn't have to be just one. You can create a set of small modules to import into other modules to share components.
jusefb commentedon Aug 11, 2016
Thanks, i will go through my code more thoroughly and try get this to work
DaSchTour commentedon Aug 11, 2016
If you want to use the same Component you can maybe try to cheat angular by using extends.
Try something like this.
No you have two components that are basically the same.
To avoid conflicts you might add different selectors to the components.
vicb commentedon Aug 12, 2016
Your question sounds like a support request.
Please use the issue tracker only for bugs and feature requests.
Use gitter and StackOverflow for support request.
pleerock commentedon Aug 12, 2016
where do you see a question here? :speachless:
PunkSage commentedon Aug 12, 2016
@vicb I think that you need to read more carefully before you close an issue.
ootwch commentedon Aug 14, 2016
Same issue here: "Type NgSelectOption is part of the declarations of 2 modules". Fulltext search through my code has not found any occurence of 'NgSelectOption', so I am pretty sure that this is caused by a third party module (?) or library... but which one?
=> Please add "better error message" to this feature request, I think it might make the migration to post rc.5 with ngmodules a lot less painful
Note: The solutions presented in #10784 did not help either...
SnareChops commentedon Aug 15, 2016
Agreed, this is a legitimate feature request and not a question requesting support. This should be reopened for discussion.
brandonroberts commentedon Aug 15, 2016
@PunkSage @ootwch @SnareChops can someone reproduce this in a plunker? It would help in getting the issue reopened. If its a third party module that's causing it, my guess is that two modules have the
NgSelectOptionin theirdeclarationsinstead of importing the appropriate module.It could also happen if you haven't removed all the
directivesfrom your components and still have a lingering directive in a component used in multiple modules.70 remaining items
mlc-mlapis commentedon Nov 10, 2017
@rmcsharry ... generally the situation is simple ... you need to import (for example to module
M) always a module (for example moduleS) when you want to use a component that is declared in that module (moduleS).This is the same principle both for eager or lazy module.
rmcsharry commentedon Nov 10, 2017
@mic-mlapis It seems I am not doing a very good job of explaining a situation that appears to NOT follow these rules, yet should.
Here are the prerequisites for this problem:
1 ThisComponent is declared in Module S.
2 Module S declares two routes, A and B, each of which lazy load their own modules: ModuleLazyA, ModuleLazyB.
So in this situation, modules A and B are not importing Module S.
Module S is not importing either A or B, but is lazy loading them.
A and B are essentially children of S.
But neither A or B can see ThisComponent EVEN THOUGH it is declared in their parent module. They seem to just completely ignore it.
So I have to put ThisComponent into another module and then that module has to be imported by BOTH of the lazy modules.
Does that not seem odd to anyone else?
Why do I have to create another module just for ThisComponent...surely it makes more sense for the lazy loaded modules to have 'access' to whatever components are declared in their parent module?
If I am wrong and they CAN DO THAT, then clearly there is some extra plumbing code I need to add to make that happen.
If they CANNOT DO THAT then the statement by @jcmordan is incorrect when he said "your component will be available for all sub modules childrens of the module where you put your shared component."
I would also contend your statement "This the same principle both for eager or lazy module."
If A and B were eager loaded, then they are imported into S (not the same as lazy loaded). So in that scenario they would both get access to ThisComponent declared in their parent, S (and an extra module would not be required).
mlc-mlapis commentedon Nov 10, 2017
@rmcsharry ... you have to create a new module, even for this one component, we can call it SHARED, and this one will be imported to the eager module and both lazy loaded modules. The concept of modules is relative easy but what is SUPER IMPORTANT is the context in which components are declared, compiled, and used ...
And this is the reason why you need the new module ... and when lazy loaded modules will be loaded in future ... that new module will be already loaded before of course in this case. Creating a new module is about 5 lines of code so it is nothing to care about.
rmcsharry commentedon Nov 22, 2017
@mlc-mlapis Thank you for the reply but I believe you are still not understanding what I am saying, which is this:
You don't need the shared module if a parent is eager loading children. The parent can contain the component and both children will be able to use it.
You do need the shared module if a parent is lazy loading children. The children will not see the component if you declare it in the parent so in this scenario you must use a shared module.
So I would say it is something to care about - otherwise you are in danger of creating a huge shared module with maybe hundreds of components and then end up loading that on a lazy route just to get access to one single component. So how you structure shared code is quite important I think. I imagine most large Angular projects will require several shared modules, not just one, for this reason. And on routes which are not lazy loaded, they might not need a shared module at all - they can simply put the component in the parent.
GO3LIN commentedon Jan 4, 2019
Well, I join this discussion another year after your discussion.
I just wanted to specify that the components/directives that are not widely used in the app should not be included in the shared module !!!
The feature modules can also export components and directives, don't just get stuck in the shared module and put in it everything that is only used few times in all your app. This is an anti-pattern ;-) Enjoy :)
m3hm3tk commentedon Jan 16, 2019
I have a shared module but I am getting the following. "ModuleX and ModuleX" 😄
ModuleX has root and child providers too in addition to PipeA
I had to create another module for PipeA
rjamesnw commentedon Feb 5, 2019
I'm doing research before I start using Angular CLI (first time dealing with Angular). Based on this thread I'm deciding the best way to build my first Angular app is to create one module for every component or group of components that perform a single function, like:
All basic/primitive functionality controls have one module and one component per module.
Example:
- 1 module and component for Avatar picture.
- 1 module and component for an image file upload button.
Specialized "controls", such as a module that imports the avatar picture control (module) and the image upload control (module) together.
I believe thinking about modules as single "controls", not website "widgets" is the best way to modularize Angular apps (well, any web app really). That said, a widget of course will also be a module, so it's just a way of thinking (control modules vs widget modules, all placed on a view module).
kennygitchen commentedon Feb 7, 2019
I don't think this thread is about what is the best practice, I think most of people here are not asking for what is the best practice to do this. Other than, this is quite a specific problem that people trying to get Angular to solve.
The issue here is really dependency management and probably, especially for people managing large applications with lazy loading components (loading components on the fly, so the app gets loaded in parts)
I have been working with a web application contains 60+ screens, and based on the configurations, each client gets different screens. Each screen implementation is complex enough to warrant its own module. So, we don't want to load the whole application when the user hit the url the first time. The whole app download will probably exceed 5MB+ in size. For us to be able to manage the 'dependencies' probably, it will be easier to just declare the components in the module and let the code/framework sort out the duplications. You can argue this is custom but as there are quite a few people coming in this thread to express their 'feedback' as 'this is not good enough' (well at least I am), is probably something worth look into.
In situation like this, declaring shared module specifically for the combination of 'screens' will be mad, therefore there is no choice but to put all the shared components into one single shared module. That defects the purpose of splitting the code. Of course there is always a solution to a problem, such as declare a shared module for each, for example client, but the point is 'we are giving our feedback to improve this framework'.
This might be an old concept now as most of the web apps I have been working are just one JS file contains everything. Therefore, putting all shared component as one shared module isn't an issue at all.
cheers, Kenny
mlc-mlapis commentedon Feb 7, 2019
@kennygitchen ...
Certainly not. Creating a module means adding 5 lines of code over the code for just a component, so it's nothing that should be a problem.
There is an idea to have a so-called
defaultmodule (when Ivy will be ready) which should allow to lazily-load only a single component.rjamesnw commentedon Feb 11, 2019
@mlc-mlapis The default module wrapping sounds great, and makes sense. I find myself wondering the same thing as I keep creating a module just to wrap a component for the purpose of sharing in other modules. Seems that should be implicit.
phutaneVinayak commentedon Feb 14, 2019
yes i try this way.
but angular giving error for shared components
error: Template parse errors:
'trip-card' is not a known element:
Angelita31 commentedon Mar 26, 2019
it works fine for me
In my case: this is my component that is repeating ModalFilterOptionPage :
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Routes, RouterModule } from '@angular/router';
import { IonicModule } from '@ionic/angular';
import { ReactiveFormsModule } from '@angular/forms';
const routes: Routes = [
{
path: '',
/* component: ModalFilterOptionPage remove it */
}
];
@NgModule({
imports: [
CommonModule,
ReactiveFormsModule,
IonicModule,
RouterModule.forChild(routes)
]
/* declarations: [ModalFilterOptionPage] remove it*/
})
export class ModalFilterOptionPageModule {}
Then, only add it in your app module:
...
@NgModule({
declarations: [
AppComponent,
ModalFilterOptionPage],
entryComponents: [
ModalFilterOptionPage
],
.....})
it works for me!
proto6 commentedon Aug 18, 2019
I can only agree w/ @rmcsharry, he explained the problem multiple times in detail, specifically for lazy loaded modules.
question is also if I have to import that shared module again and again in lazy loaded modules (although the shared module was already loaded by the main app.module and should be accessible), will this bloat my lazy loaded chunks w/ redundant code ?
angular-automatic-lock-bot commentedon Sep 18, 2019
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.