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

localized date incorrectly submitted as part of <form> #21

Closed
wimdeblauwe opened this issue Sep 22, 2020 · 18 comments · Fixed by #43
Closed

localized date incorrectly submitted as part of <form> #21

wimdeblauwe opened this issue Sep 22, 2020 · 18 comments · Fixed by #43
Labels
bug Something isn't working

Comments

@wimdeblauwe
Copy link

I am trying to use duet-date-picker with Thymeleaf (server-side rendering). It works as long as I don't use the localization support.

I added this in a <script> tag in my page:

    const picker = document.querySelector('duet-date-picker');
    const DATE_FORMAT = /^(\d{1,2})\.(\d{1,2})\.(\d{4})$/;

    if (picker) {
        picker.dateAdapter = {
            parse(value = '', createDate) {
                try {
                    console.log('parsing' + value);
                    const matches = value.match(DATE_FORMAT);

                    if (matches) {
                        return createDate(matches[3], matches[2], matches[1]);
                    }
                } catch (err) {
                    console.log(err);
                }
            },
            format(date) {
                console.log('formatting: ' + date);
                return `${date.getDate()}.${date.getMonth() + 1}.${date.getFullYear()}`;
            },
        };
    }

I see lot's of formatting... statements, but never parsing... and also no error in the console.

When I check with dev tools, I see updates to the value attribute of <duet-date-picker>, but the value of the actual <input> is not updated. Due to this, my server-side thinks that nothing was selected. For some reason, that does not seem to be an issue when not using the localization support. Am I doing something wrong?

@WickyNilliams
Copy link
Contributor

WickyNilliams commented Sep 24, 2020

Parsing is only used when typing into the input itself with a keyboard. All values passed as props should be in ISO-8601 format, not your locale. Is that where you've gone wrong?

I'm on my mobile, so this is just a guess :)

@wimdeblauwe
Copy link
Author

What do you mean with "values passed as props"? The value of the <input> is what Spring will look at when the form is POST'ed to the server. I would think that the component keeps that up to date itself?

@WickyNilliams
Copy link
Contributor

WickyNilliams commented Sep 25, 2020

I mean even if you are using localisation, you should still pass dates in ISO format:

<duet-date-picker
  value="2020-09-25">
</duet-date-picker>

Can you confirm you're doing this?

@wimdeblauwe
Copy link
Author

I am indeed doing this when the page is generated on the server initially. The proper value is shown according to the format function. But if I select a different date using the picker and submit the form, then the server receives no value for the <input>.

@WickyNilliams
Copy link
Contributor

OK, I think the issue title threw me off as it seems unrelated to what you're describing. Could you share some of your code?

@wimdeblauwe
Copy link
Author

Sure. So I have added the js and css in my <head> section:

    <script type="module" src="https://cdn.jsdelivr.net/npm/@duetds/date-picker@1.0.1/dist/duet/duet.esm.js"></script>
    <script nomodule src="https://cdn.jsdelivr.net/npm/@duetds/date-picker@1.0.1/dist/duet/duet.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@duetds/date-picker@1.0.1/dist/duet/themes/default.css"/>

The Thymeleaf code that uses the component looks like this:

<duet-date-picker th:identifier="${fieldName}"
                          th:value="*{__${fieldName}__}"
                          th:name="${fieldName}"
                          class="w-full sm:text-sm sm:leading-5"
                          th:classappend="${#fields.hasErrors('__${fieldName}__')?'error-border':''}">
        </duet-date-picker>

This renders in the browser like this:

image

You can see that the custom format function is being used.

This is the HTML that Chrome dev tools shows:

image

You can see that the value has the correct ISO-8601 format.

If I select a different date using the picker, I can see the value change to the selected date (in ISO-8601 format).

When I post the form after that, I get a validation error that the value is not present.

If I remove the code to overwrite the dateAdapter, then the value is shown to the user in ISO-8601 format:

image

The HTML looks the same to me:

image

And posting the form works without issues after selecting a different date (or not selecting any date at all).

@WickyNilliams
Copy link
Contributor

WickyNilliams commented Sep 28, 2020

Having done some investigation, the input is being submitted, but it's being submitted with the localised value. e.g. so in this case you'll get a form submission with birthday=6.9.2020. So it probably fails to parse on your server.

I think a fix for this would be to have a hidden input (within the component, not for you to add), which would store the current ISO value and participate in form submission. The text input is then purely for the purpose of display/manual entry

@arielsalminen arielsalminen added the enhancement New feature or request label Sep 28, 2020
@wimdeblauwe
Copy link
Author

Yes, that would be great. Is this something that could be fixed on short term? I am writing a book about Thymeleaf and wanted to include an example of using a date picker. I'd love to use this one, but I would need a fix for this, preferably in the coming weeks if that is possible?

@WickyNilliams
Copy link
Contributor

WickyNilliams commented Sep 28, 2020

I think we should be able to get a fix out this week or next. It won't be a big change on our end.

You might be able to work around it with something like this (not tested!!):

<duet-date-picker name=""></duet-date-picker>
<input type="hidden" name="birthday" />

<script>
  const picker = document.querySelector("duet-date-picker");
  const hidden = document.querySelector(`input[type="hidden"]`);

  picker.dateAdapter = {
    parse(value = "", createDate) {
      try {
        console.log("parsing" + value);
        const matches = value.match(DATE_FORMAT);

        if (matches) {
          return createDate(matches[3], matches[2], matches[1]);
        }
      } catch (err) {
        console.log(err);
      }
    },
    format(date) {
      console.log("formatting: " + date);
      return `${date.getDate()}.${date.getMonth() + 1}.${date.getFullYear()}`;
    },
  };

  picker.addEventListener("duetChange", (e) => {
    hidden.value = e.detail.value
  });
</script>

Basically, copy the value on change into a hidden input yourself. But that's a bit of a hack, and is essentially what we'd end up doing behind the scenes

@wimdeblauwe
Copy link
Author

ok, great. I'll wait for the update. Thanks!

@WickyNilliams
Copy link
Contributor

I'm going to edit the issue title to better reflect the problem, hope that's ok!

@WickyNilliams WickyNilliams added bug Something isn't working and removed enhancement New feature or request labels Oct 7, 2020
@WickyNilliams WickyNilliams changed the title parse method never called when using localization? localized date incorrectly submitted as part of <form> Oct 7, 2020
@wimdeblauwe
Copy link
Author

@WickyNilliams Any idea when a fix can be released on this?

@WickyNilliams
Copy link
Contributor

Sorry, this fell through the net. I'll see if i can get a PR together tomorrow

@WickyNilliams
Copy link
Contributor

WickyNilliams commented Oct 30, 2020

PR ready here: #43. Feel free to test @wimdeblauwe and let me know if it works for you :)

@wimdeblauwe
Copy link
Author

Thanks! How can I get the binaries to test?

@wimdeblauwe
Copy link
Author

Is this included in the 1.1.0 release? Or can I see release notes somewhere?

@WickyNilliams
Copy link
Contributor

Yes, it is included. There's not much by the way of release notes (there is a short changelog in the readme).

Using this code as an example, you will now always get an ISO date submitted via the form, despite using a British date adapter (omitted for conciseness):

<form>
  <duet-date-picker name="date"></duet-date-picker>
  <button type="submit">Submit</button>
</form>

<script>
  const picker = document.querySelector("duet-date-picker");
  picker.dateAdapter = britishDateAdapter
</script>

Hope that helps

@wimdeblauwe
Copy link
Author

I can confirm it works with version 1.1.0. Thanks for the bugfix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

Successfully merging a pull request may close this issue.

3 participants