【问题标题】:KO computed array filter not workingKO 计算数组过滤器不起作用
【发布时间】:2015-04-01 13:19:26
【问题描述】:

我一直在学习 KO,但只知道我真的花时间用它从头开始创建一个小项目。

我无法理解我的问题,我将简要解释一下逻辑:

您有页面,这些页面可以有页面(子页面)。

/* Defines a Page */
var page = function(ID, alias, body, connections) {
this.ID = ko.observable(ID);
this.alias = ko.observable(alias);
this.body = ko.observable(body);
this.connections = ko.observableArray(connections);
};

var dummyPages = [
new page(1, 'Alias #1', 'Body #1', [5]),
new page(2, 'Alias #2', 'Body #2', []),
new page(3, 'Alias #3', 'Body #3', [2,3]),
new page(4, 'Alias #4', 'Body #4', [5]),
new page(5, 'Alias #5', 'Body #5', [6]),
new page(6, 'Alias #6', 'Body #6', [7]),
new page(7, 'Alias #7', 'Body #7', [1, 4])
];

我在这里要做的是使用一个计算函数,它将放置在 foreach html 元素上。

<tbody data-bind="foreach: foreachConnectionAliases" style="text-align: left">

它会做的基本上是获取页面的孩子信息。

这是我的代码:

/* Return the pages that are connected to the clicked one */
this.foreachConnectionAliases = ko.computed(function(){
alert(this.chPages);
if(typeof this.chPages === "undefined")
  return null;

var filtered =  ko.utils.arrayFilter(this.chPages(), function(page) {
                      return this.filterByThisPage(page.ID());
                  });
                  debugger;
return filtered;
}).bind(this);//, { deferEvaluation: true });

/* Finds out if the activeConnection exists for the page we want */
this.filterByThisPage = function(pageID){
alert('filterByThisPage');
ko.utils.arrayForEach(getPageConnections(), function(id) {
  if(id === pageID) return true;
});
return false;
}.bind(this);

/* Receive a page ID and get its connections array */
this.getPageConnections = function(){
alert('getPageConnections');
var getConnections = ko.utils.arrayFirst(this.chPages(), function(page){
                      return this.activeConnection() === page.ID();
                     });

return getConnections.connections();
}

如您所见,我在路上的某处放置了许多警报。计算函数中的警报只触发一次,我认为这是由于返回 null。

需要注意的重要一点是,假设我希望它在我们更改 this.activeConnection() 的值时触发,它是一个可观察变量,保存我们单击的页面的 ID(查看子页面)。

非常感谢任何关于修复代码以及使其更干净的想法,因为我相信我过于复杂了。

编辑:

我还尝试了 deferEvaluation: true ,在这种情况下,我的 foreach 数据绑定总是出现未定义的错误。

编辑 2:

http://jsfiddle.net/g1q99jr8/6/

这简要说明了我的情况。 HTML部分可能有一些错误。

【问题讨论】:

  • 我并不完全清楚您要做什么。什么是this.chPages,什么是page?您是要显示所有pages 中的所有connections,还是要显示特定页面的connections?在最后一种情况下,您可以将当前活动页面放入可观察对象中,将连接列表父元素的范围设置为该可观察对象(例如with: currentPage),然后在connections 属性上执行foreach(例如@ 987654335@).
  • 您好 CornéM 感谢您的回答。 chPages() 是所有页面,它是 var dummyPages 的可观察数组。我要展示的是单个页面的所有连接(子)(因此 chPages() 中的单个记录)。我这样做的原因是,如果您注意每个页面,您会发现连接是一堆 ID,因此我需要遍历所有 chPages() 来获取信息(别名和正文)。你明白我的意思吗?
  • 如果你能分叉这个样本小提琴并解释你的案例会更好jsfiddle.net/supercool/LkqTU/22317。干杯
  • 感谢您的回答超级酷。一旦我得到更改并用它编辑我的帖子,我就会这样做。
  • 编辑超酷:) jsfiddle.net/g1q99jr8/6

标签: jquery html knockout.js foreach


【解决方案1】:

使用您提供的 Fiddle,我已更改您的代码以实现我认为您想要实现的目标。对于数组搜索,我使用了 jQuery。

这是 HTML:

<input type="text" placeholder="Write a number, please" id="number" />
<button type="submit" data-bind="click: changeActiveConnection">
    Click me!
</button>
<div style="margin-bottom: 10px"></div>
<div data-bind="foreach:foreachConnectionAliases">
    <input type="text" data-bind="value:alias" />
    <br />
</div>

还有 JavaScript:

