如何检测angular2中的bootstrap datetimepicker更改事件

时间:2016-03-18 15:04:09

标签: angular angular-ngmodel bootstrap-datetimepicker

我在angular 2中使用bootstrap datetimepicker

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}}会显示该值以及我输入的文字。

如果用户点击选择器中的日期进行更改,如何检测文本框中的更改?

5 个答案:

答案 0 :(得分:14)

问题是Angular不知道输入的值已经改变以便更新ngModel。另一个奇怪的事情是bootstrap-datetimepicker没有触发输入上的更改事件 - 这需要一些解决方法。

参见此工作示例:

<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":关于模糊,我们更新模型

答案 1 :(得分:7)

其他答案所述的问题是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();
    };
};

答案 2 :(得分:5)

user3169887发布的解决方案对我来说非常有用,直到我从模板驱动的表单(使用ngModel)切换到反应式表单。

进一步研究原始问题,我了解到Angular正在倾听&#34;输入&#34;这些日期选择器库不会触发的事件。我的解决方案是调整指令以触发&#34;输入&#34;事件而不是发出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");
    };
};

请注意,我使用了不同的日期拣档库,因此我正在聆听&#34; changeDate&#34;事件和您的图书馆可能会发起不同的事件,如&#34; dp.change&#34;。

答案 3 :(得分:3)

尝试使用ngModelChange代替change

<input class="form-control" (ngModelChange)="changeDate($event)"
      [(ngModel)]="startRegistrationDate" ngbDatepicker #start="ngbDatepicker">

// to catch the event
changeDate(event: any) {
  console.log(event);
}

答案 4 :(得分:1)

不确定这是否有效,但根据文档,正确的事件是change

<div class='input-group date datepicker' (change)="date=$event">