Knockout自定义绑定处理程序错误:不是构造函数' Flatpickr'

时间:2017-09-15 21:38:38

标签: typescript knockout.js typescript-typings flatpickr

我试图在Flatpickr的淘汰赛中创建自定义绑定处理程序。当我尝试使用它时,我收到一个错误:

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

我的自定义绑定处理程序:

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

打字稿定义文件:

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

我的观点:

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

我的页面模型:

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

我不确定为什么它说Flatpickr不是构造函数,当我将鼠标悬停在Visual Studio的new Flatpickr部分时,它会正确显示构造函数:{{3} }

1 个答案:

答案 0 :(得分:0)

问题出在我导入Flatpickr的方式上。我将import语句更改为以下内容:

import Flatpickr from 'flatpickr';

现在它有效。我不得不将自定义绑定处理程序更改为以下内容:

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