Hello fellow developers,
I'm encountering an issue with my Blazor component that involves JavaScript interop. Specifically, when trying to get a reference to the table body in JavaScript and process its rows, I'm facing a JSON deserialization error. The error message suggests that the JSON value received from JavaScript cannot be converted to Microsoft.JSInterop.IJSObjectReference[]. I've included relevant portions of my Blazor component and JavaScript code.
Has anyone else experienced a similar problem or can offer insights into what might be causing this issue? I appreciate any help or guidance in resolving this JSON deserialization challenge. Thank you in advance for your expertise!
Please note: I'm working inside a Razor class library that is being referenced to a Blazor server app and MAUI Blazor App. The Javascript code is not referenced and it was only to test if I'm getting any values, which I am using the javascript code. I want to insert the data in a SQL Table but unable to do so.
<tbody id="table-body">
<!-- Rows will be added here dynamically -->
@for (int index = 0; index < Items.Count; index++)
{
var item = Items[index];
<tr>
<td>
<div style="display: flex; align-items: center;">
<input type="checkbox" class="me-1" @bind="item.Selected" />
@(index + 1)
<button class="ms-2 btn btn-sm btn-danger" @onclick:preventDefault @onclick="() => DeleteRow(index)" style="display: @(item.Selected ? "block" : "none")">Delete</button>
</div>
</td>
<td><input type="text" class="form-control" @bind="item.Name" /></td>
<td><input type="text" class="form-control" @bind="item.Quantity" /></td>
<td>
<input type="text" list="uomOptions" class="form-control" @bind="item.UOM" />
<datalist id="uomOptions">
<option value="Piece"></option>
<option value="Each"></option>
<option value="Box"></option>
<!-- Add more UOM options as needed -->
</datalist>
</td>
<td>
<input type="date" class="form-control" @bind="item.RequiredBy" min="@DateTime.Now.ToString("dd-MM-yyyy")" />
</td>
</tr>
}
</tbody>
<div class="col-12">
<button class="btn btn-primary rounded-pill" @onclick="AddRow">Add Row</button>
<button class="btn btn-primary rounded-pill" @onclick="StoreAndCallCSharpMethod">Get Data</button>
</div>
<script defer>
// JavaScript method to store values in an array and log to console
function storeAndCallCSharpMethod() {
var dataArray = [];
// Loop through each dynamically added row
var tableBody = document.getElementById('table-body');
var rows = tableBody.getElementsByTagName('tr');
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
var inputs = row.getElementsByTagName('input');
// Get values from input fields
var name = inputs[1].value;
var quantity = inputs[2].value;
var uom = inputs[3].value;
var requiredBy = inputs[4].value;
// Store values in an object
var rowData = {
Name: name,
Quantity: quantity,
UOM: uom,
RequiredBy: requiredBy
};
// Add the object to the array
dataArray.push(rowData);
}
// Log the array to the console
console.log(dataArray);
}
</script>
@code {
List<Item> dataArray = new List<Item>();
public async Task GetAndLogTableData()
{
// Get table body from JS
var tableBody = await JSRuntime.InvokeAsync<IJSObjectReference>("eval", "document.getElementById('table-body')");
// Get all rows
var rows = await tableBody.InvokeAsync<IJSObjectReference[]>("querySelectorAll", "tr");
foreach (var row in rows)
{
// Get input fields within the current row
var inputs = await row.InvokeAsync<IJSObjectReference[]>("querySelectorAll", "input");
// Map to RowData object
var rowData = new Item
{
Name = await inputs[1].InvokeAsync<string>("value"),
Quantity = await inputs[2].InvokeAsync<string>("value"),
UOM = await inputs[3].InvokeAsync<string>("value"),
RequiredBy = await inputs[4].InvokeAsync<DateTime>("value") // Assuming RequiredBy is a string, adjust accordingly
};
// Add to list
dataArray.Add(rowData);
}
foreach (var data in dataArray)
{
await insert.PRInsert(data.Name, data.Quantity, data.UOM, data.RequiredBy);
Console.WriteLine($"{data.Name}, {data.Quantity}, {data.UOM}, {data.RequiredBy}");
}
}
}
Using the below method shows errors related to length Error: Microsoft.JSInterop.JSException: Could not find 'get' ('get' was undefined). I've tried different things but nothing works
private async Task StoreAndCallCSharpMethod()
{
var tableBody = await JSRuntime.InvokeAsync<IJSObjectReference>("eval", "document.getElementById('table-body')");
var rows = await tableBody.InvokeAsync<IJSObjectReference>("getElementsByTagName", "tr");
for (int i = 0; i < await rows.InvokeAsync<int>("get", "length"); i++)
{
var row = await rows.InvokeAsync<IJSObjectReference>("get", i);
var inputs = await row.InvokeAsync<IJSObjectReference>("getElementsByTagName", "input");
var name = await inputs.InvokeAsync<string>("get", 1, "value");
var quantity = await inputs.InvokeAsync<string>("get", 2, "value");
var uom = await inputs.InvokeAsync<string>("get", 3, "value");
var requiredBy = await inputs.InvokeAsync<string>("get", 4, "value");
var rowData = new Item
{
Name = name,
Quantity = quantity,
UOM = uom,
RequiredBy = DateTime.Parse(requiredBy)
};
dataArray.Add(rowData);
}
// Log the list to the console
Console.WriteLine("Logging from C#:");
foreach (var data in dataArray)
{
Console.WriteLine($"{data.Name}, {data.Quantity}, {data.UOM}, {data.RequiredBy}");
}
}
Anyone insterested in all the kinds of errors I encountered may refer to the ChatGPT chat below Chat
Based on your code, I could make it work on my side.
You can refer to the followng code:
async Task StoreAndCallCSharpMethod()
{
var dataArray = await JSRuntime.InvokeAsync<List<RowData>>("storeAndCallCSharpMethod");
// Log the list to the console
Console.WriteLine("Logging from C#:");
// foreach (var data in dataArray)
// {
// Console.WriteLine($"{data.Name}, {data.Quantity}, {data.UOM}, {data.RequiredBy}");
// }
}
And the script
is as follows:
<script src="_framework/blazor.server.js"></script>
<script defer >
// JavaScript method to store values in an array and log to console
function storeAndCallCSharpMethod() {
var dataArray = [];
// Loop through each dynamically added row
var tableBody = document.getElementById('table-body');
var rows = tableBody.getElementsByTagName('tr');
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
var inputs = row.getElementsByTagName('input');
// Get values from input fields
var name = inputs[1].value;
var quantity = inputs[2].value;
var uom = inputs[3].value;
var requiredBy = inputs[4].value;
// Store values in an object
var rowData = {
Name: name,
Quantity: quantity,
UOM: uom,
RequiredBy: requiredBy
};
// Add the object to the array
dataArray.push(rowData);
}
// Log the array to the console
console.log(dataArray);
return dataArray;
}
</script>