Yesterday I posted how to create a CRUD App using Blazor and ASP.NET Core and got a good response from folks on Facebook and Twitter. This Blazor app is using JavaScript for showing/hiding the HTML elements on the page. David Masterson on twitter pointed out that it can be done in another neat way that too without JavaScript and I thought of sharing with you (with his permission) how to update the same CRUD blazor app with no dependency on JavaScript.
Let’s add another component named ToDoWithoutJS.cshtml
to our blazor app with the following code. Previously, we were calling the JavaScript method on click on Edit, Update and Cancel button. This code makes use of the two-way data binding feature to set the display of HTML controls.
@page "/anothertodo" | |
@using ASPNETBlazorCRUDApp.Shared | |
@inject HttpClient Http | |
<h1>ToDo List</h1> | |
<div> | |
<div class="row"> | |
<div class="col-sm-1"> | |
<p>Item:</p> | |
</div> | |
<div class="col-sm-4"> | |
<input id="todoName" placeholder="Item Name" @bind(itemName)> | |
</div> | |
</div> | |
<br /> | |
<div class="row"> | |
<div class="col-sm-1"> | |
<button class="btn btn-info" id="btnAdd" @onclick(async () => await AddToDo())>Add</button> | |
</div> | |
<div class="col-sm-2"> | |
@if (todos != null && todos.Count > 0) | |
{ | |
<button class="btn btn-danger" @onclick(async () => await DeleteAllToDos())>Delete All</button> | |
} | |
</div> | |
</div> | |
</div> | |
<br /><br /> | |
@if (todos == null) | |
{ | |
<p><em>Loading...</em></p> | |
} | |
else | |
{ | |
@if (todos.Count > 0) | |
{ | |
<table class='table table-striped table-bordered table-hover table-condensed' style="width:80%;"> | |
<thead> | |
<tr> | |
<th style="width: 40%">Name</th> | |
<th style="width: 40%">Edit</th> | |
<th style="width: 20%">Delete</th> | |
</tr> | |
</thead> | |
<tbody> | |
@foreach (var todo in todos) | |
{ | |
<tr> | |
<td> | |
<span style="display:@HideOnEditing(todo.ID);">@todo.Item</span> | |
<input style="display:@ShowOnEditing(todo.ID);" @bind(todo.Item) /> | |
</td> | |
<td> | |
<button style="display:@HideOnEditing(todo.ID);" class="btn btn-primary" @onclick(() => EditToDo(todo))>Edit</button> | |
<button style="display:@ShowOnEditing(todo.ID);" class="btn btn-success" @onclick(async () => await UpdateToDo(todo))>Update</button> | |
<button style="display:@ShowOnEditing(todo.ID);" class="btn btn-primary" @onclick(() => CancelToDo())>Cancel</button> | |
</td> | |
<td><button class="btn btn-danger" @onclick(async () => await DeleteToDo(todo.ID))>Delete</button></td> | |
</tr> | |
} | |
</tbody> | |
</table> | |
} | |
} | |
@functions { | |
string itemName; | |
int SelectedID = -1; | |
IList<ToDoList> todos = new List<ToDoList>(); | |
protected override async Task OnInitAsync() | |
{ | |
await Refresh(); | |
} | |
String ShowOnEditing(int _id) | |
{ | |
return (SelectedID == _id) ? "" : "none"; | |
} | |
String HideOnEditing(int _id) | |
{ | |
return (SelectedID == _id) ? "none" : ""; | |
} | |
private async Task Refresh() | |
{ | |
todos = await Http.GetJsonAsync<ToDoList[]>("/api/ToDo"); | |
StateHasChanged(); | |
} | |
private async Task AddToDo() | |
{ | |
if (!string.IsNullOrEmpty(itemName)) | |
{ | |
await Http.SendJsonAsync(HttpMethod.Post, "/api/ToDo", new ToDoList | |
{ | |
Item = itemName, | |
}); | |
itemName = ""; | |
await Refresh(); | |
} | |
} | |
private async Task UpdateToDo(ToDoList todo) | |
{ | |
if (!string.IsNullOrEmpty(todo.Item)) | |
{ | |
await Http.SendJsonAsync(HttpMethod.Put, $"/api/ToDo/{todo.ID}", todo); | |
SelectedID = -1; | |
await Refresh(); | |
} | |
} | |
private async Task DeleteToDo(int id) | |
{ | |
await Http.DeleteAsync($"/api/ToDo/{id}"); | |
await Refresh(); | |
} | |
private void EditToDo(ToDoList todo) | |
{ | |
SelectedID = todo.ID; | |
} | |
private void CancelToDo() | |
{ | |
SelectedID = -1; | |
} | |
private async Task DeleteAllToDos() | |
{ | |
foreach (var c in todos) | |
{ | |
await Http.DeleteAsync($"/api/ToDo/{c.ID}"); | |
} | |
await Refresh(); | |
} | |
} |
There is a variable defined SelectedID
and its value is changed on the click of Edit, Update and Cancel button, which in turn triggers these functions to return the updated value for setting up the display property of HTML controls.
1 2 3 4 5 6 7 8 9 | String ShowOnEditing( int _id) { return (SelectedID == _id) ? "" : "none" ; } String HideOnEditing( int _id) { return (SelectedID == _id) ? "none" : "" ; } |
It’s really implemented in a neat way and takes away all those lengthy JavaScript code. The updated source code is available at GitHub and David Masterson’s updated code is also available at GitHub. Feel free to play around with this app and share your knowledge about Blazor to the world.
Thank you for reading. Keep visiting this blog and share this in your network. Please put your thoughts and feedback in the comments section.
Thank you for this. I’ve updated your code for Blazor 0.3.0 compatibility. You know how those moving targets can be
Here’s the link https://gist.github.com/malachib/753e8b3344a7284a313d5bee4eba0a03
Thanks for the update. I also updated the app, but didn’t get enough time to make a post out of it. Will post soon with all the changes.