【问题标题】:Removing Self From observableArray in knockoutJS在 knockoutJS 中从 observableArray 中删除 Self
【发布时间】:2012-07-12 22:04:15
【问题描述】:

我正在使用 knockoutjs 创建部门的树形视图。每个节点旁边将是三个按钮:1)新建子节点(应用于它旁边的节点 2)删除(这将删除它旁边的节点,以及 3)复制,它复制节点及其所有子节点并创建一个新的父节点下的节点。

我已经按下新建按钮,现在我正在处理删除按钮。我似乎无法让它工作,而不是做任何有用的事情,它只是刷新了整个页面。代码如下:

查看:

<h2>Skill & Weight Divisions</h2>
        <span data-bind="text: tournamentname"></span><button data-bind="click: addDivision"><img src="new.png"/></button>
        <ul data-bind="template: { name: 'divisionTemplate', foreach: divisions }"></ul>

模板:

<script id="divisionTemplate" type="text/html">
   <li data-bind="style: {'background-color':color}">
       <input data-bind="value: name"/><button data-bind="click: addDivision"><img src="new.png"/></button><button data-bind="click: $parent.removeDivision"><img src="remove.png"/></button><button data-bind="click: $parent.copyDivision"><img src="copy.png"/></button>
       <ul data-bind="template: { 'if': children, name: 'divisionTemplate', foreach: children }"></ul>
    </li>       
</script>

查看模型和适当的辅助函数:

function division(id, name, filter, children) {
        this.id = ko.observable(id);
        this.name = ko.observable(name);
        this.filter = ko.observable(filter)
        if(children){
            this.children = ko.observableArray(children);   
        }else{
            this.children = ko.observableArray();   
        }
        this.addDivision = function(){
            this.children.push(new division("", "", ""));   
        }
        this.removeDivision = function(division){
            this.children.remove(division);
        }
        this.copyDivision = function(division){
            this.children.push(division);   
        }
        this.color = randColor();
    };
    function tournamentViewModel(){
        var self= this;
        self.tournamentname = ko.observable('NO NAME YET');
        self.districts = ko.observableArray([new district('Provo',1),new district('Salt Lake City',2),new district('St. George',3)]);
        self.district = ko.observable(self.districts()[0]);
        self.regions = ko.observableArray([new region('Utah',1),new region('Idaho',2)]);
        self.region = ko.observable(self.regions()[0]);
        self.location = ko.observable('WHEREVER YOU WANT');
        self.eventdate = ko.observable('');
        self.startTime = ko.observable('');
        self.image = ko.observable();
        self.flyer = ko.computed(function(){
            var flyerHTML = '<span style="text-align:center;padding:10px;"><h1>'+self.tournamentname()+'</h1><img src="'+self.image()+'"/><br/>';
            flyerHTML += 'District: ' + self.district().districtName + ' Region: ' + self.region().regionName+'<br><br>';
            flyerHTML += '<h2>WHEN: '+self.eventdate()+' '+self.startTime()+'</h2>';
            flyerHTML += '<h2>WHERE: '+self.location()+'</h2>';
            flyerHTML += '<img src="http://maps.googleapis.com/maps/api/staticmap?center='+encodeURI(self.location())+'&zoom=12&size=200x200&markers=color:blue%7Clabel:S%7C'+encodeURI(self.location())+'&maptype=roadmap&sensor=false"/>';
            return flyerHTML;
        }, self);
        self.clearImage = function(){
            self.image(''); 
        }
        self.tournamentID = ko.computed(function(){return 't_'+self.district()+'_'+self.region()+'_'+self.eventdate()}, self);
        self.pricingStructures = ko.observableArray([new pricingStructure(3,2.99), new pricingStructure(1,1.99)]);
        self.removePricingStructure = function(pricingStructure){
            self.pricingStructures.remove(pricingStructure); 
        }
        self.addPricingStructure = function(){
            self.pricingStructures.push(new pricingStructure("", ""));  
        }
        self.promoCodes = ko.observableArray();
        self.promoTypes = ['%','$'];
        self.removePromoCode = function(promoCode){
            self.promoCodes.remove(promoCode); 
        }
        self.addPromoCode = function(){
            self.promoCodes.push(new promoCode("", ""));    
        }
        self.divisions = ko.observableArray([new division(1, "Men","",[new division(2,"Gi"), new division(3,"No-Gi")])]);
        self.addDivision = function(){
            self.divisions.push(new division("", "", ""));  
        }

    }
    ko.applyBindings(new tournamentViewModel());

