MudBlazor icon indicating copy to clipboard operation
MudBlazor copied to clipboard

MudDatePicker with mask jump back caret on input in Server Side

Open altbodhi opened this issue 1 year ago • 22 comments

Bug type

Component

Component name

MudDatePicker

What happened?

When i develop local it not visible, but if publish on remote linux. Linux on low resources VM. I see how every cursor jumping back if i type quickly. <MudDatePicker Label="Date" @bind-Date="@DocDate" Editable="true" Clearable="true" Mask="@(new DateMask("dd.MM.yyyy"))" DateFormat="dd.MM.yyyy" > </MudDatePicker>

Expected behavior

In Remote ServerSide App if quickly type from keyboard date caret in field stay at end of input.

Reproduction link

https://try.mudblazor.com/snippet/cEcxOzkyxAkCxykM

Reproduction steps

  1. run server side app with datepicker with mask editable and clearable.
  2. in developer console browser set network type to slow 3g
  3. try quickly type from keyboard date. for example 12.12.12, result 12.12.1|2 or even worse like 1012002

Relevant log output

No response

Version (bug)

6.1.8

Version (working)

No response

What browsers are you seeing the problem on?

Firefox, Chrome, Microsoft Edge

On what operating system are you experiencing the issue?

Windows

Pull Request

  • [ ] I would like to do a Pull Request

Code of Conduct

  • [X] I agree to follow this project's Code of Conduct

altbodhi avatar May 04 '23 10:05 altbodhi

I think this is because mask computed on server. Better if it will be on client side.

altbodhi avatar May 10 '23 02:05 altbodhi

Hi @altbodhi, the cursor jumping is due to server side latency. You can try using Cleave.js locally instead.

Mr-Technician avatar May 11 '23 18:05 Mr-Technician

Hi @altbodhi, the cursor jumping is due to server side latency. You can try using Cleave.js locally instead.

Cleave.js applied to MudDatePicker is work but on enter to change date, in MudDatePicker without js masked if i type Enter it change value.

altbodhi avatar May 12 '23 09:05 altbodhi

Also having this issue. Is anyone able to share an example or reference showing how to apply Cleave.js to this situation? Thanks

dennml avatar Jul 27 '23 07:07 dennml

Same with me. I would greatly appreciate it if anyone could provide an example or reference demonstrating how to apply Cleave.js in this particular situation.

csuka1219 avatar Jul 28 '23 09:07 csuka1219

Hi, i figured out, here is a short example of how to implement it: https://github.com/csuka1219/CleaveMudDateMask

csuka1219 avatar Aug 09 '23 20:08 csuka1219

Hi, i figured out, here is a short example of how to implement it: https://github.com/csuka1219/CleaveMudDateMask

I am try to use your example with slow 3g settings but it work unstable. 1) not apply mask if reload page 2) after start mask work but value not aply to component.

altbodhi avatar Aug 10 '23 02:08 altbodhi

For me it works well, the only problem is that i need to click out of the datepicker component's focus to bind the value to the DateTime variable, I'm working on the solution of the problem.

csuka1219 avatar Aug 10 '23 13:08 csuka1219

For me it works well, the only problem is that i need to click out of the datepicker component's focus to bind the value to the DateTime variable, I'm working on the solution of the problem.

Thanks @csuka1219 your solution is really appreciated. The masking works well for me with no cursor jumping but I also have the problem you mentioned. It does not bind until the element loses focus. In my case I need it to bind once the text is a valid date but I have not found a way to do that or access the string from blazor code. If you have any progress of tips I would be very grateful.

dennml avatar Aug 17 '23 03:08 dennml

Hey @dennml, I think I've found a possible solution. I've added a commented line to the example, please uncomment it and give it a try. I would be grateful if You could let me know later it's solved your problem or not. The point is, I've also set the MudBlazor mask to the component. I don't think its the best way, but if you try every datepicker example on https://mudblazor.com/components/datepicker#api you'll see that none of them bind dynamically except for the masked ones.

