Error message: Custom binding handler failed: 'Flatpickr' is not a valid constructor

Trying my hand at creating a custom binding handler in knockout for Flatpickr has hit a snag. Upon attempting to use it, an error is thrown:

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

The custom binding handler in question looks like this:

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

The associated Typescript definition file contains:

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

(...)

export = Flatpickr;

View snippet using the custom binding:

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

Model setup for the page:

class AssignmentModel {
    (...)

}

class AssignmentGroupModel {
    (...)    
}


A puzzling issue arises when indicating that Flatpickr is not recognized as a constructor. Despite Visual Studio displaying the constructor correctly upon hover.

Answer №1

The issue arose from how I was importing the Flatpickr library. I made adjustments to my import statement as shown below:

import Flatpickr from 'flatpickr';

With this change, everything is functioning properly now. I also updated my custom binding handler like so:

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Typescript monorepo facing issues with module resolution in Next.js projects

In my monorepo with yarn workspaces, I have 2 Next.js projects set up. apps ┣ app-1 ┗ app-2 The problem arises when app-1 needs to import components from app-2. I add app-2 as a dependency in the app-1 project and configure the path in app-1's ...

Error encountered when upgrading to Material-UI v5 rc.0 with typescript

After updating my material-ui to version v5-rc.0, I decided to implement styled-components. However, as I was working on my Component.styles.ts file, I encountered an error: The inferred type of 'StyledStepper' cannot be named without a referen ...

What is the correct method for packaging and using a TypeScript library built with webpack?

Recently delving into the world of TypeScript, I find myself struggling to grasp how to create a TypeScript library that can be utilized in another TypeScript module through webpack. This particular library is meant to be functional within a browser envir ...

How to Retrieve Inputs from Child Component Form without Prop Passing?

Within the Parent component below, there is a Dropdown menu with two options. Selecting "TOP LEVEL" will display Form1, while selecting "MAKE ITEM" will show Form2. If no option is selected, both forms remain hidden. The Parent component also contains a Bu ...

Error in Protractor Typescript: The 'By' type does not share any properties with the 'Locator' type

https://i.stack.imgur.com/8j2PR.png All the different versions Error. Protractor version : 5.2.0 npm : 3.10.10 node :6.9.5 typescript :2.6.0 The 'By' type does not share any properties with the 'Locator' type What is the solution to ...

Tips for verifying the variable type in a TypeScript ESLint custom rule

Trying my hand at creating a custom TypeScript-eslint rule that requires the callee's object of a node to be of a specific type, which I'll refer to as MyType. Utilizing the CallExpression from typescript-eslint in the code snippet below: Source ...

Unable to generate a store using reducer in TypeScript and Redux

I am having trouble creating a store using Redux and TypeScript. Here is my actions.js file: import { Action } from 'redux'; export interface ITodoAction extends Action { todo:string; } export const ADD_TODO:string = 'ADD_TODO'; ...

How can I use the Required utility type in TypeScript for nested properties?

I'm exploring how to utilize the Required keyword to ensure that all members are not optional in TypeScript. I've achieved success with it so far, but I've run into an issue where it doesn't seem to work for nested members of an interfa ...

Encountering an error when attempting to include React TypeScript onChange with a Material UI switch component

I'm working on implementing a show/hide functionality using a switch. I want the component to be displayed when the switch is turned on and hidden when it's turned off. Here's the code I've written: const VirtualEventSection = ({ con ...

Converting time from 00:00:01 to a format of 8 minutes and 49 seconds in Angular

Is there a way to transform a time value from 00:00:01 (not a date object) into a format showing 8 minutes and 49 seconds? Even after consulting the Angular 'date pipe' documentation, I couldn't find a solution to this issue. ...

Choosing to overload the plainToClass function may result in a type error

I've been tasked with compiling an angular project that contains mostly code written by someone else. Although the example below compiles successfully on one machine, it throws an error on different machines. import { plainToClass } from 'class ...

Sending a `refresh` to a Context

I'm struggling to pass a refetch function from a useQuery() hook into a context in order to call it within the context. I've been facing issues with type mismatches, and sometimes the app crashes with an error saying that refetch() is not a funct ...

What is the process for accessing getBoundingClientRect within the Vue Composition API?

While I understand that in Vue we can access template refs to use getBoundingClientRect() with the options API like this: const rect = this.$refs.image.$el.getBoundingClientRect(); I am now attempting to achieve the same using template refs within the com ...

Encountering an issue with the UNION operator in Typescript causes an error

Currently, I am utilizing the OR operator within Typescript to designate that a product could be of type ProductI OR CartResponseInterface.Product This is how it is structured: product: ProductI | CartResponseInterface.Product However, when attempting t ...

Is there a more efficient method for invoking `emit` in Vue's Composition API from an external file?

Is there a more efficient way to access the emit function in a separate logic file? This is my current approach that is functioning well: foo.js export default (emit) => { const foo = () => { emit('bar') }; return { foo }; } When ...

The property of the Angular Typescript object is distinctly not defined, yet the property itself is

Currently facing a bizarre issue. Even though the console displays data in an object from a subscribed observable, TypeScript code shows it as undefined. Take a look: initData(): void { this.backendService.getData().subscribe((depotDays: DepotDayAcc ...

The combination of React, Typescript, and MaterialUI Paper results in a stunning design with a sleek and

Whenever I include <Paper elevation={0} /> within my react component, I encounter the following issue: Cannot read properties of undefined (reading 'background') TypeError: Cannot read properties of undefined (reading 'background&apos ...

The character 'T' cannot be assigned to the data type 'number'

When working with an optional type argument function RECT(T), I encountered a situation where I need to check if the argument is an instance of date. If it is, I convert it to a number; if not, I use the number directly. However, I keep getting an error ...

How to convert an attribute of an object within a list to a string separated by commas in TypeScript and Angular

I am working with an array of person objects in Angular 5 and displaying them in HTML using ngFor. The Person objects also contain an array of Role objects. persons:Array<Person>=[]; Each Role object is structured like this: export class Role{ ...

Passing values in onPress method of TouchableOpacity without using arrow functions or bind function can be achieved by using JSX props. Remember not to use arrow functions in JSX props

I am working on a React Native project and I have a TouchableOpacity component in my view with an onPress method. I want to avoid using arrow functions and bind functions in the onPress method as it creates a new function every time. My goal is to pass par ...