我的主要问题是:有没有办法访问对象的父数组以便从数组中删除该对象?提前感谢您的帮助!

编辑:这是一个 jsFiddle:http://jsfiddle.net/eqY7Z/ 但是它似乎根本不起作用。如果你们看不下去,我会附上我的托管网站的链接,这样你们就可以好好看看了。

【问题讨论】:

  • 另外我想补充一点,在某些时候我确实让删除工作了,但只有两个级别。任何更深的东西都不起作用。如果我记得那里的代码,我会告诉你的。
  • 你能为此创建一个 jsfiddle 吗?
  • 我现在得去上班,但我休息的时候会放一个。

标签: javascript arrays knockout.js ko.observablearray


【解决方案1】:

我采纳了你的想法并制作了一个working fiddle,它的行为与你描述的完全一样。我不想尝试解决你的问题,抱歉。它有很多与您的问题没有直接关系的东西,而且这个解决方案足够通用,其他人应该能够使用它。如果您需要帮助调整它,请告诉我。

需要注意的一点是克隆功能。您的复制功能并不深,并且会导致多个节点指向同一个对象。如果您要更新节点值,它将传播到其克隆。 Knockout 使用ko.toJS 提供了一个方便的深拷贝 + 解包 observables。超级好用。

JS:

var Node = function(name, children) {
    var self = this;
    self.name = ko.observable(name || 'NewNode');
    self.children = ko.observableArray(
    ko.utils.arrayMap(children || [], function(i) {
        return new Node(i.name, i.children);
    }));
    self.newChild = function() {
        self.children.push(new Node());
    };
    self.removeNode = function(node) {
        self.children.remove(node);
    };
    self.copyNode = function(node) {
        var cloneNode = ko.toJS(node);
        self.children.push(new Node(cloneNode.name, cloneNode.children));
    };
};

//Example data removed for brevity, see fiddle
ko.applyBindings(new Node(data.name, data.children));​

HTML:

<button data-bind="click: newChild">NewNode</button>
<ul data-bind="template: { name: 'treeTemplate', foreach: children}">
</ul>

<script id="treeTemplate" type="text/html">
    <li>
        <input data-bind="value: name" />
        <button data-bind="click: newChild">New Child</button>
        <button data-bind="click: $parent.removeNode">Remove Node</button>
        <button data-bind="click: $parent.copyNode">Copy Node</button>
        <ul data-bind="template: { name: 'treeTemplate', foreach: children}"></ul>
    </li>
</script>
​

【讨论】:

  • 这看起来很棒,今晚晚些时候我会试一试。为了清楚起见,据我所知,您将其写为一般性答案,在我的特定情况下,节点将是我所说的部门,对吗?
  • 是的。节点是树中项目的常用术语。
  • 也非常感谢您处理复制功能。在我击败了删除功能后,我打算这样做。感谢您为我节省了大量时间并教我一些优秀的淘汰 JavaScript!
  • 我接受了,因为小提琴看起来很棒。我相信它会在我的代码中工作,如果不是那是我的错,不是你的错,所以我认为你没有理由等待你的观点。
  • @FrankB 哈哈,谢谢。不过说真的,如果您需要帮助来调整它(因为这是您问题的一部分),请告诉我。我很乐意提供帮助。
【解决方案2】:

我能够在以下 jsFiddle 中创建您的代码的工作版本:http://jsfiddle.net/3eQNf/。这似乎归结为两个主要问题:

  1. 您在分区类中使用“this”关键字时遇到了上下文问题。添加 self 变量解决了这个问题。

  2. 您需要添加一个根级分区并绑定到其子级。这使得所有递归都按预期工作。这样做还消除了对您的锦标赛视图模型的 addDivision 方法的需求

另外,仅供参考,我需要为您的地区、地区和定价结构类添加存根,因为这些未包含在您的上面的示例代码中。希望这会有所帮助。

【讨论】:

  • 感谢您告诉我出了什么问题。我以为我已经清除了地区、地区等代码。那好吧。我确实注意到,我无法使用您提供的小提琴复制顶级分区,并且复制实际上只是创建了指向现有对象的文本框。我知道我的问题与复制无关,只是想为您指出这一点。
猜你喜欢
  • 2013-10-23
  • 2012-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-14
  • 1970-01-01
  • 2016-09-10
相关资源
最近更新 更多