Knockout custom binding handler error: Not a constructor 'Flatpickr'
Knockout custom binding handler error: Not a constructor '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
部分时,它正确地显示了构造函数:
问题在于我如何导入 Flatpickr
。我将导入语句更改为以下内容:
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'));
}
};
我正在尝试为 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
部分时,它正确地显示了构造函数:
问题在于我如何导入 Flatpickr
。我将导入语句更改为以下内容:
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'));
}
};