csuka1219 avatar Aug 17 '23 08:08 csuka1219

@dennml If You want to access to the string you can override the StringValueChanged method like this:

        protected override Task StringValueChanged(string value)
        {
            if(value.Length == 10) //or smth like this
            {
                //Do smth

               //or you can call this method, it's set the component date value
               SetDateAsync(Converter.Get(value), false);
               
               //Or just like this
               base.Date = smthStringToDate(value);
            }

            return base.StringValueChanged(value);
        }

csuka1219 avatar Aug 17 '23 09:08 csuka1219

@csuka1219 I was trying with

        protected override Task StringValueChanged(string value)
        {
            if (!string.IsNullOrEmpty(value))
            {                
                if (DateTime.TryParseExact(value, DateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime validDate))
                {
                    Date = validDate;
                }
            }

            return base.StringValueChanged(value);
        }

But the problem is that StringValueChanged is not invoked when I type into the MudDateField from your github sample. It is only invoked if the focus changes away from that component. If that was invoked when typing, it would set the Date value as soon as a valid date is typed. I can confirm that StringValueChanged does get invoked when typing if I set Mask like the commented line in your sample. However that causes the original issue where the caret jumps around with the mud masking; exactly the issue we're trying to avoid. This seems to indicate that StringValueChanged does not get invoked by MudBlazor when typing if Mask is null. If we could change that so it does get invoked, I think your solution with cleave.js would work perfectly.

dennml avatar Aug 18 '23 07:08 dennml

what do you think about fix bug without any js code? maybe in datepicker has some wrong async (not synchronized) calls.

altbodhi avatar Aug 18 '23 08:08 altbodhi

I created a new issue #7391 and raised a PR so that TextChanged and StringValueChanged will be invoked as the user types.

dennml avatar Aug 21 '23 08:08 dennml

what do you think about fix bug without any js code? maybe in datepicker has some wrong async (not synchronized) calls.

If someone is able to address this purely in MudBlazor, I'm sure that would be the preferred solution. Is this something you're able to look into @altbodhi ?

For now I've raised a PR to help with the cleave.js approach and other useful scenarios such as the snippet I created in #7391

dennml avatar Aug 21 '23 08:08 dennml

what do you think about fix bug without any js code? maybe in datepicker has some wrong async (not synchronized) calls.

It is my understanding that this problem is impossible to fix in C# on server side blazor. The problem is simply the nature how BSS works:

image

That's why the only feasible solution for masking on BSS is to do it directly on the browser in JS.

henon avatar Aug 25 '23 14:08 henon

May be simply skip update input if it not equal?

altbodhi avatar Aug 25 '23 23:08 altbodhi

@altbodhi That would be a JavaScript solution (and I wouldn't even know how to do this, because you would fight the Blazor engine), above you suggested a C# solution.

Clearly doing masking in JavaScript is the easier and cleaner way.

henon avatar Aug 26 '23 18:08 henon

@csuka1219 the latest MudBlazor 6.10.0 has the new ImmediateText parameter. You may want set that to true and try again with your Cleave.js solution.

dennml avatar Sep 15 '23 04:09 dennml

@dennml Thank you for notifying me. I have implemented it, and now it works well.

csuka1219 avatar Sep 15 '23 08:09 csuka1219

@csuka1219 -- how were you able to implement it?

I'm running into the same issue -- where my caret jumps around due to being Blazor Server-- and I've got the eventListener firing as expected and cleave-zen formats the string, but I've been completely unable to inject the value back into the input in a way that updates the MudDatePicker text box.

matneyx avatar Feb 15 '24 22:02 matneyx

@matneyx Here is a working demo, but you can ask me anything if something isn't clear. https://github.com/csuka1219/CleaveMudDateMask

csuka1219 avatar Feb 15 '24 23:02 csuka1219