byCoder
byCoder

Reputation: 9184

Angular 2: misunderstanding with imports

I wanna port some of structure from angular 1.4...

And I have some troubles. For example I have such structure:

enter image description here

components - is a module, customer is a module, list - is a module.

I have troubles with importing modules & components.

I do it in a such way:

app.module

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';

import { MaterialModule } from '@angular/material';
import 'hammerjs';

import {NgbModule} from '@ng-bootstrap/ng-bootstrap';

import { ComponentsModule } from './components/components.module';
import { CoreModule } from './core/core.module';
import { ServicesModule } from './services/services.module';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    MaterialModule.forRoot(),
    ComponentsModule,
    CoreModule,
    ServicesModule,
    NgbModule.forRoot()
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.html

<customer-list></customer-list>

and if I use here angular2 bootstrap:

<ngb-accordion #acc="ngbAccordion" activeIds="ngb-panel-0">
  <ngb-panel title="Simple">
    <template ngbPanelContent>
      demo
    </template>
  </ngb-panel>
</ngb-accordion>

everything is ok.

components.module

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

import { CustomerModule } from './customer/customer.module';

@NgModule({
  imports: [
    CommonModule
  ],
  declarations: [],
  exports: [CustomerModule]
})
export class ComponentsModule { }

customer.module

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CustomerComponent } from './customer.component';
import { ListComponent } from './list/list.component';
import { ItemComponent } from './list/item/item.component';

@NgModule({
  imports: [
    CommonModule
  ],
  declarations: [CustomerComponent, ListComponent, ItemComponent],
  exports: [CustomerComponent, ListComponent]
})
export class CustomerModule { }

list.module

import { NgModule } from '@angular/core';

import {NgbModule} from '@ng-bootstrap/ng-bootstrap';

import { CommonModule } from '@angular/common';
import { ListComponent } from './list.component';
import { ItemComponent } from './item/item.component';

@NgModule({
  imports: [
    CommonModule,
    NgbModule
  ],
  declarations: [ListComponent, ItemComponent],
  exports: [ListComponent]
})
export class CustomerModule { }

list.component.html

  <ngb-accordion #acc="ngbAccordion">
    <ngb-panel >
      <template ngbPanelContent>
        test
      </template>
    </ngb-panel>
  </ngb-accordion>

And here I get error:

zone.js:388Unhandled Promise rejection: Template parse errors: 'ngb-panel' is not a known element:

But if I import NgbModule in every module, till I reach app.module - everything is fine. But this is ridiculous.

Is there any possibility, to organize imports of modules in angular 2, so, that I don't need to import them in every module, once imported in root - I can reuse them in nested modules, like it was in angular 1.4 (using ngInject)?

Upvotes: 1

Views: 1125

Answers (3)

Poul Kruijt
Poul Kruijt

Reputation: 71891

To use NgbModule inside your ListModule you should add it to the imports array like you did. But you should also import it in your AppModule. So only in two places. The module where you use it, and the forRoot() import at the root module which also imports the BrowserModule:

only relevant code: AppModule

@NgModule({
...
  imports: [
    BrowserModule,
    NgbModule.forRoot()
  ]
...
})
export class AppModule {}

only relevant code: ListModule:

@NgModule({
  imports: [
    CommonModule,
    NgbModule
  ],
  declarations : [
    ListComponent,
    ItemComponent
  ],
  exports : [
    ListComponent,
    ItemComponent
  ]
})
export class ListModule{}
//you named this CustomerModule for some reason....
//could also be the problem, or just a wrong copy paste :)

If you then want to use the ListComponent inside your CustomerModule, you should import the ListModule and not the ListComponent.

@NgModule({
  imports: [
    CommonModule,
    ListModule
  ],
  declarations: [CustomerComponent],
  exports: [CustomerComponent]
})
export class CustomerModule {}

If you only import the ListComponent it won't see the NgbModule you imported in your ListModule. Rule of thumb, only import/declare components which belong to that module. Don't import/declare components/directives/pipes/services from other modules. Only import the entire module. You can however export one module in the other. This way, if you import the module which exported another module, the other module is also available. (this doesn't make a lot of sense). Let me write it down for you:

Components module only export customer module

@NgModule({
   exports : [
      CustomerModule
   ]
})
export class ComponentsModule{}

Customer module importing and export list module

@NgModule({
   imports : [
     ListModule
   ],
   exports : [
     ListModule
   ]
})
export class CustomerModule{}

List module exporting list component

@NgModule({
   imports : [
     NgbModule
   ],
   declarations: [
     ListComponent
   ],
   exports : [
     ListComponent
   ]
})
export class ListModule{}

App module importing the components module

@NgModule({
   imports : [
     BrowserModule,
     NgbModule.forRoot()
     ComponentsModule
   ]
})
export class AppModule{}

As far as i know, you will now be able to use the ListComponent inside your AppModule. Because the customer module also exports the ListModule. I think this is a bit counter-intuitive though, and would advice to only import the list module inside the customer module, and export the list module inside the components module.

Upvotes: 2

nameless
nameless

Reputation: 1521

See this answer in another thread, so it seems like it's not possible in Angular 2, as every component are modular pieces and needs it's own imports, because otherwise the modularity would be lost.

You can have detailled instructions on how to use them here as well.

Upvotes: 0

Robba
Robba

Reputation: 8324

The idea behind a module in Angular2 is that it's a standalone reusable module. This does however mean that whatever the module requires must be imported by the module itself.

If the imported modules are inherited, the modules are no longer standalone and thus no longer reusable and you lose most of the benefits of a modular system.

Upvotes: 0

Related Questions