首页 > 解决方案 > 未捕获的 ReferenceError:在初始化之前无法访问“MaterialModule”

问题描述

我正在为个人项目制作一个简单的表格,并尝试使用以下示例放置电话表格:https://material.angular,.io/components/form-field/examples之后适合所有内容,它给了我这个错误尽管删除与电话表单相关的所有内容保持不变。

在此处输入图像描述

form.component.ts

import { Component, OnInit } from '@angular/core';
import { Builder } from 'protractor';
import {FocusMonitor} from '@angular/cdk/a11y';
import {coerceBooleanProperty} from '@angular/cdk/coercion';
import {ElementRef, Input, OnDestroy, Optional, Self} from '@angular/core';
import {FormBuilder, FormGroup, ControlValueAccessor, NgControl} from '@angular/forms';
import {MatFormFieldControl} from '@angular/material';
import {Subject} from 'rxjs';

@Component({
  selector: 'app-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.scss'],
  providers: [{provide: MatFormFieldControl, useExisting: MyTelInput}],
  host: {
    '[class.example-floating]': 'shouldLabelFloat',
    '[id]': 'id',
    '[attr.aria-describedby]': 'describedBy',
  }
})

export class MyTelInput implements ControlValueAccessor, MatFormFieldControl<MyTel>, OnDestroy {
  static nextId = 0;

  parts: FormGroup;
  stateChanges = new Subject<void>();
  focused = false;
  errorState = false;
  controlType = 'example-tel-input';
  id = `example-tel-input-${MyTelInput.nextId++}`;
  describedBy = '';
  onChange = (_: any) => {};
  onTouched = () => {};

  get empty() {
    const {value: {area, exchange, subscriber}} = this.parts;

    return !area && !exchange && !subscriber;
  }

  get shouldLabelFloat() { return this.focused || !this.empty; }

  @Input()
  get placeholder(): string { return this._placeholder; }
  set placeholder(value: string) {
    this._placeholder = value;
    this.stateChanges.next();
  }
  private _placeholder: string;

  @Input()
  get required(): boolean { return this._required; }
  set required(value: boolean) {
    this._required = coerceBooleanProperty(value);
    this.stateChanges.next();
  }
  private _required = false;

  @Input()
  get disabled(): boolean { return this._disabled; }
  set disabled(value: boolean) {
    this._disabled = coerceBooleanProperty(value);
    this._disabled ? this.parts.disable() : this.parts.enable();
    this.stateChanges.next();
  }
  private _disabled = false;

  @Input()
  get value(): MyTel | null {
    const {value: {area, exchange, subscriber}} = this.parts;
    if (area.length === 3 && exchange.length === 3 && subscriber.length === 4) {
      return new MyTel(area, exchange, subscriber);
    }
    return null;
  }
  set value(tel: MyTel | null) {
    const {area, exchange, subscriber} = tel || new MyTel('', '', '');
    this.parts.setValue({area, exchange, subscriber});
    this.stateChanges.next();
  }

  constructor(
    formBuilder: FormBuilder,
    private _focusMonitor: FocusMonitor,
    private _elementRef: ElementRef<HTMLElement>,
    @Optional() @Self() public ngControl: NgControl) {

    this.parts = formBuilder.group({
      area: '',
      exchange: '',
      subscriber: '',
    });

    _focusMonitor.monitor(_elementRef, true).subscribe(origin => {
      if (this.focused && !origin) {
        this.onTouched();
      }
      this.focused = !!origin;
      this.stateChanges.next();
    });

    if (this.ngControl != null) {
      this.ngControl.valueAccessor = this;
    }
  }

  ngOnDestroy() {
    this.stateChanges.complete();
    this._focusMonitor.stopMonitoring(this._elementRef);
  }

  setDescribedByIds(ids: string[]) {
    this.describedBy = ids.join(' ');
  }

  onContainerClick(event: MouseEvent) {
    if ((event.target as Element).tagName.toLowerCase() != 'input') {
      this._elementRef.nativeElement.querySelector('input')!.focus();
    }
  }

  writeValue(tel: MyTel | null): void {
    this.value = tel;
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  setDisabledState(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }

  _handleInput(): void {
    this.onChange(this.parts.value);
  }
}
export class MyTel {
  constructor(public area: string, public exchange: string, public subscriber: string) {}
}

export class FormComponent implements OnInit {

