反应形式的 NgbDatepicker:设置初始值
NgbDatepicker in Reactive Forms: Set Initial Value
这可能是我一段时间以来遇到的最令人沮丧的问题之一。一般来说,在 Angular 中处理日期,尤其是 NgbDatepicker 有点麻烦。
我在 Angular 8 中实现了针对反应式表单的 NgbDatepicker,我的问题的要点是我可以设置我的日期控件的初始值,但该初始值没有显示(视觉上)在表格上。我可以将我的表单记录到控制台并看到值正在设置,但表单字段本身不会更新。如果我 select 来自选择器本身的日期,那么我的 selection 会反映在表单字段中。我原以为它会像设置 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;
}
}
从那里我确实有自定义 parser/formatter 设置,它看起来就像 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 : '';
}
}
而且,这似乎无法让我用可见的启动值启动该日期字段。如您所见,此时我只是硬编码该开始日期的 return 值。那个日期确实设置正确——当你打开选择器时,这是它登陆的日期,但当你登陆页面时它实际上并没有出现在显示字段中。在您实际 select 一个值之前,那只是空白。
我尝试了很多不同的想法组合,但没有任何效果。真是令人沮丧。我看到这个问题的 variations/fragments 确实已经存在,但是我找不到使用这种技术组合提出的问题的例子。大多数人在使用 NgbDatepicker 时似乎都依赖于模板化表单,而不是反应式表单。
startDatae
属性日期选择器没有设置初始值。您应该将 formControl 的值设置为您想要的值。
这是一个没有解析器的例子。我在工作中使用自定义 parser/formatter,但它确实有效(不能 post 此处的代码)。
工作 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>
如果您的解析器仍有问题,请确保您同时拥有 NgbDateParserFormatter
和 NgbDateAdapter
,并且您设置的初始值可以被适配器正确转换(如果它不是 Ngb 日期对象)
这可能是我一段时间以来遇到的最令人沮丧的问题之一。一般来说,在 Angular 中处理日期,尤其是 NgbDatepicker 有点麻烦。
我在 Angular 8 中实现了针对反应式表单的 NgbDatepicker,我的问题的要点是我可以设置我的日期控件的初始值,但该初始值没有显示(视觉上)在表格上。我可以将我的表单记录到控制台并看到值正在设置,但表单字段本身不会更新。如果我 select 来自选择器本身的日期,那么我的 selection 会反映在表单字段中。我原以为它会像设置 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;
}
}
从那里我确实有自定义 parser/formatter 设置,它看起来就像 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 : '';
}
}
而且,这似乎无法让我用可见的启动值启动该日期字段。如您所见,此时我只是硬编码该开始日期的 return 值。那个日期确实设置正确——当你打开选择器时,这是它登陆的日期,但当你登陆页面时它实际上并没有出现在显示字段中。在您实际 select 一个值之前,那只是空白。
我尝试了很多不同的想法组合,但没有任何效果。真是令人沮丧。我看到这个问题的 variations/fragments 确实已经存在,但是我找不到使用这种技术组合提出的问题的例子。大多数人在使用 NgbDatepicker 时似乎都依赖于模板化表单,而不是反应式表单。
startDatae
属性日期选择器没有设置初始值。您应该将 formControl 的值设置为您想要的值。
这是一个没有解析器的例子。我在工作中使用自定义 parser/formatter,但它确实有效(不能 post 此处的代码)。
工作 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>
如果您的解析器仍有问题,请确保您同时拥有 NgbDateParserFormatter
和 NgbDateAdapter
,并且您设置的初始值可以被适配器正确转换(如果它不是 Ngb 日期对象)