5

部門のツリービューを作成するために、knockoutjs を使用しています。各ノードの隣には、次の 3 つのボタンがあります。1) 新しい子 (隣のノードに適用されます) 2) 削除 (隣のノードを削除します。3) コピー。ノードとそのすべての子をコピーし、新しいノードを作成します。親の下のノード。

New ボタンを押し下げて、今は削除ボタンに取り組んでいます。私はそれを機能させることができないようで、何か役に立つことをする代わりに、ページ全体を更新するだけです。コードは次のとおりです。

意見:

<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/ただし、まったく機能していないようです。皆さんがうまくいかない場合は、ホストされている私のサイトへのリンクを含めて、よく見ることができるようにします.

4

2 に答える 2

2

私はあなたのアイデアを取り入れて、あなたが説明したとおりに動作する実用的なフィドルを作成しました。整理しようとは思わなかった、ごめんなさい。それはあなたの問題に直接関係のないものがたくさんありました、そしてこの解決策は他の人がそれを使うことができるはずであるのに十分一般的です。あなたがそれを適応させるのに助けが必要な場合は、私に知らせてください。

注意すべき点の1つは、クローン関数です。コピー機能は深くなく、複数のノードが同じオブジェクトを指すようになります。ノード値を更新すると、そのクローンに伝播されます。Knockoutは、便利なディープコピーとアンラップオブザーバブルをで提供しko.toJSます。とても便利です。

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>
​
于 2012-07-13T16:20:30.393 に答える
1

次の jsFiddle でコードの動作バージョンを作成できました: http://jsfiddle.net/3eQNf/。それは 2 つの主な問題に帰着するように思われました。

  1. 部門クラスで「this」キーワードを使用すると、コンテキストの問題が発生しました。self 変数を追加すると、その問題が解決しました。

  2. 単一のルート レベルの部門を追加し、その子にバインドする必要がありました。これにより、すべての再帰が期待どおりに機能します。これを行うと、トーナメントビューモデルから addDivision メソッドを削除する必要もなくなりました

また、参考までに、district、region、pricingStructure クラスのスタブを追加する必要がありました。これらは上記のサンプル コードに含まれていなかったからです。お役に立てれば。

于 2012-07-13T18:52:23.623 に答える