2

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)?

Poul Kruijt
  • 69,713
  • 12
  • 145
  • 149
brabertaser19
  • 5,678
  • 16
  • 78
  • 184
  • If you only use the `NgbModule` inside your `ListModule` then you should only need to import it there. You got that right :) Maybe a long shot, but could the extra space in the `` be the problem? – Poul Kruijt Dec 16 '16 at 09:06
  • @PierreDuc seems that it doesn't help( – brabertaser19 Dec 16 '16 at 09:24

3 Answers3

2

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.

Poul Kruijt
  • 69,713
  • 12
  • 145
  • 149
  • Why do you declare ListComponent inside CustomerModule? If you want to use the ListComponent, you should import ListModule inside your CustomerModule. I believe this is where your problem is. I've updated my answer – Poul Kruijt Dec 16 '16 at 09:35
  • good) why i'm using nesting: for me in angular 1.4 it was much easier and obvious to have for example: components/cards/list/item, neither separate them on one level... – brabertaser19 Dec 16 '16 at 10:48
  • How would you organize such structure? for example i have customer screen, with customers list or customer details (with some shared styles, like panel), list & customer have their own route path. Is my schema suitable for this, or not? – brabertaser19 Dec 16 '16 at 11:08
  • Customer would be a module which include the customer list and customer detauls. Your components module would export components to make a list and perhaps even a detail screen. Your customer module imports this components module to build the detail and list screen. Your appmodule imports the customer module. But this only applies if your componentsmodule is going to behave like a commons module, otherwise i see now use for the components module – Poul Kruijt Dec 16 '16 at 11:16
0

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.

Community
  • 1
  • 1
nameless
  • 1,483
  • 5
  • 32
  • 78
  • yes, ok every module is importing dependencies. but why if i use ngbModule in list module, i need to import it in customer, components etc? – brabertaser19 Dec 16 '16 at 08:59
  • 1
    You need to import it in every module you use, because there is not anything like a "parent" module or something, every module has his own dependencies and therefore needs its own imports. – nameless Dec 16 '16 at 09:01
  • check my question... so is it true, that i need to import ngbModule everywhere (components, customer) even if i didn't use it in app view? i use only list module in app view – brabertaser19 Dec 16 '16 at 09:11
0

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.

Robba
  • 7,684
  • 12
  • 48
  • 76
  • yes, ok every module is importing dependencies. but why if i use ngbModule in list module, i need to import it in customer, components etc? – brabertaser19 Dec 16 '16 at 09:00
  • You should only need to import it into any module that declares Components, Pipes, Directives, etc that use something from the imported module. – Robba Dec 16 '16 at 09:02
  • check my question... so is it true, that i need to import ngbModule everywhere (components, customer) even if i didn't use it in app view? i use only list module in app view – brabertaser19 Dec 16 '16 at 09:11
  • You only import it in the actual module that defines the Component that uses it. In your example you use it in the `list.component.html`. It's not clear what Component that template belongs to, nor what Module that component is defined in. But assuming that this template is used by a ListComponent that is defined in the ListModule, then you'd only need to add the ngbModule to the imports of the ListModule – Robba Dec 16 '16 at 09:24