【问题标题】:Knockout.js: click event is not triggered inside a foreach loop data-bindKnockout.js:在 foreach 循环数据绑定中未触发点击事件
【发布时间】:2018-09-23 20:40:03
【问题描述】:

我正在使用 Knockout.js 和 asp .net mvc。以下代码的问题是未触发“removeItem”事件。我已经为此苦苦挣扎了好几天,并尝试了不同的替代方案,但似乎没有任何效果。页面上没有 javascript 错误,它可以正确加载,但是当我单击按钮时没有任何反应。任何帮助将不胜感激。

<tbody data-bind="foreach: categories" id="tablebody">
                    <tr>
                        <td class="table-cell-id">
                            <span data-bind="text: $index"></span>
                        </td>
                        <td>
                            <a class="small" data-bind="text: Name, attr: { href: $parent.onViewDetails($data) }"></a>
                        </td>
                        <td>
                            <a class="small text-nowrap" data-bind="text: Code, attr: { href: $parent.onViewDetails($data) }"></a>
                        </td>
                        <td class="text-center" data-bind="text: CreationDateInFormat"></td>
                        <td class="text-center text-nowrap" data-bind="text: CreatedByName"></td>
                        <td class="text-center" data-bind="text: ModificationDateInFormat"></td>
                        <td class="text-center text-nowrap" data-bind="text: ModifiedByName"></td>
                        <td>
                            <span class="label label-default" data-bind="text: StatusName"></span>
                        </td>
                        <td class="table-cell-actions">
                            <div class="btn-group">
                                <button class="item-action" type="button" id="itemOptions1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                                    <span class="glyphicon glyphicon-option-vertical" aria-hidden="true"></span>
                                </button>
                                <ul class="dropdown-menu dropdown-menu-right" aria-labelledby="itemOptions1">
                                    <li>
                                        <a class="btn btn-dropdown" data-bind="attr: { href: $parent.onViewDetails($data) }">
                                            <span class="glyphicon glyphicon-eye-open offset-right" aria-hidden="true"></span>
                                            Details
                                        </a>
                                    </li>
                                    <li>
                                        <a class="btn btn-dropdown" data-bind="attr: { href: $parent.onEditItem($data) }">
                                            <span class="glyphicon glyphicon-pencil offset-right" aria-hidden="true"></span>
                                            Edit
                                        </a>
                                    </li>
                                    <li>
                                        <button type="button" class="btn btn-dropdown" data-bind="click: removeItem">
                                            <span class="glyphicon glyphicon-remove-sign offset-right" aria-hidden="true"></span>
                                            Delete
                                        </button>
                                    </li>
                                </ul>
                            </div>
                        </td>
                    </tr>
                </tbody>

JS:

<script>
        function MyViewModel() {
            var self = this;

            var categories = [];
            var arrayOfCategories = @Html.HtmlConvertToJson(Model);

            var Item = function (name, code, categoryId, creationDateInFormat, createdByName, modificationDateInFormat, modifiedByName, status) {
                this.Name = name;
                this.Code = code;
                this.CategoryId = categoryId;
                this.CreationDateInFormat = creationDateInFormat;
                this.CreatedByName = createdByName;
                this.ModificationDateInFormat = modificationDateInFormat;
                this.ModifiedByName = modifiedByName;
                this.StatusName = status;
                this.removeItem = function () {
                    alert(this.Name);
                }
            };

            arrayOfCategories.forEach(function(element) {
                categories.push(
                    new Item(element.Name,
                        element.Code,
                        element.CategoryId,
                        element.CreationDateInFormat,
                        element.CreatedByName,
                        element.ModificationDateInFormat,
                        element.ModifiedByName,
                        element.Status.Name
                    )
                );
            });


            var pageUrls = {};
            pageUrls.editUrl = '@Url.Action("Edit", new { id = 0 })';
            pageUrls.detailsUrl = '@Url.Action("Details", new { id = 0 })';

            self.categories = ko.observableArray(categories);

            self.onEditItem = function(data) {
                return pageUrls.editUrl.replace('0', data.CategoryId);
            };

            self.onViewDetails = function(data) {
                return pageUrls.detailsUrl.replace('0', data.CategoryId);
            };
        }

        var viewModel = new MyViewModel();
        ko.applyBindings(viewModel);
    </script>

【问题讨论】:

  • 哪个按钮?您的代码中不止一个。您是否也尝试过创建一个最小、完整和可验证的示例?见stackoverflow.com/help/mcve
  • 感谢您回答@MartinBrown。由于我对 bootstrap-iu.js 的引用,我注意到该删除按钮没有任何作用。当我删除它时,我的代码运行良好