var viewModel = function () {
    var self = this;

    var page = function (ID, alias, body, connections) {
        this.ID = ko.observable(ID);
        this.alias = ko.observable(alias);
        this.body = ko.observable(body);
        this.connections = ko.observableArray(connections);
    };

    var dummyPages = [
        new page(1, 'Alias #1', 'Body #1', [5]),
        new page(2, 'Alias #2', 'Body #2', []),
        new page(3, 'Alias #3', 'Body #3', [2, 3]),
        new page(4, 'Alias #4', 'Body #4', [5]),
        new page(5, 'Alias #5', 'Body #5', [6]),
        new page(6, 'Alias #6', 'Body #6', [7]),
        new page(7, 'Alias #7', 'Body #7', [1, 4])];

    self.chPages = ko.observableArray(dummyPages);
    self.activePage = ko.observable();

    self.changeActiveConnection = function() {
        var number = +$('#number').val();

        // Find the selected page
        var match = $.grep(self.chPages(), function (e, i) {
           return e.ID() == number;
        });

        if (match.length < 1) // No element found
            return;

        self.activePage(match[0]);
    };

    /* Return the pages that are connected to the clicked one */
    self.foreachConnectionAliases = ko.computed(function() {
        var _page = self.activePage();

        if (_page == null || _page.connections().length < 1)
            return [];

        var aliases = [];

        // Loop through the connections of the current page
        _page.connections().forEach(function (e, i) {
            // Find the page again
            var connection = $.grep(self.chPages(), function (el, ix) {
                return el.ID() == e;          
            })[0];

            aliases.push(connection);
        });

        return aliases;
    });
};

ko.applyBindings(new viewModel());

还有一个working Fiddle

【讨论】:

  • 我无语了。谢谢!我避免使用第二个阵列,因为我希望所有东西都连接起来。因此,如果我更改页面上的连接,我希望它能够自动更新。不过,我认为我不能轻易做到这一点。
【解决方案2】:

好吧,您正试图根据单击功能在文本框中输入的连接 ID 进行过滤。

这里要注意的第一点是不需要使用computed这里的点击功能可能已经绰绰有余,可以通过非常简单的方式完成

查看模型:

    var viewModel = function () {
    var self = this;
    var page = function (ID, alias, body, connections) {
        this.ID = ko.observable(ID);
        this.alias = ko.observable(alias);
        this.body = ko.observable(body);
        this.connections = ko.observableArray(connections);
    };

    var dummyPages = [
    new page(1, 'Alias #1', 'Body #1', [5]),
    new page(2, 'Alias #2', 'Body #2', []),
    new page(3, 'Alias #3', 'Body #3', [2, 3]),
    new page(4, 'Alias #4', 'Body #4', [5]),
    new page(5, 'Alias #5', 'Body #5', [6]),
    new page(6, 'Alias #6', 'Body #6', [7]),
    new page(7, 'Alias #7', 'Body #7', [1, 4])];

    self.chPages = ko.observableArray(dummyPages);
    self.activeConnection = ko.observable();
    self.foreachConnectionAliases = ko.observableArray();

    /* Return the pages that are connected to the clicked one */

    self.changeActiveConnection = function () {
        self.foreachConnectionAliases([]);
        var conValue = self.activeConnection();

        if (typeof self.chPages === "undefined") return null;

        var filter = ko.utils.arrayFirst(self.chPages(), function (page) {
            if (page.ID() == conValue) return true;
            else return false;
        });

        if(! filter) return true; 

        ko.utils.arrayForEach(filter.connections(), function (id) {
           ko.utils.arrayFilter(self.chPages(), function (page) {
                if (page.ID() == id) {
                    self.foreachConnectionAliases.push(page);
                    return true;
                } else {
                    return false;
                }
            });
        });
    }

};
ko.applyBindings(new viewModel());

工作小提琴here

如有任何问题,请告诉我们

【讨论】:

  • 嘿,超级酷,也非常感谢您的回答!我没有机会查看整个代码,但是当我按下以获得“1”的别名时,可能会出现一些问题,它返回的结果与预期的不同。我对 cormé 的同样问题是:是否可以自动更新页面的连接?例如,当我与数组返回的页面之一交互时(例如删除其中一个页面),它会自动反映在父级上吗?即:第1页与第2页和第3页有联系。我删除第2页和第1页更新,所以它只与第3页有联系。
  • 我误解了你的要求,现在相应地更正了我的代码。只是一个小小的改变就是这样。附上工作小提琴检查它。欢呼
  • Is it possible to automatically update the connections of a page 。是的,它会自动更新,因为它是 observableArray 。当你删除一些东西时,我希望你能从 observableArray 中删除,如果是这样的话,我向你保证一切都井井有条。欢呼
  • 非常感谢您的回答。您的代码现在可以工作了!哪里错了?一旦我将它应用到我的项目中,我会回复你,这样我就可以看到一切正常。我需要一些时间来分析所有内容并执行删除功能等 :) 准备好后我会更新您!
  • 实际上我以为您正在寻找不同的东西,例如我认为您在文本框中输入了连接号,然后它应该获取输入了连接号的所有连接的别名,例如您输入了 5 所以我需要显示 alias1 和 alias4 都具有连接号 5 。反正我不好。
猜你喜欢
  • 1970-01-01
  • 2020-10-21
  • 1970-01-01
  • 2020-09-06
  • 1970-01-01
  • 2021-08-03
  • 2015-12-07
  • 2022-11-24
  • 2018-04-23
相关资源
最近更新 更多