无法使用角形式

时间:2017-09-01 09:18:32

标签: angular angular-material2

我正在尝试使用角度形式的角度素材2 datepicker,我收到此错误:

vendor.bundle.js:92803 ERROR TypeError: Cannot read property 'invalid' of undefined
    at MdInput.defaultErrorStateMatcher [as errorStateMatcher] (vendor.bundle.js:121344)
    at MdInput.webpackJsonp.../../../material/@angular/material.es5.js.MdInput._updateErrorState (vendor.bundle.js:131778)
    at MdInput.webpackJsonp.../../../material/@angular/material.es5.js.MdInput.ngDoCheck (vendor.bundle.js:131739)
    at checkAndUpdateDirectiveInline (vendor.bundle.js:102634)
    at checkAndUpdateNodeInline (vendor.bundle.js:104132)
    at checkAndUpdateNode (vendor.bundle.js:104071)
    at prodCheckAndUpdateNode (vendor.bundle.js:104765)
    at Object.View_FormComponent_0._co [as updateDirectives] (ng:///AppModule/FormComponent.ngfactory.js:2337)
    at Object.updateDirectives (vendor.bundle.js:104522)
    at checkAndUpdateView (vendor.bundle.js:104038)

以下是我的组成部分的代码:

import {Component, OnInit, Output, Input, EventEmitter} from "@angular/core";
import {FormControl, Validators, FormGroup} from "@angular/forms";
import {ReferentialService} from "../shared/referential.service";

@Component({
  selector: 'app-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.css']
})
export class FormComponent implements OnInit {

  private form: FormGroup;
  @Input() model: any;
  isValidationMode: boolean;

  @Output('cancel') cancel$: EventEmitter<any>;
  @Output('submit') submit$: EventEmitter<any>;


  // select lists
  languages: any;
  types: any;
  subtypes: any;
  entities: any;
  managements: any;
  countries: any;
  services: any;

  constructor(private _referentialService: ReferentialService) {
    this.submit$ = new EventEmitter();
    this.cancel$ = new EventEmitter();
    this.model = {};
    this.form = this._buildForm();
  }

  ngOnInit() {
    this.initSelectLists();
  }

  /**
   * Function to handle component update
   *
   * @param record
   */
  ngOnChanges(record) {
    if (record.model && record.model.currentValue) {
      this.model = record.model.currentValue;
      this.isValidationMode = !!this.model;
      this.form.patchValue(this.model);
    }
  }

  /**
   * Function to init select list
   */
  initSelectLists() {
    this._referentialService.getCountries().subscribe((countries: any[]) => this.countries = countries);
    this._referentialService.getLanguages().subscribe((languages: any[]) => this.languages = languages);
    this._referentialService.getTypes().subscribe((types: any[]) => this.types = types);
    this._referentialService.getSubTypes().subscribe((subtypes: any[]) => this.subtypes = subtypes);
    this._referentialService.getEntities().subscribe((entities: any[]) => this.entities = entities);
    this._referentialService.getServices().subscribe((services: any[]) => this.services = services);
    this._referentialService.getManagements().subscribe((managements: any[]) => this.managements = managements);
  }

  /**
   * Function to emit event to cancel process
   */
  cancel() {
    this.cancel$.emit();
  }

  /**
   * Function to emit event to submit form and person
   */
  submit(doc: any) {
    this.submit$.emit(doc);
  }

