Search code examples
javascriptdatepickerjsrenderjsviewsflatpickr

Bind value attribute from input field to JsViews Observables


I am trying to bind the value=".."-attribute from an <input>-field to a JsViews observable, so that changes made from a JS datepicker will get detected by the JsView framework.

Example

On initial rendering, the data-linked observedDate parameter is displayed in the <input>-field:

<input class="flatpickr-calendar" type="text" data-link="observedDate">

Then, selecting a new date using the flatpickr javascript tool, the new date will be stored in the value=".."-field:

<input class="flatpickr-calendar" type="text" data-link="observedDate" value="2017-05-09">

The problem

There is now a divergence between the date handled by observedDate and the value-attribute:

JsViews does not detect the change in the value-attribute.


Does anyone have some suggestion as of how to handle this situation? Thanks.


Solution

  • You need an event onChange update value observedDate.

    For example, you can do so:

    $(".flatpickr").flatpickr({
        onChange: function(selectedDates, dateStr, instance) {
            $.observable($.view(this.input).data).setProperty("observedDate", dateStr);
        },
    });
    

    full code.

    Update

    Or you can create custom tag:

    $.views.tags({
        flatpickr: {
            template: "<input/>",
            onUpdate: false,
            dataBoundOnly: true,
    
            flatpickr: null,
            isChange: false,
            changeEvent: function (selectedDates, dateStr, instance) {
                this.isChange = true;
                this.update(dateStr);
                this.isChange = false;
            },
    
            onDispose: function () {
                if (this.flatpickr) {
                    this.flatpickr.destroy();
                }
            },
    
            onAfterLink: function (tagCtx, linkCtx) {
                var tag = this;
                var props = tagCtx.props;
                var options = {
                    defaultDate: tagCtx.args[0]
                };
    
                if (tag._.unlinked) {
                    if (!tag.linkedElem) {
                        tag.linkedElem = tag._.inline ? tag.contents("*").first() : $(linkCtx.elem);
                    }
                    $.each(props, function (key, prop) {
                        var option;
                        if (key.charAt(0) === "_") {
                            key = key.slice(1);
                            options[key] = prop;
                        }
                    });
    
                    options.onChange = $.proxy(tag.changeEvent, tag);
                    this.flatpickr = tag.linkedElem.flatpickr(options);
                } else {
                    if (!this.isChange) {
                        this.flatpickr.setDate(options.defaultDate)
                    }
                }
            }
    
        }
    });
    

    And use:

    {^{flatpickr observedDate /}}
    

    full code

    Support flatpickr options:

    {^{flatpickr observedDate _inline=true _maxDate='2018-05-01' _minDate='2017-05-01'/}}
    

    full code