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

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

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

  1. <div>
  2. <input
  3. ngbDatepicker
  4. class="form-control"
  5. [(ngModel)]="date"
  6. #dateInput="ngbDatepicker"
  7. (click)="onToggle(dateInput)"
  8. (ngModelChange)="onChangeDate($event)"
  9. ngControl="date" name="dateInput"/>
  10. <button class="btn input-group-text date-picker-toggle-btn" (click)="dateInput.toggle()" type="button"></button>
  11. </div>

custom-datepicker.ts

  1. import { Component, EventEmitter, Input, Output } from '@angular/core';
  2. import {
  3. NgbCalendar,
  4. NgbDateStruct,
  5. NgbDatepickerI18n,
  6. } from '@ng-bootstrap/ng-bootstrap';
  7. @Component({
  8. selector: 'date-picker',
  9. templateUrl: './date-picker.component.html',
  10. styleUrls: ['./date-picker.component.scss'],
  11. providers: [],
  12. })
  13. export class DatePickerComponent {
  14. @Input('date')
  15. date: NgbDateStruct;
  16. @Output()
  17. dateChange: EventEmitter<any> = new EventEmitter<any>();
  18. today = this.calendar.getToday();
  19. constructor(private calendar: NgbCalendar) {
  20. }
  21. onChangeDate(newDate: any) {
  22. this.dateChange.emit(newDate);
  23. }
  24. onToggle(dateInput) {
  25. dateInput.toggle();
  26. }
  27. }

ngbDateCustomParserFormatter.ts

  1. import { NgbDateParserFormatter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
  2. import { Injectable } from '@angular/core';
  3. import { TranslateService } from '@ngx-translate/core';
  4. import { DatePipe } from '@angular/common';
  5. function toInteger(value: any): number {
  6. return parseInt(`${value}`, 10);
  7. }
  8. function isNumber(value: any): value is number {
  9. return !isNaN(toInteger(value));
  10. }
  11. @Injectable()
  12. export class NgbDateCustomParserFormatter extends NgbDateParserFormatter {
  13. constructor(private datePipe: DatePipe, private translator: TranslateService) {
  14. super();
  15. }
  16. parse(value: string): NgbDateStruct {
  17. if (value) {
  18. const dateParts = value.trim().split('-');
  19. if (dateParts.length === 1 && isNumber(dateParts[0])) {
  20. return { day: toInteger(dateParts[0]), month: null, year: null };
  21. } else if (dateParts.length === 2 && isNumber(dateParts[0]) && isNumber(dateParts[1])) {
  22. return { day: toInteger(dateParts[0]), month: toInteger(dateParts[1]), year: null };
  23. } else if (dateParts.length === 3 && isNumber(dateParts[0]) && isNumber(dateParts[1]) && isNumber(dateParts[2])) {
  24. return { day: toInteger(dateParts[0]), month: toInteger(dateParts[1]), year: toInteger(dateParts[2]) };
  25. }
  26. }
  27. return null;
  28. }
  29. format(date: NgbDateStruct): string {
  30. let dateObj = new Date(date.year, date.month - 1, date.day);
  31. return this.datePipe.transform(dateObj, 'dd/MM/yyyy');
  32. }
  33. }

这是如何在父组件HTML中使用我的组件(expirationDate是NgbDateStruct):

  1. <date-picker [(date)]="expirationDate" id="expiration-date" />

编辑:只是为了澄清一下。我已经在AppModule中添加了提供程序,并且自定义日期选择器组件,在我将其添加到提供程序时,模型不会得到更新,当我删除该提供程序时,模型会得到正确的更新。

  1. @NgModule({
  2. declarations: [
  3. ...
  4. ],
  5. imports: [
  6. ...
  7. ],
  8. providers: [provide: NgbDateParserFormatter, useClass: NgbDateCustomParserFormatter}
  9. ],
  10. bootstrap: [AppComponent],
  11. })
  12. 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

  1. &lt;div&gt;
  2. &lt;input
  3. ngbDatepicker
  4. class=&quot;form-control&quot;
  5. [(ngModel)]=&quot;date&quot;
  6. #dateInput=&quot;ngbDatepicker&quot;
  7. (click)=&quot;onToggle(dateInput)&quot;
  8. (ngModelChange)=&quot;onChangeDate($event)&quot;
  9. ngControl=&quot;date&quot; name=&quot;dateInput&quot;/&gt;
  10. &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;
  11. &lt;/div&gt;

