2017-09-15 7 views
0

Ich versuche, einen benutzerdefinierten Bindungshandler in Knockout für Flatpickr zu erstellen. Wenn ich versuche, es zu benutzen, bekomme ich einen Fehler:Knockout-Custom-Binding-Handler-Fehler: Kein Konstruktor 'Flatpickr'

Uncaught TypeError: Unable to process binding "datetimepicker: function(){return startDate }" 
Message: Flatpickr is not a constructor 
    at init (knockout.bindings.ts:16) 

Meine benutzerdefinierte Bindung Handler:

import ko from 'knockout'; 
import $ from 'jquery'; 
import * as Flatpickr from 'flatpickr'; 

let bindingHandlers: any = ko.bindingHandlers; 

bindingHandlers.datetimepicker = { 
    init: function (element: any, valueAccessor: any, allBindingsAccessor: any) { 
     var options = $.extend({ 
      dateFormat: 'DD-MM-YYYY', 
      enableTime: true 
     }, allBindingsAccessor().datetimepickerOptions), 
      $el = $(element), 
      picker = new Flatpickr(element, options), 
      observable = valueAccessor(); 

     //handle the field changing by registering datepicker's changeDate event 
     ko.utils.registerEventHandler(element, "change", function() { 
      observable(picker.parseDate((<any>$el).val(), 'DD-MM-YYYY')); 
     }); 

     //handle disposal (if KO removes by the template binding) 
     ko.utils.domNodeDisposal.addDisposeCallback(element, function() { 
      (<any>$el).flatpickr("destroy"); 
     }); 

     observable.subscribe(function (newVal: any) { 
      (<any>$el).val(picker.formatDate(options.dateFormat, newVal)); 
     }); 

     picker.setDate(ko.unwrap(observable)); 
    } 
}; 

Typoskript Definitionsdatei:

// Type definitions for flatpickr 3.0 
// Project: https://github.com/chmln/flatpickr 
// Definitions by: James Birtles <https://github.com/UnwrittenFun> 
//     Rowell Heria <https://github.com/rowellx68> 
//     Michael Wagner <https://github.com/wagich> 
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped 

declare function flatpickr(element: string | Element | HTMLElement, options?: Flatpickr.Options): Flatpickr; 

declare class Flatpickr { 
    constructor(element: string | Element | HTMLElement, options?: Flatpickr.Options); 

    changeMonth(month: number, isOffset?: boolean): void; 
    clear(): void; 
    close(): void; 
    destroy(): void; 
    formatDate(date: Date, format: string): string; 
    jumpToDate(date?: Flatpickr.DateString): void; 
    open(): void; 
    parseDate(date: string, format: string): Date; 
    redraw(): void; 
    set(option: string, value: any): void; 
    setDate(date: Flatpickr.DateString | Flatpickr.DateString[], triggerChange?: boolean, dateFormat?: string): void; 
    toggle(): void; 

    static localize(locale: string | Flatpickr.Locale): void; 
    static l10ns: { 
     default: Flatpickr.Locale; 
    }; 
} 

declare namespace Flatpickr { 
    interface Options { 
     altFormat?: string; 
     altInput?: boolean; 
     altInputClass?: string; 
     allowInput?: boolean; 
     clickOpens?: boolean; 
     dateFormat?: string | null; 
     defaultDate?: DateString | DateString[]; 
     defaultHour?: number; 
     defaultMinute?: number; 
     disable?: DateRange[]; 
     disableMobile?: boolean; 
     enable?: DateRange[]; 
     enableTime?: boolean; 
     enableSeconds?: boolean; 
     hourIncrement?: number; 
     inline?: boolean; 
     maxDate?: DateString; 
     minDate?: DateString; 
     minuteIncrement?: number; 
     mode?: Mode; 
     nextArrow?: string; 
     noCalendar?: boolean; 
     onChange?: EventCallback | EventCallback[]; 
     onClose?: EventCallback | EventCallback[]; 
     onOpen?: EventCallback | EventCallback[]; 
     onReady?: EventCallback | EventCallback[]; 
     onMonthChange?: EventCallback | EventCallback[]; 
     onYearChange?: EventCallback | EventCallback[]; 
     onValueUpdate?: EventCallback | EventCallback[]; 
     onDayCreate?: EventCallback | EventCallback[]; 
     parseDate?(date: string): Date; 
     prevArrow?: string; 
     shorthandCurrentMonth?: boolean; 
     static?: boolean; 
     time_24hr?: boolean; 
     utc?: boolean; 
     weekNumbers?: boolean; 
     wrap?: boolean; 
     locale?: string | Locale; 
     plugins?: any[]; 
    } 