  /**
   * Function to build our form
   *
   * @returns {FormGroup}
   *
   * @private
   */
  private _buildForm(): FormGroup {
    return new FormGroup({
      file: new FormControl('', Validators.compose([])),
      documentid: new FormControl('', Validators.compose([Validators.required])),
      title: new FormControl('', Validators.compose([Validators.required])),
      name: new FormControl('', Validators.compose([Validators.required])),
      format: new FormControl('', Validators.compose([Validators.required])),
      summary: new FormControl('', Validators.compose([Validators.required])),
      mnesysid: new FormControl('', Validators.compose([Validators.required])),
      entity: new FormControl('', Validators.compose([Validators.required])),
      management: new FormControl('', Validators.compose([])),
      service: new FormControl('', Validators.compose([])),
      creationDate: new FormControl(null, Validators.compose([])),
      sendDate: new FormControl({
        value: this.model.creationDate
      }, Validators.compose([Validators.required])),
      type: new FormControl('', Validators.compose([Validators.required])),
      subtype: new FormControl('', Validators.compose([])),
      archivist: new FormControl({
        value: this.model.archivist,
        disabled: true
      }, Validators.compose([Validators.required])),
      firstname: new FormControl({value: this.model.name, disabled: true}, Validators.compose([Validators.required])),
      lastname: new FormControl({
        value: this.model.firstname,
        disabled: true
      }, Validators.compose([Validators.required])),
      beneficiary: new FormControl('', Validators.compose([])),
      depositid: new FormControl('', Validators.compose([])),
      filepath: new FormControl('', Validators.compose([])),
      isprivate: new FormControl('', Validators.compose([])),
      language: new FormControl('', Validators.compose([Validators.required])),
      country: new FormControl('', Validators.compose([])),
      publicyear: new FormControl(null, Validators.compose([])),
      version: new FormControl('', Validators.compose([])),
      status: new FormControl('', Validators.compose([])),
      comment: new FormControl('', Validators.compose([Validators.required]))
    });
  }
}

这是我的HTML代码