custom-datepicker.ts

  1. import { Component, EventEmitter, Input, Output } from &#39;@angular/core&#39;;
  2. import {
  3. NgbCalendar,
  4. NgbDateStruct,
  5. NgbDatepickerI18n,
  6. } from &#39;@ng-bootstrap/ng-bootstrap&#39;;
  7. @Component({
  8. selector: &#39;date-picker&#39;,
  9. templateUrl: &#39;./date-picker.component.html&#39;,
  10. styleUrls: [&#39;./date-picker.component.scss&#39;],
  11. providers: [],
  12. })
  13. export class DatePickerComponent {
  14. @Input(&#39;date&#39;)
  15. date: NgbDateStruct;
  16. @Output()
  17. dateChange: EventEmitter&lt;any&gt; = new EventEmitter&lt;any&gt;();
  18. today = this.calendar.getToday();
  19. constructor(private calendar: NgbCalendar) {
  20. }
  21. onChangeDate(newDate: any) {
  22. this.dateChange.emit(newDate);
  23. }
  24. onToggle(dateInput) {
  25. dateInput.toggle();
  26. }
  27. }

ngbDateCustomParserFormatter.ts

  1. import { NgbDateParserFormatter, NgbDateStruct } from &#39;@ng-bootstrap/ng-bootstrap&#39;;
  2. import { Injectable } from &#39;@angular/core&#39;;
  3. import { TranslateService } from &#39;@ngx-translate/core&#39;;
  4. import { DatePipe } from &#39;@angular/common&#39;;
  5. function toInteger(value: any): number {
  6. return parseInt(`${value}`, 10);
  7. }
  8. function isNumber(value: any): value is number {
  9. return !isNaN(toInteger(value));
  10. }
  11. @Injectable()
  12. export class NgbDateCustomParserFormatter extends NgbDateParserFormatter {
  13. constructor(private datePipe: DatePipe, private translator: TranslateService) {
  14. super();
  15. }
  16. parse(value: string): NgbDateStruct {
  17. if (value) {
  18. const dateParts = value.trim().split(&#39;-&#39;);
  19. if (dateParts.length === 1 &amp;&amp; isNumber(dateParts[0])) {
  20. return {day: toInteger(dateParts[0]), month: null, year: null};
  21. } else if (dateParts.length === 2 &amp;&amp; isNumber(dateParts[0]) &amp;&amp; isNumber(dateParts[1])) {
  22. return {day: toInteger(dateParts[0]), month: toInteger(dateParts[1]), year: null};
  23. } else if (dateParts.length === 3 &amp;&amp; isNumber(dateParts[0]) &amp;&amp; isNumber(dateParts[1]) &amp;&amp; isNumber(dateParts[2])) {
  24. return {day: toInteger(dateParts[0]), month: toInteger(dateParts[1]), year: toInteger(dateParts[2])};
  25. }
  26. }
  27. return null;
  28. }
  29. format(date: NgbDateStruct): string {
  30. let dateObj = new Date(date.year, date.month - 1, date.day);
  31. return this.datePipe.transform(dateObj, &#39;dd/MM/yyyy&#39;);
  32. }
  33. }

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

  1. &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.

  1. @NgModule({
  2. declarations: [
  3. ...
  4. ],
  5. imports: [
  6. ...
  7. ],
  8. providers: [provide: NgbDateParserFormatter, useClass: NgbDateCustomParserFormatter}
  9. ],
  10. bootstrap: [AppComponent],
  11. })
  12. export class AppModule {}

答案1

得分: 0

在你的DatePickerComponent.ts中,需要添加提供者(providers)以及适配器(adapter)。你也可以在你的app.module.ts中添加:

  1. providers: [
  2. { provide: NgbDateParserFormatter, useClass: NgbDateCustomParserFormatter },
  3. // 如果你想要使用自定义的日期适配器
  4. { provide: NgbDateAdapter, useClass: NgbDateCustomDateAdapter }
  5. ],
英文:

See that it's necessary add in provider the adapter. In your DatePickerComponent.ts (you can also add in your app.module.ts)

  1. providers: [
  2. { provide: NgbDateParserFormatter , useClass: NgbDateCustomParserFormatter},
  3. //If you want also to use a CustomDate adapter
  4. { provide: NgbDateAdapter, useClass: NgbDateCustomDateAdapter }
  5. ],

答案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:

确定