    interface Locale { 
     weekdays?: { 
      shorthand?: string[]; 
      longhand?: string[]; 
     }; 

     months?: { 
      shorthand?: string[]; 
      longhand?: string[]; 
     }; 

     firstDayOfWeek?: number; 
     weekAbbreviation?: string; 
     rangeSeparator?: string; 
     am?: string; 
     pm?: string; 

     ordinal?: ((nth: number) => string) | string; 

     scrollTitle?: string; 
     toggleTitle?: string; 
    } 

    type DateString = Date | string; 
    type DateRange = DateString | { from: DateString, to: DateString } | ((date: Date) => boolean); 
    type Mode = 'single' | 'multiple' | 'range'; 
    type EventCallback = (selectedDates: Date[], dateStr: string, instance: Flatpickr, elem: HTMLElement) => void; 
} 

export = Flatpickr; 

Meine Ansicht:

<!-- ko with: assignment --> 
<form> 
    <div class="form-group"> 
     <label for="startDate" class="control-label">Start date</label> 
     <input data-bind="attr: { id: 'startDate' + $parent.selector() }, datetimepicker: startDate, datetimepickerOptions:{ enableTime: false }" type="text" class="form-control" /> 
    </div> 
    <div class="form-group"> 
     <label for="endDate" class="control-label">End date</label> 
     <input data-bind="attr: { id: 'endDate' + $parent.selector() }, datetimepicker: startDate, datetimepickerOptions:{ enableTime: false }" type="text" class="form-control" /> 
    </div> 
</form> 
<!-- /ko --> 

Mein Seitenmodell:

class AssignmentModel { 
    startDate: KnockoutObservable<moment.Moment>; 
    endDate: KnockoutObservable<moment.Moment>; 

    constructor(startDate?: moment.Moment, endDate?: moment.Moment) { 
     this.startDate = ko.observable<moment.Moment>(startDate); 
     this.endDate = ko.observable<moment.Moment>(endDate); 
    } 
} 

class AssignmentGroupModel { 
    assignment: KnockoutObservable<AssignmentModel>; 
    assignments: KnockoutObservableArray<AssignmentModel>; 
    type: KnockoutObservable<string>; 
    index: KnockoutObservable<number>; 


    constructor(type: string, index: number) { 
     this.assignment = ko.observable<AssignmentModel>(); 
     this.assignments = ko.observableArray<AssignmentModel>([]); 
     this.type = ko.observable<string>(type); 
     this.index = ko.observable<number>(index); 
    } 


    public selector(): string { 
     return '-' + this.type() + '-' + this.index(); 
    } 
} 

Ich bin nicht sicher, warum es sagt Flatpickr kein Konstruktor ist, wenn ich über den new Flatpickr Teil in Visual Studio schweben, zeigt es richtig den Konstruktor: Flatpickr hover

Antwort

0

Das Problem war, mit wie Ich importierte Flatpickr. Ich habe meine Import-Anweisung wie folgt geändert:

import Flatpickr from 'flatpickr'; 

Jetzt funktioniert es. Ich musste meinen Custom-Binding-Handler wie folgt ändern:

ko.bindingHandlers.datetimepicker = { 
    init: function (element: any, valueAccessor: any, allBindingsAccessor: any) { 
     var options = { 
      ...allBindingsAccessor().flatpickrOptions, 
      dateFormat: 'd-m-Y', 
      enableTime: false 
     } 
     let picker = new Flatpickr(element, options); 
     let $el = $(element); 
     $el.data('dtp', picker); 

     ko.utils.registerEventHandler(element, "change", function() { 
      let momentValue = moment(element.value, 'DD-MM-YYYY'); 
      valueAccessor()(momentValue); 
     }); 

     ko.utils.domNodeDisposal.addDisposeCallback(element, function() { 
      (<any>element).flatpickr("destroy"); 
     }); 
    }, 
    update: function (element: any, valueAccessor: any) { 
     let picker = $(element).data('dtp'); 
     let value = ko.unwrap(valueAccessor()); 
     picker.setDate(value.format('DD-MM-YYYY')); 
    } 
};