Подтвердить что ты не робот

Как обнаружить события изменения событий datetimepicker bootstrap в angular2

Я использую bootstrap datetimepicker в 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}} показывает мне значение плюс текст, который я напечатал.

Как я могу обнаружить изменения в текстовом поле, если пользователь нажимает на дату в селекторе, чтобы изменить его?

4b9b3361

Ответ 1

Проблема заключается в том, что 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": при размытии мы обновляем модель.

Ответ 2

Проблема, изложенная в других ответах, заключается в том, что 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();
    };
};

Ответ 3

Решение, отправленное пользователем3169887, отлично подойдет для меня, пока я не переключился с формы с шаблоном (использует ngModel) в реактивную форму.

Вдаваясь в первоначальную проблему, я узнал, что Angular прослушивает событие ввода, которое эти библиотеки датпикера не срабатывают. Мое решение состояло в том, чтобы настроить директиву, чтобы запустить событие ввода, а не излучать событие 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".

Ответ 4

Не уверен, что это работает, но в соответствии с документами правильное событие для прослушивания - change

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