角材料表单不起作用-垫形字段必须包含MatFormFieldControl

时间:2020-08-14 09:01:47

标签: angular typescript angular-material

我正在尝试创建一个简单的应用程序来管理我们的流媒体设备的配置。但是尽管一切正常,我还是无法正常工作-导入的模块,标记指令...这是我的第一个有角度的应用程序,它是根据文档(所有内容的最新版本)生成的。

在.ts文件中,我从服务器获取带有设置的json(为简单起见,我仅使用其中的一部分)。我用FormBuilder构建FormGroup并用值填充它。当我记录它时,它看起来不错-FormGroups / FormControls应该在它们应该在的地方,值还可以。但是,当我尝试将其显示在模板中时,它失败并显示错误。通过添加指令或导入模块解决了类似的问题,但正如我所说,我应该拥有所需的一切。谢谢您的回应,我现在很沮丧...

编辑:抱歉,我忘了包含从服务器获取的数据-我在构造函数https://stackblitz.com/edit/angular-gdkrdr?file=app/app.component.ts中伪造了数据

模板

<p>streamer-configuration works!</p>

<div>
  <form *ngIf="config" [formGroup]="configForm" (ngSubmit)="onSubmit(configForm)">
    <b>Conference:</b>
    <mat-form-field appearance="standard">
      <mat-label>Enabled</mat-label>
      <input matInput formControlName="enabled" value="{{ config["enabled"] }}" required />
    </mat-form-field>
    <mat-form-field appearance="standard">
      <mat-label>Auto answer</mat-label>
      <input matInput formControlName="auto_answer" value="{{ config["auto_answer"] }}" required />
    </mat-form-field>
    <mat-form-field appearance="standard">
      <mat-label>Port</mat-label>
      <input matInput formControlName="port" value="{{ config["port"] }}" required />
    </mat-form-field>
    <div formGroupName="technology">
      <mat-form-field appearance="standard">
        <mat-label>Selected technology</mat-label>
        <input matInput formControlName="selected" value="{{ config["technology"]["selected"] }}" required />
      </mat-form-field>
    </div>
    <button mat-raised-button color="primary" type="submit">Submit</button>
  </form>
</div>

ts文件

import { Component, OnInit, createPlatformFactory } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { FormBuilder } from '@angular/forms';
import { ConstantsService } from '../common/services/constants.service';

@Component({
  selector: 'app-streamer-configuration',
  templateUrl: './streamer-configuration.component.html',
  styleUrls: ['./streamer-configuration.component.scss']
})
export class StreamerConfigurationComponent implements OnInit {
  private apiURL: string;
  config: Object;
  configForm: Object;

  constructor(private http: HttpClient, private formBuilder: FormBuilder, private _constant: ConstantsService) {
    this.apiURL = `${this._constant.baseApiUrl}/xxx`;
    this.getData();
  }

  ngOnInit(): void {
  }

  private getData() {
    return this.http.get(this.apiURL).subscribe(config => {
      console.log(config);
      this.config = config["Conference"];
      this.createConfigForm();
    });
  }

  private createConfigForm(obj = this.config) {
    this.configForm = this.formBuilder.group({
      enabled: [obj["enabled"]],
      auto_answer: [obj["auto_answer"]],
      technology: this.formBuilder.group({
        selected: [obj["technology"]["selected"]]
      }),
      port: [obj["port"]]
    })
    console.log(this.configForm);
  }

  onSubmit(data) {
    console.log(data);
  }
}

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 { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { ConfigSectionsComponent } from './config-sections/config-sections.component';
import { LayoutModule } from '@angular/cdk/layout';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatButtonModule } from '@angular/material/button';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatIconModule } from '@angular/material/icon';
import { MatListModule } from '@angular/material/list';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input'; // <-----------
import { FormsModule, ReactiveFormsModule  } from '@angular/forms';

import { StreamerConfigurationComponent } from './streamer-configuration/streamer-configuration.component';
import { ManifestConfigurationComponent } from './manifest-configuration/manifest-configuration.component';
import { NetworkCamerasComponent } from './network-cameras/network-cameras.component';
import { CamerasIconsComponent } from './cameras-icons/cameras-icons.component';

import { ConstantsService } from './common/services/constants.service';

import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent,
    ConfigSectionsComponent,
    StreamerConfigurationComponent,
    ManifestConfigurationComponent,
    NetworkCamerasComponent,
    CamerasIconsComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    HttpClientModule,
    LayoutModule,
    MatToolbarModule,
    FormsModule,
    MatButtonModule,
    MatSidenavModule,
    MatIconModule,
    MatListModule,
    MatFormFieldModule,
    MatInputModule, // <----------
    ReactiveFormsModule,
  ],
  providers: [ConstantsService],
  bootstrap: [AppComponent]
})
export class AppModule { }

1 个答案:

答案 0 :(得分:2)

Liniik,三个音符

1.-如果使用插值,请在双引号之间使用单引号

//WRONG
value="{{ config["technology"]["selected"] }}"

//OK
value="{{ config['technology']['selected'] }}"
//OR
value="{{config.technology.selected}}"
//OR
[value]="config.technology.selected"

2.-如果您使用反应性表单,而不使用“值”,则只需将值赋予formControl

//WRONG
<input matInput formControlName="port" value="{{ config['port'] }}" required />

//OK
<input matInput formControlName="port"  required />

3.-在提交功能中,您通过表单,因此,您的提交必须像

  onSubmit(formGroup:FormGroup) {
    if (formGroup.valid)
      console.log(formGroup.value); //<--see how get the "data"
    }
  }