Open Kevin-Andrew opened 1 year ago
Thanks for reporting this, @Kevin-Andrew. I think this whole issue comes down to the fact that assigning someTextArea.textContent
stops changing the UI once the user has edited the textarea. You can reproduce this in a single line of pure JS without involving Blazor, e.g.: https://jsfiddle.net/rocd8qhp/
I agree that it would be helpful for Blazor to work around this internally. We could do so by special-casing textarea
elements in BrowserRenderer.ts
so that, after assigning .textContent
to any node inside a textarea
, we also assign textArea.value = textArea.textContent
. That would also fix things if the content is a compound value (e.g., <textarea>Some text @withAVariable</textarea>
). Maybe there are other solutions to consider too.
In the meantime I recommend you use the value
attribute instead. This will always produce the correct behavior when rendering interactively, because Blazor assigns the textarea's value attribute as being a DOM element property rather than an HTML attribute. It will not produce the expected output when prerendering, so if you want to cover all bases, consider doing this:
<textarea value="@someValue">@someValue</textarea>
Thanks for contacting us.
We're moving this issue to the .NET 8 Planning
milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.
@SteveSandersonMS, I'm a bit confused by your reply. Specifically, your mentioning and use of someTextArea.textContent
and your provided JSFiddle. What I mean by that, is according to the specifications here and here, there is no documentation that suggests using textContent
when it comes to programmatically changing the value of a <textarea>
.
Doing an Internet search for "javascript set textarea text" (without the quotes), in all search engines, the first result is to: https://stackoverflow.com/questions/1642447/how-to-change-the-content-of-a-textarea-with-javascript, which was posted over 13 years ago. And again, even in it, there is no mention of using a textContent
property on the <textarea>
in JavaScript.
Instead, when using JavaScript, you are supposed to use the value
property. I have taken your JSFiddle and modified it to show the correct, working example: https://jsfiddle.net/dgtaz1n7/
Therefore, I would not consider your example to be an accurate representation of the problem and try to blame the problem on the web browser. In my opinion, you're not using the right tool for the job. So of course it's not going to function correctly.
There appears to be a misunderstanding around the <textarea>
element. With a <textarea>
, there is a difference between the value seen on the screen and what the initial value is in the DOM. With a <textarea>
, there is effectively an extra property, defaultValue
: https://www.w3schools.com/jsref/prop_textarea_defaultvalue.asp
When Blazor updates the DOM by changing the text between the tags of a <textarea>
, by using .textContent
or whatever, to a web browser, it is only changing the defautlValue
, not the value
which is what is currently displayed on the screen. And let's be honest, the intent of every developer, when using Blazor to update the text of a <textarea>
is to have that updated text be displayed on the screen, not the underlying default value in the DOM.
So while the use of .textContent
may work for other elements, something else needs to be done with a <textarea>
to be able to get the developer's intent, by default, of having the value displayed on the screen of a <textarea>
be updated. If the developer truly wants to set the defaultValue
of a <textarea>
, perhaps Blazor can offer some special case way of doing that.
I appreciate you taking the time that you have thus far. But I really hope you give this more consideration. At a minimum, this should be documented to try and clear up that misunderstanding and explain the difference between the defaultValue
versus the value
seen on screen, and how to change each of them using Blazor.
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.
Is there an existing issue for this?
Describe the bug
If you have a
That code will initialize the with the string from the . This is the recommended practice for initializing a in HTML. What I mean by that is, according to https://www.w3schools.com/tags/tag_textarea.asp, a does not, for example, have/support a
GetData(someParameter)
method, which is placed between the opening and closing tag of thevalue
attribute like other<input>
elements.Then, because we also want to get any changes that the user may make to the text, we wire up the. In the first example of the following documentation, https://learn.microsoft.com/en-us/aspnet/core/blazor/components/data-binding?view=aspnetcore-6.0, it says the same thing:
onchange
event. This should conceptually and effectively give us two-way binding of theAgain, the reason why we don't simply just use a is because we don't have a bindable property. The data is coming from a method.
@bind
attribute on theInitially, this code appears to work. However, in the following complete example, it does not work as expected. You can download the example from the repo, but I'll also outline and include most of the details and code directly here too for others to quickly see and read.
Create a new solution/project using either the Blazor WebAssembly App or Blazor Server App project templates: In the
Index.razor
page, replace the code with the following:Run/debug the app and follow the instructions by clicking on both links to see the initial data: and
Then change the text in the of the first link:
Finally, click on the "Method 2" link and notice that the text in the is not updated:
As you see in the example, I have also include an
<input type="text">
element. With an<input type="text">
element, the proper way to set/initialize the text value is to set thevalue
attribute. So we can accomplish what we need to do, that is, conceptually/effectively perform two-way binding by setting thevalue
attribute to the result of theGetData(someParameter)
method and wiring up and handling the@onchange
event.If you noticed in the last screen shot, the text in the regular text box was correctly updated. So why wasn't the? We can take it a step further and have the user change the text in the regular text box too, then click back and forth between the two links and the text in the text box is always updated correctly:
So why is the behavior between those to, very similar elements, different?
Doing more tests on my own, I also discovered that if you change the to instead use/have a
value
attribute, which again, according to the HTML specification is not a valid attribute, then the behavior is as expected and matches that of the regular<input type="text">
element. At least, in this simple example, that workaround yields the correct/desired behavior. However, in my real project, that workaround still doesn't give the correct/expected behavior.I have found and read the following: https://github.com/dotnet/aspnetcore/issues/45797 I have also read the following, that is new in .NET 7. https://learn.microsoft.com/en-us/aspnet/core/blazor/components/data-binding?view=aspnetcore-7.0#use-bindgetbindset-modifiers-and-avoid-event-handlers-for-two-way-data-binding But in my example, I'm not trying to do. Specifically, I am not attempting to modify the value that the user enters and expect Blazor to render that modified value.
I have not tried the new
@bind:get/@bind:set
modifiers available in .NET 7 to know whether or not it would fix my problem. But if the new@bind:get
only supports binding to a C# property, then no, that won't solve my problem because I need to pass in a parameter to a method.Expected Behavior
Having said all of that, I have worked around all of the issues, but I wanted to report this nonetheless and at least try to get an answer to the following: Why, in the provided example code, is there a behavior difference between a that is written as:
versus being written as:
To me, the second one, that uses the
value
attribute, shouldn't even be allowed. But at a minimum, isn't it a bug that those two behave differently?Steps To Reproduce
https://github.com/Kevin-Andrew/BlazorTextAreaNotUpdating
Exceptions (if any)
No response
.NET Version
.NET 6
Anything else?
No response