【问题标题】:cannot remove knockout observableArray item with SingalR无法使用 SignalR 删除淘汰赛 observable Array 项
【发布时间】:2014-01-31 10:35:39
【问题描述】:

我正在努力解决两个问题。第一个是在我将一个新项目推入 observableArray 并尝试刷新手风琴之后。新项目没有出现在手风琴中。但是 products().length 增加了 1。

  this.hub.client.productAdded = function (p) {
    products.push(new productListViewModel(p.id, p.Name, self));
    $("#accordion").accordion("refresh");
    //loadAccordion();
  };

我的第二个问题是,在 SignalR 删除数据库中的一个项目并返回删除的对象后,我试图从 observableArray 中删除已删除的对象。我尝试了不同的方法,但都没有奏效。

  this.hub.client.productRemoved = function (deleted) {
    //var deleted = ko.utils.arrayFilter(products(), function (item) {
    //  return item.id == deleted.id;
    //})[0];
    products.remove(function (item) { return item.id == deleted.id; });
    //products.remove(deleted);

    $("#accordion").accordion("refresh");
  };

我在这里想念什么?以下是整页代码供参考

@{
    ViewBag.Title = "SignalR";
}

<h2>SignalR</h2>

<div id="error"></div>
<h2>Add Product</h2>
<form data-bind="submit: addProduct">
  <input data-bind="value: newProductText" class="ui-corner-all" placeholder="New product name?" />
  <input type="submit" class="ui-button" value="Add Product" />
</form>

<h2>Our Products</h2>

listed: <b data-bind="text: productCount"></b> product(s)
@*<div id="accordion" data-bind="template: {name: productTemplate, foreach: products }, visible: products.Length > 0"></div>*@
<div id="accordion" data-bind='template: {name: "product-template", foreach: products }'></div>

<script type="text/html" id="product-template">
  <h3 data-bind="text: name"></h3>
  <div>
    <input type="button" class="ui-button" value="Remove Rroduct" data-bind="click: removeProduct" />
  </div>
</script>

<span data-bind="visible: productCount() == 0">What? No products?</span>

@section Scripts {
  @Scripts.Render("~/bundles/knockout")
  @Scripts.Render("~/bundles/signalr")
  <script src="/Scripts/jquery.signalR-2.0.1.min.js" type="text/javascript"></script>
  <script src="~/signalr/hubs" type="text/javascript"></script>
  <script src="/Scripts/jquery.livequery.min.js"></script>
  <style>
    #accordion {width: 300px;}
    #accordion h3 { padding-left: 30px}
  </style>

  <script>
    function productViewModel(id, name, ownerViewModel) {
      this.id = ko.observable(id);
      this.name = ko.observable(name);
      var self = this;
      this.removeProduct = function () { ownerViewModel.removeProduct( id); };
      this.name.subscribe(function (newValue) {
        ownerViewModel.updateProduct(ko.toJS(self));
      });
    }

    function productListViewModel() {
      this.hub = $.connection.products;
      this.products = ko.observableArray([]);
      this.newProductText = ko.observable();
      chat = this.hub
      var products = this.products;
      var self = this;
      // Get All
      this.init = function () {
        this.hub.server.getAll();
      }

      this.hub.client.productAll = function (allProducts) {
        //var mappedProducts = $.map(allProducts, function (item) {
        //  return new productViewModel(item.id, item.name, self);
        //});
        //products(mappedProducts);

        $.each(allProducts, function (index, item) {
          products.push(new productViewModel(item.id, item.Name, self));
        });
        loadAccordion();
      };

      this.hub.reportError = function (error) {
        $("#error").text(error);
      };
      $.connection.hub.error(function (error) {
        console.log('SignalR error: ' + error)
      });

      this.hub.client.productAdded = function (p) {
        products.push(new productListViewModel(p.id, p.Name, self));
        $("#accordion").accordion("refresh");
        //loadAccordion();
      };

      this.hub.client.productRemoved = function (deleted) {
        //var deleted = ko.utils.arrayFilter(products(), function (item) {
        //  return item.id == deleted.id;
        //})[0];
        products.remove(function (item) { return item.id == deleted.id; });
        //products.remove(deleted);

        $("#accordion").accordion("refresh");
      };

      // Commands
      this.addProduct = function () {
        var p = { "Name": this.newProductText() };
        this.hub.server.add(p).done(function () { }).fail(function (e) { alert(e); });
        this.newProductText("");
      };

      this.removeProduct = function (id) {
        this.hub.server.remove(id).done(function () { alert("aa"); }).fail(function (e) { alert(e+" aa"); });
      };

      this.productCount = ko.dependentObservable(function () {
        return products().length;
      }, this);
    }
    function loadAccordion() {
      $("#accordion").accordion({ event: "mouseover" });
    }


    $(function () {    
      var viewModel = new productListViewModel(); 
      ko.applyBindings(viewModel);

      // connect SinalR
      $.connection.hub.start(function () { viewModel.init(); });
      //$.connection.hub.start(function () { chat.server.getAll(); });

    });
  </script>
}

【问题讨论】:

  • 在您的删除中,您需要使用item.id(),因为id 是可观察的:products.remove(function (item) { return item.id() == deleted.id; }); 关于添加:您是否在添加后检查了DOM 是否生成了您的HTML?也许您的手风琴没有正确刷新...
  • nemesv,感谢您的评论。它运作良好。我会检查 DOM。按照你的建议。
  • 我检查了 DOM。
    已生成,但内部 HTML 为空。想知道为什么?

标签: asp.net-mvc-4 knockout.js signalr


【解决方案1】:

解决您的添加问题:

您正在创建一个新的productListViewModel,但您需要添加一个新的productViewModel,因此您只需要创建正确的视图模型:
this.hub.client.productAdded = function (p) {
    products.push(new productViewModel(p.id, p.Name, self));
    $("#accordion").accordion("refresh");
};

解决您的删除问题:

在您的productViewModel 中,id 是一个ko.observable,因此您需要编写item.id() 以在remove 函数中访问其值:
this.hub.client.productRemoved = function (deleted) {
    products.remove(function (item) { return item.id() == deleted.id; });
    $("#accordion").accordion("refresh");
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-10
    • 2018-06-05
    • 1970-01-01
    • 1970-01-01
    • 2014-08-05
    • 1970-01-01
    • 2019-03-28
    • 1970-01-01
    相关资源
    最近更新 更多