Как правильно импортировать модуль Angular Material через общий модуль в Angular 4?

Я создаю приложение, используя Angular в сочетании с Angular Material, и у меня возникают некоторые проблемы со структурой моих модулей.

Как указано в руководстве, импорт MaterialModule устарел и больше не должен выполняться, поэтому я создал отдельный MaterialModule, в котором я импортирую только те модули материалов, которые мне нужны; затем этот модуль импортируется в SharedModule, который в конечном итоге импортируется везде, где это необходимо, включая основной модуль AppModule.

Одним из компонентов материала, который я использую, является MdTooltip, и все он отлично работает, за исключением случаев, когда я тестирую свое приложение на планшете: происходит то, что всплывающие подсказки не реагируют на длинные нажатия, как должны, и они не открываются. Единственный способ заставить его работать - это импортировать полный MaterialModule (из @ angular / material) в мой AppModule, что ужасно неправильно и неэлегантно. Любой другой подход, похоже, не помогал, поскольку все они приносили свои проблемы, но не решали испытания.

Это мои модули (без лишних операторов импорта):

МатериалМодуль:

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 { }

Я делаю что-то неправильно? Как бы вы разделили свое приложение на подмодули?

заранее спасибо


person Samuele    schedule 26.06.2017    source источник
comment
Я сделал то же самое, что и вы, но получаю StaticInjectorError [ElementRef]: error, все загружено, но компоненты материала angular не работают. ты знаешь почему?   -  person molikh    schedule 06.01.2018


Ответы (4)


В зависимости от вашей стратегии компиляции и развертывания вы захотите использовать встряхивание дерева (для удаления мертвого кода или импорта живого кода). Это основная причина того, что MaterialModule устарел. Официальное предложение - импортировать только необходимые компоненты в модули, которые в этом нуждаются. Ваше решение по созданию единого MaterialModule со всем импортом отменяет этот аспект, но может работать в зависимости от структуры вашего проекта (например, если вы используете только один модуль).

Попробуйте удалить MaterialModule из SharedModule экспорта. Таким образом, у вас будет только одна точка входа для модуля в корне вашего приложения.

person Raven    schedule 26.06.2017
comment
Это был проницательный ответ, но я не смог ответить на свой первоначальный вопрос. Компоненты, объявленные и экспортированные SharedModule, широко используют компоненты Material, что делает импорт моего MaterialModule (или отдельных компонентов, если на то пошло) необходимым; всплывающие подсказки, однако, не работают должным образом. Что заставляет его работать, так это импорт устаревшего MaterialModule в мой AppModule, при этом мой пользовательский MaterialModule импортирован в мой SharedModule. Зачем мне нужно импортировать полный модуль MaterialModule в корень? Это то, что меня беспокоит - person Samuele; 26.06.2017
comment
Возможно, вы захотите проверить установленные версии в node_modules: устаревший MaterialModule не должен вообще ничего делать с последними версиями. Как я вижу, у вас есть два компонента в SharedModule и два в AppModule (рекомендую) поместите их в отдельный модуль). Что делать, если вы не выполняли экспорт из SharedModule и импортировали в свой AppModule определенные компоненты, необходимые для его компонентов (AppComponent, ProductPageComponent)? - person Raven; 26.06.2017
comment
Вы правы в том, что устаревший MaterialModule практически ничего не делает, а является пустым классом. Я пробовал импортировать все отдельные модули, которые мне нужны, в каждый модуль, и все работает, кроме функции касания всплывающей подсказки. По какой-то причине единственный способ заставить его работать - это импортировать устаревший MaterialModule в мой основной AppModule, что бы я ни делал. Если я импортирую его, я получаю сенсорную функцию, если я не импортирую ее, она не работает. Честно говоря, это не имеет для меня особого смысла, может ли это зависеть от того, куда импортируются hammer.js и BrowserModule? - person Samuele; 26.06.2017

Ваш подход великолепен. Представленная вами структура является альтернативой, представленной в material.angular.io. Я не уверен, почему ваша всплывающая подсказка не работает. Но я хотел бы посоветовать вам использовать свой собственный MaterialModule только один раз в корневом модуле. Нет необходимости снова импортировать его в SharedModule.

person alaboudi    schedule 11.10.2017

Ваша первая ошибка - это сервисы в SharedModule. SharedModule не должен иметь массива Providers. CoreModule используется для сервисов.

Вам не нужно импортировать все данные в общий модуль. SharedModule обычно предназначен для экспорта. Также MaterialModule не требует импорта, потому что он не использует их. Его цель - экспорт.

Если NavBarComponent используется в масштабе всего приложения, он должен быть в CoreModule. Нет в SharedModule.

Если в этом нет необходимости, не импортируйте SharedModule в AppModule. SharedModule предназначен для FeaturedModules.

Прочтите официальные документы: https://angular.io/guide/ngmodule-faq#what-kinds-of-modules-should-i-have-and-how-should-i-use-them

person LacOniC    schedule 09.11.2019
comment
И почему у SharedModule не должно быть провайдеров? Что, если я хочу иметь новую услугу для каждой функции? что случилось с этим ? - person CornelC; 18.03.2020
comment
Если у вас есть особая услуга, вы должны поместить ее в этот функциональный модуль. Не в общем модуле. Общий модуль для всех. - person LacOniC; 23.03.2020
comment
Не хотите объяснить свое утверждение? - person CornelC; 24.03.2020

  1. создать общий модуль в src \ app, используя: ng g module shared

  2. импортировать все необходимые модули материалов в общий модуль. важный!!! иногда вы получаете сообщение об ошибке, если пытаетесь импортировать набор модулей вместе. вы должны импортировать их один за другим, как показано ниже = ›

    импортировать {MatButtonModule} из '@ angular / material / button';

    импортировать {MatFormFieldModule} из '@ angular / material / form-field';

    импортировать {MatInputModule} из '@ angular / material / input';

тогда

    @NgModule({
  declarations: [],
  imports: [
    CommonModule,
    MatButtonModule,
    MatFormFieldModule,
    MatInputModule
  ],
  exports: [
    MatButtonModule,
    MatFormFieldModule,
    MatInputModule

  ]
})

теперь вы можете импортировать этот общий модуль везде, где вам нужен один или несколько модулей материалов, которые вы импортировали в общий модуль. например, если вам нужен угловой материал в примере студента = ›

import {SharedModule} from '../shared/shared.module'

а потом

@NgModule({
  declarations: [
    TdFormComponent],
  imports: [
    CommonModule,
    SharedModule,
    
  ]
})
person Ayman Abdal    schedule 18.11.2020