<md-card>

  <md-card-title>
    <span *ngIf="isValidationMode" style="color:  #00965E !important;">Validation du document</span>
    <span *ngIf="!isValidationMode" style="color:  #00965E !important;">Soumission de document</span>
  </md-card-title>

  <md-card-content>
    <form novalidate [formGroup]="form">
      <h5 style="margin-bottom: -5px">Personne déposant le fichier</h5>
      <table>
        <tr>
          <td>
            <p [class.errors]="form.controls.archivist.touched && form.controls.archivist.invalid">
              <md-input-container>
                <input mdInput placeholder="Identifiant" formControlName="archivist">
                <span *ngIf="form.controls.archivist.touched && form.controls.archivist.errors?.required">
              <br>L'identifiant de l'archivist est obligatoire</span>
              </md-input-container>
            </p>
          </td>
          <td>
            <p [class.errors]="form.controls.lastname.touched && form.controls.lastname.invalid">
              <md-input-container>
                <input mdInput placeholder="Nom" formControlName="lastname">
                <span *ngIf="form.controls.lastname.touched && form.controls.lastname.errors?.required">
              <br>le nom est obligatoire</span>
              </md-input-container>
            </p>
          </td>
          <td>
            <p [class.errors]="form.controls.firstname.touched && form.controls.firstname.invalid">
              <md-input-container>
                <input mdInput placeholder="Prenom" formControlName="firstname">
                <span *ngIf="form.controls.firstname.touched && form.controls.firstname.errors?.required">
              <br>le prénom est obligatoire</span>
              </md-input-container>
            </p>
          </td>
          <td>
            <md-input-container>
              <input mdInput formControlName="beneficiary" placeholder="Pour le compte de">
            </md-input-container>
          </td>
        </tr>
      </table>
      <h5 class="sub-title">Identification du document</h5>
      <table>
      </table>
      <table>
        <tr>
          <td>
            <input type="file" (change)="fileChange($event)" formControlName="file" placeholder="Upload file"
                   accept=".pdf,.doc,.docx">
          </td>
          <td>
            <p [class.errors]="form.controls.title.touched && form.controls.title.invalid">
              <md-input-container>
                <input mdInput placeholder="Titre" formControlName="title">
                <span *ngIf="form.controls.title.touched && form.controls.title.errors?.required">
              <br>le titre est obligatoire</span>
              </md-input-container>
            </p>
          </td>
          <td>
            <p [class.errors]="form.controls.format.touched && form.controls.format.invalid">
              <md-input-container>
                <input mdInput placeholder="Format" formControlName="format">
                <span *ngIf="form.controls.format.touched && form.controls.format.errors?.required">
              <br>le format est obligatoire</span>
              </md-input-container>
            </p>
          </td>
          <td>
            <p [class.errors]="form.controls.documentid.touched && form.controls.documentid.invalid">
              <md-input-container>
                <input mdInput placeholder="Identifiant" formControlName="documentid">
                <span *ngIf="form.controls.documentid.touched && form.controls.documentid.errors?.required">
              <br>l'identifiant est obligatoire</span>
              </md-input-container>
            </p>
          </td>
          <td>
            <p [class.errors]="form.controls.mnesysid.touched && form.controls.mnesysid.invalid">
              <md-input-container>
                <input mdInput placeholder="Cote" formControlName="mnesysid">
                <span *ngIf="form.controls.mnesysid.touched && form.controls.mnesysid.errors?.required">
                <br>la cote est obligatoire</span>
              </md-input-container>
            </p>
          </td>
        </tr>
      </table>
      <h5 class="sub-title">Description du document</h5>
      <table>
        <tr>
          <td>
            <p [class.errors]="form.controls.name.touched && form.controls.name.invalid">
              <md-input-container>
                <input mdInput placeholder="Nom" formControlName="name">
                <span *ngIf="form.controls.name.touched && form.controls.name.errors?.required">
              <br>Le nom est obligatoire</span>
              </md-input-container>
            </p>
          </td>
          <td>
            <md-input-container><input mdInput placeholder="Version" formControlName="version"></md-input-container>
          </td>
          <td>
            <p [class.errors]="form.controls.language.touched && form.controls.language.invalid">
              <md-select placeholder="Langue" formControlName="language">
                <md-option>None</md-option>
                <md-option *ngFor="let language of languages" [value]="language.languageCode">{{ language.frenchLabel
                  }}
                </md-option>
              </md-select>
              <span *ngIf="form.controls.language.touched && form.controls.language.errors?.required">
              <br><br>La langue est obligatoire</span>
            </p>
          </td>
          <td>
            <md-select placeholder="Pays" formControlName="country">
              <md-option>None</md-option>
              <md-option *ngFor="let country of countries" [value]="country.countryCode">{{ country.frenchLabel }}
              </md-option>
            </md-select>
          </td>
        </tr>
      </table>
      <table>
        <tr>
          <td>
            <p [class.errors]="form.controls.summary.touched && form.controls.summary.invalid">
              <md-input-container>
                <textarea mdInput placeholder="Résumé" formControlName="summary"
                          class="text-area"></textarea>
                <span *ngIf="form.controls.summary.touched && form.controls.summary.errors?.required">
              <br>Le résumé est obligatoire</span>
              </md-input-container>
            </p>
          </td>
        </tr>
      </table>
      <table>
        <tr>
          <td>
            <p [class.errors]="form.controls.type.touched && form.controls.type.invalid">
              <md-select placeholder="Type" formControlName="type">
                <md-option>None</md-option>
                <md-option *ngFor="let type of types" [value]="type.typeCode">{{ type.frenchLabel }}</md-option>
              </md-select>
              <span *ngIf="form.controls.type.touched && form.controls.type.errors?.required">
              <br><br>Le type est obligatoire</span>
            </p>
          </td>
          <td>
            <md-select placeholder="Sous type" formControlName="subtype">
              <md-option>None</md-option>
              <md-option *ngFor="let subtype of subtypes" [value]="subtype.subtypeCode">{{ subtype.frenchLabel }}
              </md-option>
            </md-select>
          </td>
          <td>
            <p [class.errors]="form.controls.entity.touched && form.controls.entity.invalid">
              <md-select placeholder="Entité" formControlName="entity">
                <md-option>None</md-option>
                <md-option *ngFor="let entity of entities" [value]="entity.entityCode">{{ entity.frenchLabel }}
                </md-option>
              </md-select>
              <span *ngIf="form.controls.entity.touched && form.controls.entity.errors?.required">
              <br><br>L'entité est obligatoire</span>
            </p>
          </td>
          <td>
            <md-select placeholder="Direction" formControlName="management">
              <md-option>None</md-option>
              <md-option *ngFor="let management of managements" [value]="management.managementCode">{{
                management.frenchLabel }}
              </md-option>
            </md-select>
          </td>
          <td>
            <md-select placeholder="Métier/Service" formControlName="service">
              <md-option>None</md-option>
              <md-option *ngFor="let service of services" [value]="service.serviceCode">{{ service.frenchLabel }}
              </md-option>
            </md-select>
          </td>
        </tr>
      </table>
      <h5 style="margin-top: 5px;margin-bottom: -5px">Création du document</h5>
      <table>
        <tr>
          <td style="padding-right: 40px;">
            <md-radio-group formControlName="isprivate" required>
              <md-radio-button value="false" color="primary">Public</md-radio-button>
              <md-radio-button value="true" color="primary" [checked]="isprivate">Privé</md-radio-button>
            </md-radio-group>
          </td>
          <td>
            <md-form-field>
              <input mdInput [mdDatepicker]="creationDatePicker" placeholder="Date de création"
                     formControlName="creationDate">
              <md-datepicker-toggle mdSuffix [for]="creationDatePicker"></md-datepicker-toggle>
              <md-datepicker #creationDatePicker></md-datepicker>
            </md-form-field>
          </td>
          <!--<td>-->
            <!--<md-form-field>-->
              <!--<input mdInput [mdDatepicker]="sendDatePicker" placeholder="Date d'envoi" formControlName="sendDate">-->
              <!--<md-datepicker-toggle mdSuffix [for]="sendDatePicker"></md-datepicker-toggle>-->
              <!--<md-datepicker #sendDatePicker></md-datepicker>-->
            <!--</md-form-field>-->
          <!--</td>-->
          <!--<td>-->
            <!--<md-form-field>-->
              <!--<input mdInput [mdDatepicker]="publicationDatePicker" placeholder="Date de passage en public"-->
                     <!--formControlName="publicyear">-->
              <!--<md-datepicker-toggle mdSuffix [for]="publicationDatePicker"></md-datepicker-toggle>-->
              <!--<md-datepicker #publicationDatePicker></md-datepicker>-->
            <!--</md-form-field>-->
          <!--</td>-->
        </tr>
      </table>
      <table>
        <tr>
          <td>
            <p *ngIf="isValidationMode" [class.errors]="form.controls.comment.touched && form.controls.comment.invalid">
              <md-input-container>
                <textarea mdInput placeholder="Commentaire" formControlName="comment"
                          class="text-area"></textarea>
                <span *ngIf="form.controls.summary.touched && form.controls.comment.errors?.required">
              <br>Le commentaire est obligatoire</span>
              </md-input-container>
            </p>
          </td>
        </tr>
      </table>
    </form>
  </md-card-content>

  <md-card-actions align="end">
    <div *ngIf="isValidationMode">
      <button md-button align [hidden]="!isValidationMode">Refuser</button>
    </div>
    <div>
      <button md-button type="button" (click)="cancel()">Annuler</button>
    </div>
    <div>
      <button md-button color="primary" type="submit" (click)="submit(form.value)" >
        <span *ngIf="!isValidationMode">Soumettre</span>
        <span *ngIf="isValidationMode">Valider</span>
      </button>
    </div>
  </md-card-actions>

</md-card>

我尝试从我的模型绑定的日期格式为“2017-06-20T12:00:00.000Z”

你能帮帮我吗? 是否需要设置dateAdapter?

1 个答案:

答案 0 :(得分:6)

您的错误:

TypeError: Cannot read property 'invalid' of undefined

实际上是由此异常引起的:

Datepicker: value not recognized as a date object by DateAdapter.

这意味着您在模型中使用的日期格式"2017-06-20T12:00:00.000Z"不是有效的Date实例。请参阅源代码中的this line

所以你应该使用Date这样的实例:

return new FormGroup({
  creationDate: new FormControl(new Date(2017, 6, 20)),
})

或在您的模型中:

model.creationDate = new Date(2017, 6, 20);

另外,如documentations中所述:

  

请注意:MdNativeDateModule基于该功能   在JavaScript的本机Date对象中可用,因此不适用   对于许多语言环境。原生日期的最大缺点之一   object是无法设置解析格式。我们强烈推荐   使用适用于格式化/解析的自定义DateAdapter   您选择的图书馆。

您不应该依赖NativeDateAdapter,因为它使用本机JavaScript Date对象,这在解析复杂日期格式时非常有限。为此,您可以使用令人敬畏的Moment.js库。