【问题标题】:Angular 6: Date undefinedAngular 6:日期未定义
【发布时间】:2018-12-15 11:01:39
【问题描述】:

我有一个表单,要求用户选择日期并输入电子邮件、城市和酒店,并且用户必须能够提交数据。

这是我所拥有的:

about.component.html(表单):

<div class="container about-booking-input">
  <div class="row about-title">
    <div class="col-md-7 about-title_bookingtitle">
      <h2>Booking</h2>
    </div>
  </div>
  <div class="row about-booking">
    <flash-messages></flash-messages>
    <form [formGroup]="angForm" class="form-element">
      <div class="col-sm-4 offset-sm-2 about-booking_calendar">
        <div class="form-group form-element_date">
          <app-calendar formControlName="date" name="date" #date></app-calendar> 
        </div>
      </div>
      <div class="col-sm-4 about-booking_form">
        <div class="form-group form-element_email">
          <input type="email" class="form-control info" placeholder="Email" formControlName="email" #email (ngModelChange)="onChange($event)">
        </div>
        <div *ngIf="angForm.controls['email'].invalid && (angForm.controls['email'].dirty || angForm.controls['email'].touched)"
          class="alert alert-danger">
          <div *ngIf="angForm.controls['email'].errors.required">
            Email is required.
          </div>
        </div>
        <div class="input-group mb-3 form-element_city">
          <select class="custom-select" id="inputGroupSelect01" #cityName>
            <option selected *ngFor="let city of cities" [ngValue]="city.name">{{city.name}}</option>

          </select>
        </div>
        <div class="input-group mb-3 form-element_hotel">
          <select class="custom-select" id="inputGroupSelect01" #hotelName>
            <option selected *ngFor="let hotel of hotels" [ngValue]="hotel.name">{{hotel.name}}</option>

          </select>
        </div>
        <div class="form-group">
          <button type="submit" (click)="addReview(date.value, email.value, cityName.value , hotelName.value)" class="btn btn-primary btn-block form-element_btn"
            [disabled]="!validEmail">Book</button>
        </div>
      </div>
    </form>
  </div>
</div>

关于.component.ts

export class AboutComponent implements OnInit {
  comments: {};
  addcomments: Comment[];
  angForm: FormGroup;
  // tslint:disable-next-line:max-line-length
  validEmail = false;

  constructor(private flashMessages: FlashMessagesService,
    private fb: FormBuilder,
    private activeRouter: ActivatedRoute,
    private moviesService: MoviesService) {
    this.comments = [];
    this.createForm();
 }
  onChange(newValue) {
    // tslint:disable-next-line:max-line-length
    const validEmail = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    if (validEmail.test(newValue)) {
      this.validEmail = true;
    } else {
      this.validEmail = false;
    }

  }

  createForm() {
    this.angForm = this.fb.group({
      email: new FormControl('', [Validators.required, Validators.email]),
      date: new FormControl('') // this line missing in your code
    });
  }
  addReview(date, email, city, hotel) {
    this.moviesService.addReview(date, email, city, hotel).subscribe(success => {
      this.flashMessages.show('You are data we succesfully submitted', { cssClass: 'alert-success', timeout: 3000 });
      // get the id
      this.activeRouter.params.subscribe((params) => {
        // tslint:disable-next-line:prefer-const
        let id = params['id'];
        this.moviesService.getComments(id)
          .subscribe(comments => {
            console.log(comments);
            this.comments = comments;
          });
      });
    }, error => {
      this.flashMessages.show('Something went wrong', { cssClass: 'alert-danger', timeout: 3000 });
    });
  }
  ngOnInit() {

  }

}

这里是 calendar.ts

import { Component, OnInit, forwardRef, Input, ElementRef, ViewChild } from '@angular/core';
import { IgxCalendarComponent, IgxDialogComponent } from 'igniteui-angular';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
@Component({
  selector: 'app-calendar',
  templateUrl: './calendar.component.html',
  styleUrls: ['./calendar.component.scss'],
  providers: [
    { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CalendarComponent), multi: true }
  ]
})
export class CalendarComponent implements ControlValueAccessor, OnInit {
  @ViewChild('calendar') public calendar: IgxCalendarComponent;
  @ViewChild('alert') public dialog: IgxDialogComponent;
  @Input()
  label: string;
  @Input()
  isConsultation: boolean;

  private _theDate: string;

  constructor() { }

  propagateChange = (_: any) => { };
  onTouched: any = () => { };

  writeValue(obj: any): void {
    console.log('writeValue => obj : ', obj);
    if (obj) {
      this._theDate = obj;
    }
  }

  registerOnChange(fn: any): void {
    this.propagateChange = fn;
    console.log('registerOnChange => fn : ', fn);
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
    console.log('registerOnTouched => fn : ', fn);
  }

  get theDate() {
    console.log('get theDate()');
    return this._theDate;
  }

  set theDate(val) {
    console.log('set theDate(val) - val => ', val);
    this._theDate = val;
    this.propagateChange(val);
  }
  public verifyRange(dates: Date[]) {
    if (dates.length > 5) {
      this.calendar.selectDate(dates[0]);
      this.dialog.open();
    }
  }
  ngOnInit() {

  }
}

提交表单时出现以下错误 日期 = 未定义。

我的代码有什么问题?请问我需要你的帮助

【问题讨论】:

  • 我认为在 registerOnChange 中你忘记调用 this.propagateChange() 函数,但我不确定

标签: javascript angular html typescript bootstrap-4


【解决方案1】:

看起来你有日历的@input,但没有@output。 Angular 组件没有双向数据绑定,并且需要您为日历组件提供输出,否则调用 app-calendar 的父类将始终显示为好像传入的日期未定义。

所以在你的代码中,

html,添加输出,我只是将其命名为 outputDate,但可以是任何你想要的。

app-calendar formControlName="date" outputDate="returnedDate" name="date" #date></app-calendar> 

component ts,添加一个字符串,将传递给日历组件。在约会的任何地方都使用它。我把它命名为returnDate

export class AboutComponent implements OnInit {
comments: {};
addcomments: Comment[];
angForm: FormGroup;
// tslint:disable-next-line:max-line-length
validEmail = false;
returnedDate: string;

在应用 Calander ts 中,将 _theDate 替换为 outputDate。这将设置 outputDate 而不是父范围可以访问的。

export class CalendarComponent implements ControlValueAccessor, OnInit 
@ViewChild('calendar') public calendar: IgxCalendarComponent;
@ViewChild('alert') public dialog: IgxDialogComponent;
@Output()
outputDate: string;

【讨论】:

  • 嗨,Modest 刚刚学习,如何实现自定义表单,我尝试了很多我无法弄清楚的方法,你能在这里展示如何添加该输出吗?
  • 是的,我将编辑我的答案以包含组件的输出参数。
  • 好的,我在等。
  • 不是。是自定义控件窗体,不是子窗体。所以你不需要输出
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-03
  • 2018-10-16
  • 1970-01-01
  • 1970-01-01
  • 2018-11-02
  • 2019-03-11
  • 1970-01-01
相关资源
最近更新 更多