ngx bootstrap angular angular-ngmodel bootstrap-datetimepicker

ngx-bootstrap angular 4



Cómo detectar los eventos de cambio del datetimepicker de bootstrap dentro de angular2 (4)

El problema es que Angular no sabe que el valor de la entrada ha cambiado para actualizar ngModel. Otra cosa extraña es que bootstrap-datetimepicker no activa el evento de cambio en la entrada, esto requiere alguna solución.

Vea este ejemplo de trabajo:

<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>

Observe los cambios:

  • [ngModel]="date" : solo necesitamos el enlace de datos unidireccional (del modelo a vista) ya que Angular no sabe cuándo ha cambiado el valor de la entrada
  • #datePicker : #datePicker una variable local para acceder a su valor
  • (blur)="date = datePicker.value" : en blur actualizamos el modelo

Estoy usando el bootstrap datetimepicker en angular 2

https://eonasdan.github.io/bootstrap-datetimepicker/

En mi plantilla tengo:

<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>

El problema es que cuando selecciono una fecha en el calendario con un clic, no desencadena ningún evento de "cambio" (en otras palabras, ngModel no se ngModel ). Si escribo en el cuadro de texto, entonces {{date}} me muestra el valor más el texto que escribí.

¿Cómo puedo detectar cambios en el cuadro de texto si el usuario hace clic en una fecha en el selector para cambiarlo?


No estoy seguro de si esto funciona, pero de acuerdo con los documentos, el evento correcto para escuchar es change

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


El problema según lo manifestado por las otras respuestas es que ngModel no está recogiendo el cambio que está realizando la biblioteca de terceros. ngModel utiliza el enlace de datos bidireccional. Esencialmente, cuando dices

<div [(ngModel)]="date">

eso es equivalente a

<div [ngModel]="date" (ngModelChange)="date=$event"> .

Lo que hice fue crear una directiva para emitir el evento ngModelChange, de la siguiente manera:

@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(); }; };


La solución publicada por user3169887 funcionó muy bien para mí hasta que cambié de un formulario manejado por plantilla (usa ngModel) a una forma reactiva.

Mirando más hacia el problema original, aprendí que Angular está escuchando el evento de "entrada" que estas bibliotecas de datapicker no disparan. Mi solución fue modificar la directiva para activar el evento de "entrada" en lugar de emitir el evento ngModelChange. Probé esta directiva con una forma basada en plantillas y una forma reactiva y ambas parecían funcionar.

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"); }; };

Tenga en cuenta que estoy usando una biblioteca diferente de datepicker, así que estoy escuchando el evento "changeDate" y su biblioteca puede activar un evento diferente como "dp.change".