首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用.Net输入复选框绑定<tr>的Javascript错误

使用.Net输入复选框绑定<tr>的Javascript错误
EN

Stack Overflow用户
提问于 2020-02-09 12:20:34
回答 1查看 972关注 0票数 2

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

代码语言:javascript
复制
<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运行时错误。错误用户界面页脚显示的标准消息是“意外异常发生了。有关详细信息,请参阅浏览器开发工具。重新加载”。

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

代码语言:javascript
复制
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类作为参数,并为选择添加bool。但是,为了简化示例,我在Row类中包含了bool Selected。该示例基于标准的Blazor服务器端模板项目,并添加了一个Blazor页面。以下是该页的完整代码:

代码语言:javascript
复制
@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元素的tr,它可以正常工作。由于无论何时单击行,onclick都会触发,因此我猜与复选框上的绑定有一些冲突。然而,我没有足够的Javascript技能来进一步调查。我可以通过为每个onclick元素(除了第一个复选框之外)触发td来避免这种情况,而不是整个tr,但是当有很多列时,这会变得乏味和丑陋。由于这在blazor.js中失败了,我想知道它是否是Blazor的一个bug/限制。

任何想法都是欢迎的。谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-09 15:16:11

试试下面的代码。注:我做了一些修改,不是因为它们是问题的原因,等等,我只是忍不住要有我自己的风格。但是,您应该关注如何绑定到元素。注意,绑定到复选框的选中属性(如:checked="@row.Selected" )就足够了。我希望你在寻找这样的解决方案..。

代码语言:javascript
复制
<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,但我还是不知道为什么不能

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

注意:在编译器处理时,@bind指令创建了两个属性,如果将该指令应用到复选框中,则应该与以下内容等效:

代码语言:javascript
复制
<td><input type="checkbox" checked="@row.Selected" @onchange="@((args) => row.Selected = (bool) args.Value)" /></td>

如果您使用此代码而不是上面的代码,您的应用程序仍将正常工作,但正如您现在所理解的那样,为复选框引发的更改事件是多余的。

但是,如果您使用@bind指令,让编译器代表您执行操作,那么您的代码就会失败。我想这是未报告的窃听器。

我希望我不会因为加上上述的增加而使事情变得复杂.

希望这能帮上忙。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60136549

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档