  public formGroup: FormGroup;

  constructor(private formBuilder: FormBuilder) { }

  ngOnInit() {
    this.formGroup = this.formBuilder.group({
      name: '',
      lastname: '',
      option: '',
      checkbox: '',
      masculino: '',
      femenino: '',
      email:'',
    });
  }

}

form.module.ts

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

import { FormRoutingModule } from './form-routing.module';
import { FormComponent } from './form/form.component';
import { MaterialModule } from '../material/material.module';
import { FormBuilder } from '@angular/forms';



@NgModule({
  declarations: [FormComponent],
  imports: [
    CommonModule,
    FormRoutingModule, 
    MaterialModule
  ],
  providers: [
    FormBuilder
  ]
})
export class FormModule { }

材料.module.ts

import { NgModule } from '@angular/core';
import { 
  MatTableModule, 
  MatPaginatorModule, 
  MatFormFieldModule, 
  MatSelectModule, 
  MatInputModule, 
  MatCheckboxModule, 
  MatRadioModule} from '@angular/material';
import { ReactiveFormsModule } from '@angular/forms';
import { FormModule } from '../form/form.module';
import { FormComponent } from '../form/form/form.component';

const materialModules = [
  MatTableModule,
  MatPaginatorModule,
  MatFormFieldModule,
  ReactiveFormsModule,
  MatSelectModule,
  MatInputModule,
  MatRadioModule,
  FormModule, 
  FormComponent,
  MatCheckboxModule,
];

@NgModule({
  exports: materialModules,
  imports: materialModules
})
export class MaterialModule { }

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MaterialModule } from './modules/material/material.module';
import { MatSelectModule, MatInputModule, MatCheckbox, MatRadioModule } from '@angular/material';
import { MatFormFieldModule } from '@angular/material/form-field';
import { FormModule } from './modules/form/form.module';
import { FormComponent } from './modules/form/form/form.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    NoopAnimationsModule,
    MaterialModule,
    MatSelectModule,
    MatInputModule,
    MatFormFieldModule,
    MatRadioModule,
    FormModule,
    FormComponent
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

表单路由.component.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { FormComponent } from './form/form.component';


const routes: Routes = [{path: '', component: FormComponent}];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class FormRoutingModule { }

请帮忙

标签: htmlangulartypescript

解决方案


您在这里有两个主要错误:

  1. 将组件导入模块。做不到,只能导入模块。可以声明和导出组件。这导致您看到的错误。

  2. 通过将 FormModule 导入 MaterialModule 来导入循环模块,反之亦然。做不到。进口只能是一个方向。这导致您看到的警告实际上是阻止您重新编译的错误。

还有一些小错误,比如你混淆了模块逻辑和双重导入模块

下面修复....

材料模块,让它做它应该做的,导入和导出材料模块,NOTHING ELSE,移除反应表单导入,移除对 FormsModule 的循环引用,移除表单组件导入:

import { NgModule } from '@angular/core';
import { 
  MatTableModule, 
  MatPaginatorModule, 
  MatFormFieldModule, 
  MatSelectModule, 
  MatInputModule, 
  MatCheckboxModule, 
  MatRadioModule} from '@angular/material';

const materialModules = [
  MatTableModule,
  MatPaginatorModule,
  MatFormFieldModule,
  MatSelectModule,
  MatInputModule,
  MatRadioModule,
  MatCheckboxModule,
];

@NgModule({
  exports: materialModules,
  imports: materialModules
})
export class MaterialModule { }

表单模块,在此处导入响应式表单模块(不提供表单构建器),导出表单组件以在其他模块中使用它:

@NgModule({
  declarations: [FormComponent],
  imports: [
    CommonModule, // if you have a common module, you could import / export the reactive forms module there if it's more appropriate and then you don't need to import it again here.
    FormRoutingModule, 
    MaterialModule,
    ReactiveFormsModule // do this here, don't provide the form builder
  ],
  exports: [
    FormComponent // if you want to use this component in other modules, export here and import the MODULE
  ]
})
export class FormModule { }

app 模块,不要尝试导入表单组件,只需导入模块即可。不要重新导入材料模块,您可以在材料模块中执行此操作:

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    NoopAnimationsModule,
    MaterialModule, // do you really NEED the material module here?
    FormModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

推荐阅读