Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Input value not updated when manually changed and allowInput: true, altInput: true #639

Closed
airblade opened this issue Feb 23, 2017 · 6 comments

Comments

@airblade
Copy link

airblade commented Feb 23, 2017

Expected Behavior

I am trying to produce a text input field which the user can edit manually, and which displays the date in the UI in one format while always storing the date value in another format. Here's my code:

HTML:

<form>
  <input type="text" class="date" value="2017-02-23">
  <input type="submit">
<form>

JS:

flatpickr("input.date", {
  allowInput: true,
  altInput: true,
  altFormat: "j M Y",
  dateFormat: "Y-m-d"
});

The calendar picker itself works perfectly: the input field displays the date in its altFormat (e.g. 23 Feb 2017) and it is submitted to the server in the dateFormat (e.g. 2017-02-23), as expected.

I would expect to be able to type (directly into the input) a date in the same format as the displayed date.

Current Behavior

When I type directly into the input, the date I typed is not submitted when the form is submitted. Instead the original value is submitted.

Possible Solution

I'm new to this codebase, but it looks like altInput: true leads flatpickr to hide the original input and create a new one showing the date in its altFormat. I would guess that direct, non-calendar-picker changes to the visible input field are somehow not being passed on properly to the hidden input field.

UPDATE: after reading #578, I wonder whether this is due to parsing. I would expect to be able to directly type a date in the same format as the displayed date, i.e. altFormat. Maybe, though, it only works if I type a date in the underlying format, i.e. dateFormat. I tried it, and it works (if and only if) I also press <enter> straight afterwards. But that is impossible for the user to figure out; if we're displaying dates in altFormat, we should accept manually typed dates in altFormat.

Your Environment

  • Version used: 2.4.2
  • Browser Name and version: Chrome 56.0.2924.87 (64-bit)
  • Operating System and version (desktop or mobile): OS X 10.11.6
@airblade
Copy link
Author

Based on your comment here, I tried adding a parseDate option to my flatpickr config:

parseDate: function(dateString) { ... }

I couldn't tell from the docs whether my parseDate function was supposed to handle strings in dateFormat or altFormat. With some trial and error, it looks like it has to handle both.

Given that I only need to support two altFormats (d.m.Y and j M Y), and a dateFormat of Y-m-d, specifying my own parseDate function appears to solve the problem for me.

parseDate: function(dateString) {
  var match;
  // dateFormat
  match = dateString.match(/(\d{4})-(\d{2})-(\d{2})/);
  if (match != null) {
    return new Date(match[1], match[2] - 1, match[3]);
  }
  // altFormat 1
  match = dateString.match(/(\d{2})\.(\d{2})\.(\d{4})/);
  if (match != null) {
    return new Date(match[3], match[2] - 1, match[1]);
  }
  // altFormat 2
  match = dateString.match(/(\d{1,2}) (\w{3}) (\d{4})/);
  if (match != null) {
    return new Date(dateString);
  }
  // unparseable
  return new Date();
}

Without my parseDate function, flatpickr matches 23 Mar 2017 against timeRegex here, which sets the date to today (line 2099). Which explains the behaviour I was seeeing.

Anyway, is this the correct way to go?

@chmln
Copy link
Member

chmln commented Feb 24, 2017

@airblade Yes that's the way to go for now.

I've been seriously considering integrating a date parser, however.
The challenge is to accomplish it in minimal # lines of code.

@airblade
Copy link
Author

airblade commented Feb 24, 2017

OK, thanks for the confirmation.

I think the docs explain the difference between dateFormat and altFormat well, but it isn't clear (to me) what format Flatpickr uses to parse a date string from either the <input>'s initial value or the defaultDate option.

Regarding a date parser: I'd be happy with a very simple, no-surprises one built in; and the capability to replace it with something else, if I needed something more sophisticated.

In other words, don't clog up Flatpickr with a complicated date parser because Flatpickr's value is as a lightweight datetime picker, not a parser. Let a dedicated external parser handle the parsing and all the weird edge cases. For example rome leans on moment.js.

Anyway, thanks for a great plugin!

chmln added a commit that referenced this issue Feb 26, 2017
@Comp0ser
Copy link

*dig

You could also emit an enter press after blur occurs:

let picker = new Flatpickr(el, conf)
picker._input.addEventListener("blur", function(event) {
  let enter = new KeyboardEvent('keydown', {
    bubbles : true,
    cancelable : true,
    key : "Enter"
  })
  picker._input.dispatchEvent(enter)
}, true);

@FelixGraf
Copy link

@Comp0ser As mentioned in issue #1551 (comment) this can be done simply in the config object.

@evbrew
Copy link

evbrew commented Mar 12, 2024

*dig

You could also emit an enter press after blur occurs:

let picker = new Flatpickr(el, conf)
picker._input.addEventListener("blur", function(event) {
  let enter = new KeyboardEvent('keydown', {
    bubbles : true,
    cancelable : true,
    key : "Enter"
  })
  picker._input.dispatchEvent(enter)
}, true);

I needed something similar - came across numerous suggestions online (but none seemed to work) found 2 pull requests claiming to fix this issue (over a year old, frustrating!)

So using this as a base, this is what i came up with that seems to work on flatpickr v4.6.13
$("MyDateFieldSelectors").flatpickr(
{allowInput:true, altInput:true, altFormat:'m/d/Y', dateFormat: "Y-m-d",
onReady: function(selectedDates, dateStr, instance) {
//fp custom fix for input blur not trigging value update
let el = instance.altInput;

		el.addEventListener("focus", function(event) {
			//console.log('focus',el.value);
			el.setAttribute("data-fpcustom", el.value); // store the value on focus
		}, true);
		
		el.addEventListener("blur", function(event) {
		  //console.log('blur',el.dataset.fpcustom + ' ==? ' + el.value);
		  if(el.dataset.fpcustom == el.value) {return;} // if current value different then focused value, then trigger enter
		  let enter = new KeyboardEvent('keydown', {bubbles : true, cancelable : true, keyCode : 13});
		  instance._input.dispatchEvent(enter)
		}, true);
	 }
	}
);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants