本文介绍了.Net Core Blazor-使用带有< tr>的输入复选框绑定的Javascript错误点击的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为Blazor服务器端应用程序编写Blazor组件,该组件将显示数据表并允许选择一个或多个行.这个想法是在表的第一列中将有一个复选框,而在其余列中将有行数据.单击复选框可以选择/取消选择该行,也可以单击该行中的任何位置来选择/取消选择该行.这是通过将输入复选框绑定到行对象上的bool并使用tr元素上的onclick来完成的.

I am writing a Blazor component for a Blazor server side app, that will display a table of data and allow one or more rows to be selected. The idea is that there will be a checkbox in the first column of the table and the row data in the remaining columns. The row is selected/deselected by clicking the checkbox OR by clicking anywhere in the row. This is done by binding an input checkbox to a bool on the row object and by using onclick on the tr element.

<tr @onclick="() => item.Toggle()">
    <td><input type="checkbox" @bind="item.Selected" /></td>
    <td>@item.Number</td>
    <td>@item.Text</td>
</tr>

通常可以.单击该行将选择该行,将bool值设置为true,然后将选中该复选框.再次单击该行将取消选择该行,将bool值设置为false,并且将取消选中该复选框.一切都如预期.选中该复选框时,它也可以使用,但是取消选中该复选框将导致javascript运行时错误. blazor-error-ui页脚显示为标准消息发生了意外的异常.有关详细信息,请参见浏览器开发工具.重新加载".

Generally it works. Clicking the row will select the row, set the bool value to true and the checkbox will be checked. Clicking the row again will deselect the row, set the bool value to false and the checkbox will be unchecked. All as expected. When checking the checkbox it also works, however unchecking the checkbox results in a javascript runtime error. The blazor-error-ui footer is shown with the standard message "An unexpected exception has occurred. See browser dev tools for details. Reload".

以下是Chrome控制台中的详细信息

Here are details from the Chrome Console

blazor.server.js:1 [2020-02-09T11:25:41.667Z] Information: Normalizing '_blazor' to 'https://localhost:44374/_blazor'.
blazor.server.js:1 [2020-02-09T11:25:41.874Z] Information: WebSocket connected to wss://localhost:44374/_blazor?id=58aEAiJBVZFuzpm9Sn_HdA.
blazor.server.js:15 [2020-02-09T11:25:49.676Z] Error: There was an error applying batch 10.
e.log @ blazor.server.js:15
blazor.server.js:8 Uncaught (in promise) TypeError: Cannot read property 'parentNode' of undefined
    at Object.e [as removeLogicalChild] (blazor.server.js:8)
    at e.applyEdits (blazor.server.js:8)
    at e.updateComponent (blazor.server.js:8)
    at Object.t.renderBatch (blazor.server.js:1)
    at e.<anonymous> (blazor.server.js:15)
    at blazor.server.js:15
    at Object.next (blazor.server.js:15)
    at blazor.server.js:15
    at new Promise (<anonymous>)
    at r (blazor.server.js:15)
blazor.server.js:15 [2020-02-09T11:25:49.864Z] Error: System.AggregateException: One or more errors occurred. (TypeError: Cannot read property 'parentNode' of undefined)
 ---> System.InvalidOperationException: TypeError: Cannot read property 'parentNode' of undefined
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.InvokeRenderCompletedCallsAfterUpdateDisplayTask(Task updateDisplayTask, Int32[] updatedComponents)
   --- End of inner exception stack trace ---

我的应用程序中的Blazor组件使用类Selectable,该类将Row类作为参数并添加布尔值以供选择.但是,为了简化示例,我在Row类中包含了bool Selected.该示例基于标准的Blazor服务器端模板项目,并添加了一个Blazor页面.这是该页面的完整代码:

My Blazor component in my app uses a class Selectable which takes a Row class as a parameter and adds the bool for selection. However, to simplify the example I have included the bool Selected, in the Row class. The example is based on the standard Blazor server-side template project, and adds one Blazor page. Here is the full code for that page:

@page "/test"

@if (data == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table table-hover">
        <thead>
            <tr>
                <th>Select</th>
                <th>Number</th>
                <th>Text</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in data)
            {
                <tr @onclick="() => item.Toggle()">
                    <td><input type="checkbox" @bind="item.Selected" /></td>
                    <td>@item.Number</td>
                    <td>@item.Text</td>
                </tr>
            }
        </tbody>
    </table>
}

@code 
{
    private List<Row> data;

    private class Row
    {
        public bool Selected;
        public int Number;
        public string Text;

        public Row(int number)
        {
            Selected = false;
            Number = number;
            Text = $"Item {number}";
        }

        public void Toggle() => Selected = !Selected;
    }

    protected override void OnInitialized()
    {
        data = new List<Row>
        {
            new Row(1),
            new Row(2),
            new Row(3)
        };
    }
}

如果我删除tr元素的onclick,它将正常工作.由于onclick会在每次单击该行时触发,因此我猜想该复选框上的绑定存在一些冲突.但是,我没有足够的Javascript技能来进一步研究.我可以通过为每个td元素(第一个复选框除外)而不是整个tr触发onclick来避免这种情况,但是当有很多列时,这将变得乏味且难看.由于这在blazor.js中失败,所以我想知道这是否可能是Blazor的错误/局限性.

If I remove the onclick for the tr element it works fine. Since the onclick fires anytime the row is clicked, I'm guessing there is some conflict with the binding on the checkbox. However, I don't have enough Javascript skills to investigate further. I can avoid the situation by firing up onclick for each td element (except the first checkbox) rather than the whole tr, but that gets tedious and a bit ugly when there are lots of columns. Since this is failing within blazor.js I am wondering if it might be a bug/limitation of Blazor.

任何想法都将受到欢迎.谢谢.

Any thoughts would be welcome. Thanks.

推荐答案

尝试以下代码...注意:我进行了一些更改不是因为它们是导致问题的原因,等等.有自己的风格.但是,您应该专注于如何绑定到元素.请注意,像这样绑定到复选框的checked属性就足够了:checked="@row.Selected".希望您正在寻找这样的解决方案...

Try the following code... Note: I've made some alterations not because they are the cause of the issue, etc., I just can't help to have my own style. However, you should focus on how you bind to elements. Note that it is sufficient to bind to the checkbox's checked attribute like this: checked="@row.Selected". I hope you were looking for such solution...

<table class="table table-hover">
    <thead>
        <tr>
            <th>Select</th>
            <th>Number</th>
            <th>Text</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var row in rows)
        {
            <tr @onclick="@(() => row.Selected = !row.Selected)">
                <td><input type="checkbox" checked="@row.Selected" /></td>
                <td>@row.Number</td>
                <td>@row.Text</td>
            </tr>
        }
    </tbody>
</table>

@code
{
   List<Row> rows = Enumerable.Range(1, 10).Select(i => new Row { Selected = 
            false, Number = i, Text = $"Item {i}" }).ToList();

  private class Row
  {
    public bool Selected { get; set; }
    public int Number { get; set; }
    public string Text { get; set; }

 }

}

通常,您可以使用@bind指令在Html元素和数据源之间创建双向数据绑定.但是在这种情况下,从数据源到复选框的数据绑定就足够了,因为tr元素上的click动作触发的lambda表达式切换了boolean row.Selected属性.因此,该组件将被重新渲染,并且该复选框处于选中状态或未选中状态.取决于先前的状态.

Ordinarily you can use the @bind directive to create a two-way data-binding between an Html element, and a data source. But in this case, a one way data-binding is sufficient, from the data source to the checkbox, as the lambda expression triggered by the click action on the tr element toggles the boolean row.Selected property. Consequently, the component is re-render, and the checkbox is either checked or unchecked. depending on the previous state.

注意:如果将@bind指令应用于复选框,则@bind指令在由编译器处理时会创建两个属性,该属性应等效于如下所示:

Note: The @bind directive when processed by the compiler creates two attribute that SHOULD be equivalent to something like this, if you apply the directive to the checkbox:

<td><input type="checkbox" checked="@row.Selected" @onchange="@((args) => row.Selected = (bool) args.Value)" /></td>

如果使用此代码而不是上面的代码,则您的应用仍然可以正常运行,但是如您现在所了解的那样,为该复选框引发的change事件是多余的.

If you use this code instead of the one above, your app still will be working fine, but as you must have understood by now, the change event raised for the checkbox is superfluous.

但是,瞧,如果您使用@bind指令,让编译器代表您执行操作,您的代码将失败.我想这是未报告的错误.

But, lo and behold, if you use the @bind directive, letting the compiler act on your behalf, your code will fail. I guess this is unreported bug.

我希望我不要通过添加以上添加内容使事情变得如此复杂...

I do hope that I did not make things rather complicated by adding the above addition...

希望这对您有帮助...

Hope this helps...

这篇关于.Net Core Blazor-使用带有&lt; tr&gt;的输入复选框绑定的Javascript错误点击的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-25 17:03