Solvedangular Using multiple components in different modules causing "Type X is part of the declarations of 2 modules" error

I'm submitting a ... (check one with "x")

[ ] 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]
54 Answers

✔️Accepted Answer

as @brandonroberts saids, create a shared module like this:

import { NgModule }       from '@angular/core';
import { CommonModule }   from '@angular/common';
import { FormsModule }    from '@angular/forms';

import {SharedComponentA} from "./SharedComponentA";
import {SharedComponentB} from "./SharedComponentA";

@NgModule({
    imports: [
        CommonModule,
        FormsModule,

    ],
    declarations: [
      SharedComponentA,
      SharedComponentB

    ],
    providers: [
    ],
    exports: [
      SharedComponentA,
      SharedComponentB
    ]
})
export class SharedModule {}

then use the SharedModule like this..

import { NgModule }       from '@angular/core';
import { CommonModule }   from '@angular/common';
import { FormsModule }    from '@angular/forms';

import {SharedModule } from './SharedModule';

@NgModule({
    imports: [
        CommonModule,
        FormsModule,

        SharedModule

      //..
    ],
    declarations: [
     // ....
    ],
    providers: [
        // ....
    ]
})
export class PersonModule{}

Other Answers:

@vicb I think that you need to read more carefully before you close an issue.

where do you see a question here? :speachless:

No it really harms organization in a long run.

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?

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:

@NgModule({
    imports: [
        CommonModule,
        FormsModule
    ],
    declarations: [
        Component1,
        Component2,
        // etc..
    ],
    expose: [ // Or really any word that would better describe what you're trying to do.
        Component1,
        Component2
    ]
})
export class AppModule{}

And then in your child module:

@NgModule({
    imports: [
        CommonModule,
        FormsModule
    ],
    inherit: [ // Inherit the exposed components from the parent module!
        Component1,
        Component2
    ]
})
export class SubModule{}

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.

More Issues: