-
Notifications
You must be signed in to change notification settings - Fork 25k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using multiple components in different modules causing "Type X is part of the declarations of 2 modules" error #10646
Comments
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 |
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. |
Once you have your shared module setup it should be easier to add On Aug 10, 2016 4:26 PM, "Umed Khudoiberdiev" notifications@github.com
|
No it really harms organization in a long run. Lets bring an example. I have two modules. option1. Create a option2. Create Any good options here? |
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 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. |
Thanks, i will go through my code more thoroughly and try get this to work |
If you want to use the same Component you can maybe try to cheat angular by using extends. @Component({
selector: "selector",
templateUrl: "/component.html"
})
class BaseComponent {}
export class AComponent extends BaseComponent {}
export class BComponent extends BaseComponent {} No you have two components that are basically the same. |
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. |
where do you see a question here? :speachless: |
@vicb I think that you need to read more carefully before you close an issue. |
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... |
Agreed, this is a legitimate feature request and not a question requesting support. This should be reopened for discussion. |
@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 It could also happen if you haven't removed all the |
@brandonroberts and others - I think this error occurs when a component (either user-written or built-in) has been accidentally, implicitly, transitively included in more than one module - which can easily happen even without the now-deprecated "directives" list. Maybe that tip will make it easier to make a repro plunker. Still, I suspect it will turn out to be a "feature, not a bug". |
@kylecordes Right, but if you've upgraded to RC5 and you haven't removed all your |
@brandonroberts Thanks, that has bee helpful. I guess it could also be New full-text search on Note that I was mentioning the error message above, seems in one case it gave me the name of the offending module... in another case it mentioned Conclusion: The update from RC4 to RC5 requires to update (all?) third party libraries in use, or at least the ones designed for ng2? Seems the whole thing is less backward compatible than I had been hoping from the documentation ;-), but it also seems solvable now... Would it have been helpful to have |
@ootwch With the new module system, it will be most typical for third-party Angular based libraries to present themselves to your application as a module. So yes, they will need to be updated to embrace RC5+. However, in the meantime there is a fairly easy workaround. You can simply add a single file in your application which defines a module which includes the contents of the older (RC4 or less) angular based library you were using. Then depend on this module from each of your own modules. That should get you past the trouble between now and when those libraries are updated. |
I am having problems with ng2-select. I can't drop its directive into multiple modules now in rc5. It was a good library for making nice multi-select dropdowns but now it's ridiculous that it can't be used twice in the application. |
Hi, I have the same problem here. I try moving the common components to the AppModule. but then i got and error
|
@jcmordan |
Any update on this? It really is a headache. |
Seems pretty silly to have to do this extra work to be able to use a component thats meant to be shared... Feels like an extra layer of configuration on top of all the other configuration thats needed... |
as @brandonroberts saids, create a shared module like this:
then use the SharedModule like this..
|
Domo arigato gozaimasu, from México! 👍 |
I would have to agree that this is a big inconvenience. I have to create a module for something as trivial as one component. |
This is extremely inconvenient, as well as being plain ugly. You should really be able to inherit components from a parent module, because I think a shared module is extremely ugly. You're going to end up with one huge shared module with all your components, which is one of the things I hate in more conventional platforms like .NET I think you should be able to at least explicitly be able to share components between parent-child modules, in the sense of something like this:
And then in your child module:
I'm sure there is a better way to do this. You just don't want to have ten thousand components in a Shared module. |
@jcmordan |
FYI If you're like me and use angular-cli. When you refactor your code to use a shared module restart the cli server or you'll see console errors about the components not being registered. It doesn't detect the changes otherwise. That had me stumped for a while! |
Is there any update on this? One year latter since this issue was opened and i still can not find the answer. |
@duannx ... a component can be included in the declaration section only of one module - it is by design. |
@mlc-mlapis Yeah. I khow it is by design but it is not the problem. The main question is how to share component between modules and the only answer is use share.module.ts. This way cause many annoying |
@duannx I know is annoying, but usually an app is build in a hirarchycal group of modules. With that in mind just put your shared component as top as you need, this way your component wil be avialable for all sub modules childrens of the module where you put your shared component. |
@jcmordan Yeah. I think i should do it for my project. Thanks. |
@jcmordan -- I was wondering about this. If I declare a component in my AppModule it should be available to any modules that need it that are in my imports? That seems to be how it is working for me. |
@raysuelzer if you want to use components, directives, pipes from module B in module A, you have to import B (or any other module that exports B) in A. |
@jcmordan In the case of lazy loaded modules I am not sure what you said is correct: "With that in mind just put your shared component as top as you need, this way your component wil be avialable for all sub modules childrens of the module where you put your shared component." If you have ModuleMain which has routes defined, and it lazy loads ModuleLazyA and ModuleLazyB and both of those need ThisComponent, putting ThisComponent into ModuleMain does not seem to work, even though hierarchically speaking it is above the two lazy modules. I found that I needed to put ThisComponent into ThisSharedModule and import into BOTH of the lazy modules. Did I miss something? |
@rmcsharry No, you need to import every module everwhere where you want to use components, directives, or pipes. |
@zoechi Thanks for the fast response. Are you saying I am correct or I am wrong? I thought that I could declare ThisComponent in ModuleMain and have it available to the two lazy loaded modules. If ModuleLazyA and ModuleLazyB were NOT lazy loaded, then I presume that declaring ThisComponent inside ModuleMain (which would have to import A & B as NON lazy loaded) would then work, right? It is only because A&B are lazily loaded that I CANNOT declare ThisComponent in ModuleMain, but must instead put that into a shared module for both lazy modules to import. This seems very counter-intuitive - since A&B are both lazy loaded by Main, why do they not get access to all components declared in Main? |
@rmcsharry ... generally the situation is simple ... you need to import (for example to module 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: So in this situation, modules A and B are not importing Module 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:
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" 😄
ModuleX has root and child providers too in addition to PipeA I had to create another module for 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:
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. cheers, Kenny |
@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 |
@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. |
yes i try this way. but angular giving error for shared components error: Template parse errors:
|
it works fine for me import { IonicModule } from '@ionic/angular'; import { ReactiveFormsModule } from '@angular/forms'; const routes: Routes = [ @NgModule({ Then, only add it in your app module: .....}) |
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 ? |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
I'm submitting a ... (check one with "x")
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 errorType 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:
The text was updated successfully, but these errors were encountered: