To prove Blazor updates existing browser DOM elements we’ll create some JavaScript that will take Blazor generated elements and update them in a way Blazor does not know about. We’ll then get Blazor to update its view and observe that the JavaScript changes are not lost.
Create a default app, and then in /Pages/Index.razor make the following changes:
- Add a
List<string>member with some initial values. - Add some mark-up to render the values of that list.
- Add a button that, when clicked, will call a C# method to update the values in the list.
@page "/"
<h1>Hello, world!</h1>
Welcome to your new app.
<button @onclick=@ChangeData>Change data</button>
<ol>
@foreach(string item in Items)
{
<li>@item</li>
}
</ol>
<SurveyPrompt Title="How is Blazor working for you?" />
@code {
List<string> Items = new List<string> { "One", "Two", "3" };
void ChangeData()
{
Items[0] = "1";
Items[1] = "2";
Items.Add("4");
}
}

Main page showing values of list
Now that we have some Blazor generated elements, we need to use some JavaScript to alter those elements.
If you are using the standalone Blazor WebAssembly template, edit /wwwroot/index.html.
For a Blazor Web App (the default template), there is no editable HTML host page; the app is rendered server-side.
To follow along with this experiment, create a Blazor WebAssembly project or add a wwwroot/index.html to your project.
Inside the opening <body> element add a button, and above the closing </body> add
a script to update the existing <li> elements.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>MyFirstBlazorApp</title>
<base href="/" />
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/site.css" rel="stylesheet" />
</head>
<body>
<button id="setValues">Set values</button>
<app>Loading...</app>
<script src="\_framework/blazor.webassembly.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
document.getElementById('setValues').addEventListener('click', function () {
document.querySelectorAll('li').forEach(function (elem) {
elem.setAttribute('originalValue', elem.textContent);
});
});
});
</script>
</body>
</html>
- Line 12 adds a button in the HTML.
- Line 17 adds a script that finds all
<li>elements, gets their currenttext, and then assigns that to a new attribute namedoriginalValue.
Run the app, and right-click the first <li> element on the page and inspect it. Initially,
the elements will look like this:
<ol>
<li>One</li>
<li>Two</li>
<li>3</li>
</ol>
Next click the new Set values button at the top of the page,
this will execute the JavaScript to add a new attribute to each <li> to record the original text it held.

Main page with new Set values button
You should now see the elements in the browser's element inspector change to the following:
<ol>
<li originalValue="One">One</li>
<li originalValue="Two">Two</li>
<li originalValue="3">3</li>
</ol>
Finally, click the Change data button. This will execute C# code to change the values in the List<string>,
Blazor will then re-render its view. Inspecting the elements now should show the following:
<ol>
<li originalValue="One">1</li>
<li originalValue="Two">2</li>
<li originalValue="3">3</li>
<li>4</li>
</ol>
- The item with the text "One" had its text changed to "1".
- The item with the text "Two" had its text changed to "2".
- The item with the text "3" remained unchanged.
- Add new item with the text "4" was added.
We can see the existing elements were reused by the fact that the elements' originalValue attributes are not generated
by Blazor and yet they still exist.
The new element, that was newly created by Blazor, does not have an originalValue attribute.
Caution: Mutating Blazor-managed DOM directly from JavaScript is an experiment to demonstrate how Blazor reuses elements, not a production pattern. Interfering with the DOM that Blazor owns can lead to unpredictable behavior. For proper interop, use JSInvokable methods and ElementReference.
Now that we have seen how Blazor matches elements positionally, read about Optimising using @key to learn how to improve diffing when elements are reordered.
