16

I made an Angular2 app like described here. It has two components (A,B) which are imported by the global app.module. My idea was, to include shared modules in app.module, so I don't need to mess up every module with redundant code. I want to do that for example with the FormsModule. So in the app.module I have

imports: [
    UniversalModule,
    CommonModule,
    FormsModule,
    AModule
    RouterModule.forRoot([])
],

exports: [FormsModule]

But in the A module I got the exception Can't bind to 'ngModel' since it isn't a known property of 'select'. which seems caused by the missing FormsModule. It only works, when I import the FormsModulein every child module too using imports: [FormsModule]. That's exactly what I want to avoid.

According to this question, I tried to import the AppModule in the child module A. This doesn't work and give me the exception Exception: Call to Node module failed with error: Error: Unexpected value 'undefined' imported by the module 'AModule'

How can I inherit the imports to child modules? I need this for pipes, too.

Community
  • 1
  • 1
Lion
  • 11,498
  • 13
  • 55
  • 113

2 Answers2

9

Just create a feature module (or shared module) that exports the components, directives, and pipes, that are usually used together and import this module to modules where you want to use any of these.

There is no way to make components, directives, or pipes available globally. They need to be added to imports of every module where they are used. All you can do is combine modules and make them available by importing only a single or few modules.

Günter Zöchbauer
  • 490,478
  • 163
  • 1,733
  • 1,404
  • You can import any module you want into another module except parent modules. That is *very* weird. I don't think using child modules is a good idea at all. It makes me want to flatten everything and avoid using child modules altogether so I can just import whatever I need. – Jens Oct 09 '18 at 21:22
8

Seems that this can only be done using a shared module, which collects the shared imports, like @Günter Zöchbauer said. I found an example in the official docs, which I used as a base to create my shared module for doing this:

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

import { ObjectKeysPipe } from './../shared/pipes/object-keys.pipe';

@NgModule({
    imports: [CommonModule],
    declarations: [
        ObjectKeysPipe
    ],
    exports: [
        CommonModule,
        FormsModule,
        ObjectKeysPipe
    ]
})
export class GlobalSharedModule{}

This shares a custom pipe from me (ObjectKeysPipe) and both widely used CommonModule and FormModule. The idea of reducing redudant mess worked. In my application modules, I don't need to add a bunch of imports/declarations. Instead, I only need to import my shared module like this:

import { GlobalSharedModule } from './../shared/global-shared.module';
@ngModule({
    imports: GlobalSharedModule
})
Lion
  • 11,498
  • 13
  • 55
  • 113
  • 1
    One goal is to NOT use chains upon chains of `./../../../../../` to import modules. Any way to do that? – Douglas Gaskell Nov 23 '17 at 23:06
  • 5
    @DouglasGaskell In your `tsconfig.json` under `compilerOptions` and then `paths` you may declare a path like `"store": ["src/store.ts"]`. See [link](https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping) – Bjørn Lindner Jan 17 '18 at 15:53