英文:
ngb-datepicker does not update model value when using custom NgbDateParserFormatter
问题
I understand your request. Here's the translation of the code part you provided:
我创建了一个自定义组件,其中包含一个Angular日期选择器,问题是我需要根据应用程序选择的语言格式化日期的显示方式,这就是为什么我创建了一个自定义的NgbDateParserFormatter。当我提供我的自定义格式化程序时,日期显示正确,但是当我尝试从父组件获取值时,模型值没有更新,只有在删除我的自定义提供程序时才有效,但据我所理解,格式化程序不应该影响到这一点。
这是我的自定义日期选择器组件:
custom-datepicker.html
<div>
<input
ngbDatepicker
class="form-control"
[(ngModel)]="date"
#dateInput="ngbDatepicker"
(click)="onToggle(dateInput)"
(ngModelChange)="onChangeDate($event)"
ngControl="date" name="dateInput"/>
<button class="btn input-group-text date-picker-toggle-btn" (click)="dateInput.toggle()" type="button"></button>
</div>
custom-datepicker.ts
import { Component, EventEmitter, Input, Output } from '@angular/core';
import {
NgbCalendar,
NgbDateStruct,
NgbDatepickerI18n,
} from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'date-picker',
templateUrl: './date-picker.component.html',
styleUrls: ['./date-picker.component.scss'],
providers: [],
})
export class DatePickerComponent {
@Input('date')
date: NgbDateStruct;
@Output()
dateChange: EventEmitter<any> = new EventEmitter<any>();
today = this.calendar.getToday();
constructor(private calendar: NgbCalendar) {
}
onChangeDate(newDate: any) {
this.dateChange.emit(newDate);
}
onToggle(dateInput) {
dateInput.toggle();
}
}
ngbDateCustomParserFormatter.ts
import { NgbDateParserFormatter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { DatePipe } from '@angular/common';
function toInteger(value: any): number {
return parseInt(`${value}`, 10);
}
function isNumber(value: any): value is number {
return !isNaN(toInteger(value));
}
@Injectable()
export class NgbDateCustomParserFormatter extends NgbDateParserFormatter {
constructor(private datePipe: DatePipe, private translator: TranslateService) {
super();
}
parse(value: string): NgbDateStruct {
if (value) {
const dateParts = value.trim().split('-');
if (dateParts.length === 1 && isNumber(dateParts[0])) {
return { day: toInteger(dateParts[0]), month: null, year: null };
} else if (dateParts.length === 2 && isNumber(dateParts[0]) && isNumber(dateParts[1])) {
return { day: toInteger(dateParts[0]), month: toInteger(dateParts[1]), year: null };
} else if (dateParts.length === 3 && isNumber(dateParts[0]) && isNumber(dateParts[1]) && isNumber(dateParts[2])) {
return { day: toInteger(dateParts[0]), month: toInteger(dateParts[1]), year: toInteger(dateParts[2]) };
}
}
return null;
}
format(date: NgbDateStruct): string {
let dateObj = new Date(date.year, date.month - 1, date.day);
return this.datePipe.transform(dateObj, 'dd/MM/yyyy');
}
}
这是如何在父组件HTML中使用我的组件(expirationDate是NgbDateStruct
):
<date-picker [(date)]="expirationDate" id="expiration-date" />
编辑:只是为了澄清一下。我已经在AppModule中添加了提供程序,并且自定义日期选择器组件,在我将其添加到提供程序时,模型不会得到更新,当我删除该提供程序时,模型会得到正确的更新。
@NgModule({
declarations: [
...
],
imports: [
...
],
providers: [provide: NgbDateParserFormatter, useClass: NgbDateCustomParserFormatter}
],
bootstrap: [AppComponent],
})
export class AppModule {}
Is there anything else you need help with?
英文:
I created a custom component that holds inside an angular date picker, problem is that I need to format the way the date is displayed depeding on the app's selected language, that why I created a custom NgbDateParserFormatter. When I provide my custom formatter the date is displayed correctly, but the model value is not updated when I try to get the value from a parent component, it just works when I remove my custom provider, but I far as I understand the formatter shouldn't affect that.
Here is my custom date picker component
custom-datepicker.html
<div>
<input
ngbDatepicker
class="form-control"
[(ngModel)]="date"
#dateInput="ngbDatepicker"
(click)="onToggle(dateInput)"
(ngModelChange)="onChangeDate($event)"
ngControl="date" name="dateInput"/>
<button class="btn input-group-text date-picker-toggle-btn" (click)="dateInput.toggle()" type="button"></button>
</div>
custom-datepicker.ts
import { Component, EventEmitter, Input, Output } from '@angular/core';
import {
NgbCalendar,
NgbDateStruct,
NgbDatepickerI18n,
} from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'date-picker',
templateUrl: './date-picker.component.html',
styleUrls: ['./date-picker.component.scss'],
providers: [],
})
export class DatePickerComponent {
@Input('date')
date: NgbDateStruct;
@Output()
dateChange: EventEmitter<any> = new EventEmitter<any>();
today = this.calendar.getToday();
constructor(private calendar: NgbCalendar) {
}
onChangeDate(newDate: any) {
this.dateChange.emit(newDate);
}
onToggle(dateInput) {
dateInput.toggle();
}
}
ngbDateCustomParserFormatter.ts
import { NgbDateParserFormatter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { DatePipe } from '@angular/common';
function toInteger(value: any): number {
return parseInt(`${value}`, 10);
}
function isNumber(value: any): value is number {
return !isNaN(toInteger(value));
}
@Injectable()
export class NgbDateCustomParserFormatter extends NgbDateParserFormatter {
constructor(private datePipe: DatePipe, private translator: TranslateService) {
super();
}
parse(value: string): NgbDateStruct {
if (value) {
const dateParts = value.trim().split('-');
if (dateParts.length === 1 && isNumber(dateParts[0])) {
return {day: toInteger(dateParts[0]), month: null, year: null};
} else if (dateParts.length === 2 && isNumber(dateParts[0]) && isNumber(dateParts[1])) {
return {day: toInteger(dateParts[0]), month: toInteger(dateParts[1]), year: null};
} else if (dateParts.length === 3 && isNumber(dateParts[0]) && isNumber(dateParts[1]) && isNumber(dateParts[2])) {
return {day: toInteger(dateParts[0]), month: toInteger(dateParts[1]), year: toInteger(dateParts[2])};
}
}
return null;
}
format(date: NgbDateStruct): string {
let dateObj = new Date(date.year, date.month - 1, date.day);
return this.datePipe.transform(dateObj, 'dd/MM/yyyy');
}
}
And this is how my componen is being used in the paren component html (expirationDate id a NgbDateStruct
)
<date-picker [(date)]="expirationDate" id="expiration-date" />
EDIT:
Just to clarify. I have added the provider in the AppModule and the custom date picker component, it's when I add it to the providers when the model doesn't get updated, when I remove that provider the model gets updated correctly.
@NgModule({
declarations: [
...
],
imports: [
...
],
providers: [provide: NgbDateParserFormatter, useClass: NgbDateCustomParserFormatter}
],
bootstrap: [AppComponent],
})
export class AppModule {}
答案1
得分: 0
在你的DatePickerComponent.ts中,需要添加提供者(providers)以及适配器(adapter)。你也可以在你的app.module.ts中添加:
providers: [
{ provide: NgbDateParserFormatter, useClass: NgbDateCustomParserFormatter },
// 如果你想要使用自定义的日期适配器
{ provide: NgbDateAdapter, useClass: NgbDateCustomDateAdapter }
],
英文:
See that it's necessary add in provider the adapter. In your DatePickerComponent.ts (you can also add in your app.module.ts)
providers: [
{ provide: NgbDateParserFormatter , useClass: NgbDateCustomParserFormatter},
//If you want also to use a CustomDate adapter
{ provide: NgbDateAdapter, useClass: NgbDateCustomDateAdapter }
],
答案2
得分: 0
如果有人遇到相同的问题,请检查您的解析器,忘记更改解析器,因此它试图解析DD/MM/YYYY日期,而解析器期望的是YYYY-MM-DD日期。
英文:
If anyones expiriences the same problem, check your parser, forgot to change the parser so it was trying to parse DD/MM/YYYY dates and the parser was expecting YYYY-MM-DD dates
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论