Skip to content

Firing onchange before painting on input #5544

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

Closed
montyclt opened this issue Jul 1, 2018 · 7 comments
Closed

Firing onchange before painting on input #5544

montyclt opened this issue Jul 1, 2018 · 7 comments
Labels
area-blazor Includes: Blazor, Razor Components

Comments

@montyclt
Copy link

montyclt commented Jul 1, 2018

Hello everyone,

I have an input that I need that the user only writes in upper case.

I tried to do the following:

<input value="@Name" onchange="@ChangeName" />
void ChangeName(UIChangeEventArgs e)
{
    var value = (string)e.Value;

    Name = value.ToUpper();
}

The result:

The user writes in lowercase and when the user left focus, then the content transform to upper.

I tried too a hardcode value of Name property and left ChangeName method in blank like this:

<input class="form-control" value="@Name"/>
string Name = "Foo";

void ChangeName(UIChangeEventArgs e)
{
    // 
} 

I expected the original value of input return to "Foo", but when I leave the focus, the changed value stayed in the input.

Is possible make the value of input doesn't change if the value of value property doesn't change even if user type letters? (like readonly property)

Is possible to fire the onchange method before painting the input value to get in the input the value directly transformed while writing instead on lose focus? (like ReactJS)

@Worble
Copy link

Worble commented Jul 2, 2018

As far as I'm aware, Blazor only has support for the onchange event at the moment, which will only update when the element loses focus. If you need it to change on input, you'll probably need to write some JS that listens to the 'textInput' (www.w3.org/TR/DOM-Level-3-Events/#events-textevents) event on the element, which could potentially call a blazor method using interop if needed.

The second example, I'm not quite sure I'm understanding what is required. You're setting the 'value' attribute of the html to "Foo", which happens when the page is loaded. After that, if the user changes the input, the value attribute will change to that since that's how input elements work. If you don't want users to change the value, then consider not using a input element or use the readonly html attribute.

@montyclt
Copy link
Author

montyclt commented Jul 2, 2018

Hello @Worble,

Thank you!

I know the input has a value attribute that contains the initial value, and value property that contains the actual value.

The second example is directly related with the first example.

If the onchange event is fired before painting the new value in the input, and the event doesn't change the value, the old value must stay in the input like a readonly property.

I propose a onchange behavior like ReactJs (https://www.peterbe.com/plog/onchange-in-reactjs)

I will read your link about textInput event, maybe it could be what I need. Thank you!

@Andrzej-W
Copy link

In Blazor 0.4.0 there are a lot of different events including onkeydown, onkeyup, onkeypress but it is still difficult to implement what @montyclt wants. The biggest problem is the lack of "event is fully handled in my code". Here is a very simple and incomplete example:

<input bind="@TestValue" onkeypress="@KeyHandler" />
int TestValue { get; set; }
void KeyHandler(UIKeyboardEventArgs ev)
{
    if (ev.Key.CompareTo("+") == 0)
        TestValue++;
    else if (ev.Key.CompareTo("-") == 0)
        TestValue--;
}

Now you can press Plus or Minus key to increment or decrement value. Theoretically similar technique can be used to convert letters to uppercase. Unfortunately there are a lot of problems:

  1. There is no way to say that event is fully handled in my code. In this simple example Plus and Minus keys are fully handled in my code, but they are inserted into the input field 😢
  2. Handling text conversion Alternative 1: If you want to support editing you have to know the caret position (you have to know where to insert current character). You have to use JavaScript interoperability to get this information. Alternative 2: You can implement full editing (backspace, delete, arrow left, arrow right, etc.) in your C# code. This is probably good if you want to implement some advanced editing functionality. But yet again JS interoperability will be required to set current caret position. Alternative 3: You can also try to read current input field value, but I don't know how to do this from C#. Do we need JS interoperability for this? Maybe there is something ready to use in Blazor already.
  3. Let's assume all the above problems are solved. Your new value is rendered on screen and caret position is moved to the end of text. With this behaviour editing is almost impossible. How to set caret position? Probably it can be done in OnAfterRender through JS Interoperability.

As you can see at this stage of Blazor development there are a lot things we have to do in JavaScript.

@SteveSandersonMS maybe you have some suggestion. Here is our discussion from #803 Is this still unsolvable in Blazor?

AW: We should have a way to say that event was fully handled in our code (...)

SS: Unfortunately that might not be possible in general. The only way it could be possible is if the event raising code is synchronous. But longer term one of our goals is to support running Blazor across a boundary such as in a WebWorker. In that case, all JS-->.NET calls have to be async (even if the .NET->JS ones can be synchronous).

SS: Ultimately it's always possible to implement low-level things like a special keyboard event override in JS and encapsulate that in a component. Hopefully it's also possible to do nicely purely within the Blazor .NET model but would have to try it to determine any rough spots.

@NotAClue
Copy link

NotAClue commented Jul 4, 2018

Try using onblur?

@page "/ToUpperTest"

<input bind="@TestValue" onblur=@KeyHandler />

@functions  {
string TestValue { get; set; }

void KeyHandler()
{
    TestValue = TestValue.ToUpper();
}
}

@aspnet-hello aspnet-hello transferred this issue from dotnet/blazor Dec 17, 2018
@aspnet-hello aspnet-hello added area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates area-blazor Includes: Blazor, Razor Components labels Dec 17, 2018
@ag-petrov
Copy link

Having information about the caret position is a must when creating editor components. Any update on this?

Additionally is there any conception for cancellable events. For example I want to cancel the keypress event of an input element. Do I need to use JavaScript interoperability?

@SteveSandersonMS
Copy link
Member

Closing as a duplicate of #5545

The original requirement (text input, into which the all input is forced into uppercase) is handed quite easily using style="text-transform: uppercase" so it's presented in uppercase while typing, and then any other technique you like to convert the underlying string to uppercase before you use it. Example:

<input bind="@UserValue" style="text-transform: uppercase" />

You typed: @UserValue

@functions {
    string _userValue;
    public string UserValue
    {
        get => _userValue;
        set { _userValue = value.ToUpper(); }
    }
}

@SteveSandersonMS
Copy link
Member

SteveSandersonMS commented Mar 5, 2019

For example I want to cancel the keypress event of an input element. Do I need to use JavaScript interoperability?

In general, yes. Since this has to be synchronous, you can't use .NET code for that (e.g., because of Razor Components). Our hope is that this is a sufficiently rare case that it's not going to impact productivity much, and if there are scenarios that are common enough, we can come up with suitable helpers for it.

@mkArtakMSFT mkArtakMSFT removed area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates labels May 9, 2019
@ghost ghost locked as resolved and limited conversation to collaborators Dec 3, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components
Projects
None yet
Development

No branches or pull requests

8 participants