标签: asp.net-mvc knockout.js


【解决方案1】:

确实将您的代码复制到 sn-p 时出错。

  1. 您的&lt;tbody&gt; 元素是否在&lt;table&gt; 内?不遵守规范的表格配置通常无法正确呈现。
  2. 您的点击处理程序需要使用.bind(this) 或某些var self = this 模式正确绑定到类别。

修复这些确实可以让您的按钮按预期工作(警告类别名称)。

function MyViewModel() {
  var self = this;

  var categories = [];
  var arrayOfCategories = [{
    Code: 1,
    Name: "Some name",
    Status: {}
  }]

  var Item = function(name, code, categoryId, creationDateInFormat, createdByName, modificationDateInFormat, modifiedByName, status) {
    this.Name = name;
    this.Code = code;
    this.CategoryId = categoryId;
    this.CreationDateInFormat = creationDateInFormat;
    this.CreatedByName = createdByName;
    this.ModificationDateInFormat = modificationDateInFormat;
    this.ModifiedByName = modifiedByName;
    this.StatusName = status;
    this.removeItem = function() {
      alert(this.Name);
    }.bind(this)
  };

  arrayOfCategories.forEach(function(element) {
    categories.push(
      new Item(element.Name,
        element.Code,
        element.CategoryId,
        element.CreationDateInFormat,
        element.CreatedByName,
        element.ModificationDateInFormat,
        element.ModifiedByName,
        element.Status.Name
      )
    );
  });


  var pageUrls = {};
  pageUrls.editUrl = '@Url.Action("Edit", new { id = 0 })';
  pageUrls.detailsUrl = '@Url.Action("Details", new { id = 0 })';

  self.categories = ko.observableArray(categories);

  self.onEditItem = function(data) {
    return pageUrls.editUrl.replace('0', data.CategoryId);
  };

  self.onViewDetails = function(data) {
    return pageUrls.detailsUrl.replace('0', data.CategoryId);
  };
}

var viewModel = new MyViewModel();
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table>
  <tbody data-bind="foreach: categories" id="tablebody">
    <tr>
      <td class="table-cell-id">
        <span data-bind="text: $index"></span>
      </td>
      <td>
        <a class="small" data-bind="text: Name, attr: { href: $parent.onViewDetails($data) }"></a>
      </td>
      <td>
        <a class="small text-nowrap" data-bind="text: Code, attr: { href: $parent.onViewDetails($data) }"></a>
      </td>
      <td class="text-center" data-bind="text: CreationDateInFormat"></td>
      <td class="text-center text-nowrap" data-bind="text: CreatedByName"></td>
      <td class="text-center" data-bind="text: ModificationDateInFormat"></td>
      <td class="text-center text-nowrap" data-bind="text: ModifiedByName"></td>
      <td>
        <span class="label label-default" data-bind="text: StatusName"></span>
      </td>
      <td class="table-cell-actions">
        <div class="btn-group">
          <button class="item-action" type="button" id="itemOptions1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                                    <span class="glyphicon glyphicon-option-vertical" aria-hidden="true"></span>
                                </button>
          <ul class="dropdown-menu dropdown-menu-right" aria-labelledby="itemOptions1">
            <li>
              <a class="btn btn-dropdown" data-bind="attr: { href: $parent.onViewDetails($data) }">
                <span class="glyphicon glyphicon-eye-open offset-right" aria-hidden="true"></span> Details
              </a>
            </li>
            <li>
              <a class="btn btn-dropdown" data-bind="attr: { href: $parent.onEditItem($data) }">
                <span class="glyphicon glyphicon-pencil offset-right" aria-hidden="true"></span> Edit
              </a>
            </li>
            <li>
              <button type="button" class="btn btn-dropdown" data-bind="click: removeItem">
                                            <span class="glyphicon glyphicon-remove-sign offset-right" aria-hidden="true"></span>
                                            Delete
                                        </button>
            </li>
          </ul>
        </div>
      </td>
    </tr>
  </tbody>
</table>

【讨论】:

  • 是的,它在 中。关于#2我也试过了。无论如何,感谢您的回复,但我注意到由于我对 bootstrap-iu.js 参考的引用,该删除按钮没有任何作用。当我删除它时,我的代码运行良好。
猜你喜欢
  • 2013-07-31
  • 2021-03-21
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多