bootstrap datetimepicker in angular 2
https://eonasdan.github.io/bootstrap-datetimepicker/
私のテンプレートには次のものがあります:
<div class='input-group date datepicker'>
<input type='text' class="form-control" [(ngModel)]="date">
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar" (click)="getCalendar()"></span>
</span>
{{date}}
</div>
問題は、クリックしてカレンダーの日付を選択すると、「変更」イベントがトリガーされないことです(つまり、ngModel
は起動されません)。テキストボックスに入力すると、{{date}}
は、値と入力したテキストを表示します。
ユーザーがセレクターの日付をクリックして変更する場合、どのようにテキストボックスの変更を検出できますか?
問題は、AngularはngModelを更新するために入力値が変更されたことを知らないことです。別の奇妙なことは、bootstrap-datetimepickerが入力のchangeイベントをトリガーしないことです。回避策が必要です。
<div class='input-group date datepicker'>
<input type='text' class="form-control" #datePicker [ngModel]="date" (blur)="date = datePicker.value">
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar" (click)="getCalendar()"></span>
</span>
{{date}}
</div>
変更点に注意してください。
[ngModel]="date"
:Angularは入力値がいつ変更されたかわからないので、モデルからビューへの一方向のデータバインディングのみが必要です。#datePicker
:値にアクセスするためにローカル変数を作成しました(blur)="date = datePicker.value"
:ぼかしでモデルを更新します他の回答で述べられている問題は、ngModelがサードパーティライブラリによって行われた変更を認識していないことです。 ngModelは双方向のデータバインディングを使用します。基本的に、あなたが言うとき
<div [(ngModel)]="date">
それは同等です
<div [ngModel]="date" (ngModelChange)="date=$event">
。
次のように、ngModelChangeイベントを発行するディレクティブを作成しました。
@Directive({
selector: [datepicker],
outputs: [
"ngModelChange"
]
})
export class DatePickerDirective {
//Emits changes to ngModel
ngModelChange = new EventEmitter();
el: JQuery;
//Obtains the handle to the jQuery element
constructor(el){
this.el = jQuery(el.nativeElement);
}
ngOnInit() {
this.el.datetimepicker({
//Initialization options
});
this.el.on('dp.change', (event) => {
var moment: Moment = event.date;
//Emit new value
this.ngModelChange.emit(date.format(/*However you want it formatted*/));
});
};
ngOnDestroy() {
//Clean up
this.el.data('DateTimePicker').destroy();
};
};
User3169887によって投稿されたソリューションは、テンプレート駆動フォーム(ngModelを使用)からリアクティブフォームに切り替えるまで、私にとってはうまくいきました。
元の問題をさらに調べると、Angularはこれらのdatepickerライブラリが起動しない「入力」イベントをリッスンしていることを知りました。私の解決策は、「入力」を起動するディレクティブngModelChangeイベントを発行するのではなく、イベントです。このディレクティブをテンプレート駆動フォームとリアクティブフォームの両方でテストしましたが、どちらも機能しているように見えました。
import { Directive, ElementRef, Renderer, Input, OnInit } from "@angular/core";
declare var $: any;
@Directive({
selector: "[datepicker]"
})
export class DatePickerDirective implements OnInit {
@Input("datepicker")
private datepickerOptions: any = {};
private $el: any;
constructor(private el: ElementRef, private renderer: Renderer) {
this.$el = $(el.nativeElement);
}
ngOnInit() {
// Initialize the date picker
this.$el.datepicker(this.datepickerOptions)
// Angular is watching for the "input" event which is not fired when choosing
// a date within the datepicker, so watch for the "changeDate" event and manually
// fire the "input" event so that Angular picks up the change
// See: angular/modules/@angular/forms/src/directives/default_value_accessor.ts
.on("changeDate", (event) => {
let inputEvent = new Event("input", { bubbles: true });
this.renderer.invokeElementMethod(this.el.nativeElement, "dispatchEvent", [inputEvent]);
});
};
ngOnDestroy() {
this.$el.datepicker("destroy");
};
};
私は別のdatepickerライブラリを使用しているため、「changeDate」イベントをリッスンしているため、ライブラリは「dp.change」などの別のイベントを起動する可能性があります。
ngModelChange
の代わりにchange
を試してください。
<input class="form-control" (ngModelChange)="changeDate($event)"
[(ngModel)]="startRegistrationDate" ngbDatepicker #start="ngbDatepicker">
// to catch the event
changeDate(event: any) {
console.log(event);
}
これが機能するかどうかはわかりませんが、ドキュメントによると、リッスンする適切なイベントはchange
です
<div class='input-group date datepicker' (change)="date=$event">