繁体   English   中英

Reactive 中的 NgbDatepicker Forms:设置初始值

[英]NgbDatepicker in Reactive Forms: Set Initial Value

这可能是我一段时间以来处理过的最令人沮丧的问题之一。 一般来说,在 Angular 中处理日期,尤其是 NgbDatepicker 有点麻烦。

我正在针对 Angular 8 中的反应式 forms 实施 NgbDatepicker,我的问题的要点是我可以设置我的日期控件的初始值,但该初始值不会(在视觉上)显示在表单上。 我可以将我的表单记录到控制台并看到值正在设置,但表单字段本身不会更新。 如果我 select 来自选择器本身的日期,那么我的选择会反映在表单字段中。 我原以为它会像设置 ngbDatepicker 输入的[startDate]属性一样简单,但显然没有。 我已经尝试了很多不同的迭代; 这是事情的立场,代码方面:

我的HTML:

<input #licenseExpiration="ngbDatepicker"
    class="form-control"
    fromControlName="licenseExpiration"
    [startDate]="startDate"
    ngbDatepicker />
<button class="btn btn-info zero-spacing pt-1 pr-1 pl-1"
    (click)="licenseExpiration.toggle()"
    type="button">

我组件的相关部分:

@Component({
  selector: 'app-cert',
  templateUrl: './cert.component.html',
  providers: [
    { provide: NgbDateParserFormatter, useClass: CustomDateParserFormatter }
  ]
})
export class CertComponent implements OnInit {
  certForm: CertForm = new CertForm();

  constructor(
    public readonly formatter: CustomDateParserFormatter) { }

  ngOnInit() {
    this.certForm.setModel(...modelObjectFromOtherService...);
  }

  get startDate() {
    return { year: 2020, month: 6, day: 13 };
  }
}

上面的 HTML 驻留在由该 CertForm 类型指定的 formGroup 中。 该表单包含日期控件,看起来(部分)如下所示:

export class CertForm extends FormGroup {
  public dateParser: CustomDateParserFormatter;

  constructor(
    cert: ICertModel = new CertModel()) {
    super({
      ..
      licenseExpiration: new FormControl("", Validators.required),
      ..
    });
  }

  setModel(cert: ICertModel) {
    this.patchValue({
      licenseExpiration
    });
  }

  getModel(): ICertModel {
    const cert = new CertModel();
    ...
    cert.licenseExpiration = this.get("licenseExpiration").value;
    ...
    return cert;
  }
}

从那里我确实有自定义解析器/格式化程序设置,它看起来就像 NGB 示例页面上指定的那样:

@Injectable({
  providedIn: "root"
})
export class CustomDateParserFormatter extends NgbDateParserFormatter {

  readonly DELIMITER = '/';

  parse(value: string): NgbDateStruct | null {
    if (value) {
      let date = value.split(this.DELIMITER);
      return {
        day: parseInt(date[0], 10),
        month: parseInt(date[1], 10),
        year: parseInt(date[2], 10)
      };
    }
    return null;
  }

  format(date: NgbDateStruct | null): string {
    return date ? date.month + this.DELIMITER + date.day + this.DELIMITER + date.year : '';
  }
}

而且,这似乎不会让我启动具有可见启动值的日期字段。 如您所见,此时我只是硬编码该开始日期的返回值。 那个日期确实设置正确——当你打开选择器时,这是它登陆的日期,但当你登陆页面时它实际上并没有出现在显示字段中。 在您实际 select 一个值之前,这只是空白。

我尝试了很多不同的想法组合,但没有任何效果。 真是令人沮丧。 我看到这个问题的变体/片段确实已经存在,但是我找不到使用这种技术组合提出的问题的例子。 大多数人在使用 NgbDatepicker 时似乎依赖于模板化的 forms,而不是反应式的 forms。

日期选择器上的startDatae属性未设置初始值。 您应该将 formControl 的值设置为您想要的值。

这是一个没有解析器的例子。 我在工作中使用自定义解析器/格式化程序,但它确实有效(不能在此处发布该代码)。

工作 stackblitz(注意这是最新的 Angular 和 NgBootstrap) https://stackblitz.com/edit/angular-zpeul4

应用组件

  formGroup = new FormGroup({});

  ngOnInit() {
    console.log('on init');
    this.formGroup.addControl("test", new FormControl({day: 20, month:4, year:1969})) //nice
    this.formGroup.valueChanges.subscribe(val => {
      console.log(val);
    })
    console.log(this.formGroup.value);
  }

模板

 <div class="container" [formGroup]="formGroup">
    
  <input #licenseExpiration="ngbDatepicker"
    class="form-control"
    [formControlName]="'test'"
    ngbDatepicker />

  <button class=""
  (click)="licenseExpiration.toggle()"
  type="button">open</button>

</div>  

如果您的解析器仍然存在问题,请确保您同时拥有NgbDateParserFormatterNgbDateAdapter ,并且您设置的初始值可以被适配器正确转换(如果它不是 Ngb 日期对象)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM