Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to correctly import the Angular Material module through a shared module in Angular 4?

I'm building an application using Angular paired with Angular Material, and I'm having some issues with my modules structure.

As the guidelines suggest, importing the MaterialModule is deprecated and should no longer be done, which is why I've made a separate MaterialModule where I only import the Material modules I need to use; this module is then imported in a SharedModule, which is eventually imported everywhere it's needed, including the main AppModule.

One of the Material components I'm using is the MdTooltip, and it all works fine except for when I test my app on a tablet: what happens is that the tooltips don't react to long taps like they're supposed to, and they won't open. The only way I've managed to make it work is by importing the full MaterialModule (from @angular/material) in my AppModule, which is horrendously wrong and inelegant. Any other approach didn't quite seem to cut it, as they would all bring their own problems while not solving the ordeal.

These are my modules (stripped of redundant import statements):

MaterialModule:

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

@NgModule({
  imports: [
    MdGridListModule,
    MdButtonModule,
    MdTabsModule,
    MdToolbarModule,
    MdCardModule,
    MdInputModule,
    MdSelectModule,
    MdAutocompleteModule,
    MdIconModule,
    MdTooltipModule
  ],
  exports: [
    MdGridListModule,
    MdButtonModule,
    MdTabsModule,
    MdToolbarModule,
    MdCardModule,
    MdInputModule,
    MdSelectModule,
    MdAutocompleteModule,
    MdIconModule,
    MdTooltipModule
  ],
  providers: [
    MdIconRegistry
  ]
})

export class MaterialModule {}

SharedModule:

import { MaterialModule } from '../material/app-material.module';
@NgModule({
  imports:      [
    CommonModule,
    MaterialModule,
    FlexLayoutModule,
    FormsModule,
    ReactiveFormsModule
  ],
  declarations: [
    NavbarComponent,
    SearchFiltersComponent,
    RightCurrencyPipe
  ],
  exports:      [
    CommonModule,
    FormsModule,
    ReactiveFormsModule,
    MaterialModule,
    FlexLayoutModule,
    NavbarComponent,
    RightCurrencyPipe,
    SearchFiltersComponent
  ],
  providers: [
    SpinnerService,
    ProductsService,
    StatePersistenceService
  ]
})

export class SharedModule {}

AppModule:

import { MaterialModule } from "@angular/material";
@NgModule({
  declarations: [
    AppComponent,
    ProductPageComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    RouterModule,
    BrowserAnimationsModule,
    AppRoutingModule,
    SharedModule,
    CoreModule,
    LoginModule,
    MaterialModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Am I doing something wrong? How would you go about dividing your app into submodules?

Thanks in advance

like image 739
Samuele Avatar asked Jun 26 '17 08:06

Samuele


People also ask

Where should you import a shared module Angular?

Add the SharedModule in the imports section of the AppModule .


2 Answers

Depending on your compiling and deployment strategy you'll want to use tree shaking (for dead-code elimination or live-code import). This is the main motivation for MaterialModule being deprecated. The official suggestion is to only import the components you need in the modules that need it. Your solution of creating a single MaterialModule with all the imports is undoing that aspect but might work depending on your project structure (if you're only using a single module for example).

Try removing MaterialModule from your SharedModule exports. That way you only have a single point of entry for the module in your app root.

like image 170
Raven Avatar answered Oct 01 '22 14:10

Raven


Your approach is great. The structure that you have presented is an alternative that was presented in material.angular.io. I am unsure to why your tooltip does not work. But I would like to advise you to only use your custom MaterialModule only once on the root module. There is no need to import it in the SharedModule again.

like image 36
alaboudi Avatar answered Oct 01 '22 15:10

alaboudi