ngb-datepicker在使用自定义的NgbDateParserFormatter时不会更新模型值。

huangapple go评论56阅读模式
英文:

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

&lt;div&gt;
&lt;input
ngbDatepicker
class=&quot;form-control&quot;
[(ngModel)]=&quot;date&quot;
#dateInput=&quot;ngbDatepicker&quot;
(click)=&quot;onToggle(dateInput)&quot;
(ngModelChange)=&quot;onChangeDate($event)&quot;
ngControl=&quot;date&quot; name=&quot;dateInput&quot;/&gt;
&lt;button class=&quot;btn input-group-text date-picker-toggle-btn&quot; (click)=&quot;dateInput.toggle()&quot; type=&quot;button&quot;&gt;&lt;/button&gt;
&lt;/div&gt;

custom-datepicker.ts

import { Component, EventEmitter, Input, Output } from &#39;@angular/core&#39;;
import {
NgbCalendar,
NgbDateStruct,
NgbDatepickerI18n,
} from &#39;@ng-bootstrap/ng-bootstrap&#39;;
@Component({
selector: &#39;date-picker&#39;,
templateUrl: &#39;./date-picker.component.html&#39;,
styleUrls: [&#39;./date-picker.component.scss&#39;],
providers: [],
})
export class DatePickerComponent {
@Input(&#39;date&#39;)
date: NgbDateStruct;
@Output()
dateChange: EventEmitter&lt;any&gt; = new EventEmitter&lt;any&gt;();
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 &#39;@ng-bootstrap/ng-bootstrap&#39;;
import { Injectable } from &#39;@angular/core&#39;;
import { TranslateService } from &#39;@ngx-translate/core&#39;;
import { DatePipe } from &#39;@angular/common&#39;;
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(&#39;-&#39;);
if (dateParts.length === 1 &amp;&amp; isNumber(dateParts[0])) {
return {day: toInteger(dateParts[0]), month: null, year: null};
} else if (dateParts.length === 2 &amp;&amp; isNumber(dateParts[0]) &amp;&amp; isNumber(dateParts[1])) {
return {day: toInteger(dateParts[0]), month: toInteger(dateParts[1]), year: null};
} else if (dateParts.length === 3 &amp;&amp; isNumber(dateParts[0]) &amp;&amp; isNumber(dateParts[1]) &amp;&amp; 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, &#39;dd/MM/yyyy&#39;);
}
}

And this is how my componen is being used in the paren component html (expirationDate id a NgbDateStruct)

&lt;date-picker [(date)]=&quot;expirationDate&quot; id=&quot;expiration-date&quot; /&gt;

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

huangapple
  • 本文由 发表于 2023年6月9日 07:22:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76436290.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定