1

ノックアウトjsを使用して、4行と4列のテーブルを作成しようとしています。以下は、テーブル内に配置する必要がある16個の要素を持つ私の配列です。

    /*----------------------------------------------------------------------*/
/* View Model                                                           */
/*----------------------------------------------------------------------*/
function ViewModel() {
    var self = this;
    self.items = ko.observableArray(["1.jpg", 
                                      "2.jpg", 
                                      "3.jpg", 
                                      "4.jpg",
                                      "5.jpg",
                                      "6.jpg"
                                      ]);
    self.itemRows = ko.computed(function () { //computes the rows dynamically based on items
        var rows = [];
        var count = 0;
        var items = self.items(); //get the item array
        var current = [];
        for(var i in items)
        {
            var item = items[i];
            current.push(item);
            count++;

            if (count == 4)
            {
                count = 0;
                rows.push(current);
                current = []; //next array
            }
        }

        if (current.length > 0)
        {
            rows.push(current);
        }

        return rows;
    });

    self.bindSort = function() {

        var startIndex = -1;         
        var sortableSetup = {        
         start: function (event, ui)
         {         
          startIndex = ui.item.index();
         },


         stop: function (event, ui) 
         {      
          var newIndex = ui.item.index();        
          if (startIndex > -1) 
          {
              self.from = ko.observable(startIndex);
              self.to = ko.observable(newIndex);
              var iTo = parseInt(self.to());
          var iFrom = parseInt(self.from());
          var from = self.items()[iFrom];
              var to = self.items()[iTo];
              self.items()[iTo] = from;
                  self.items()[iFrom] = to;
                  //alert('before');
                  // alert(from);
                  // alert(to);
                  var fromA = self.items()[iFrom];
              var toA = self.items()[iTo]; 
              //alert('after');
          //alert(fromA);
                  // alert(toA);
              self.items.remove(from);               
              self.items.splice(newIndex, 0, toA);
               self.items.remove(to); 
                self.items.splice(startIndex, 0, fromA);
                          //ui.item.remove();
               self.items.valueHasMutated();

          }

         }
        };


        $(".fruitList").sortable( sortableSetup );                           

    };

}   

/*----------------------------------------------------------------------*/
/* KO HTML Binding                                                      */
/*----------------------------------------------------------------------*/   
$(document).ready(function() {

    // create the view model
    var model = new ViewModel();

    // call the bind method for jquery UI setup
    model.bindSort();

    // binds ko attributes with the html
    ko.applyBindings(model);

});

htmlでこれを行おうとすると、

<table data-bind="foreach: itemRows">
              <tr class="fruitList" data-bind="foreach: $data">
                  <td><img data-bind="attr: { src: $data }" /></td>
              </tr>
        </table>

配列の長さを取得できません。また、最初の行に4つのtdsが作成され、次に2番目の行が作成されたらループを解除するにはどうすればよいですか。

アップデート:

以下のコードは、sortableを使用すると機能しないようです。

    start: function (event, ui)
     {         
      startIndex = ui.item.index();
     },


     stop: function (event, ui) 
     {      
      var newIndex = ui.item.index();  
4

1 に答える 1

2

更新:ソート可能なバージョンの一番下に移動します

ソート不可能なバージョン

編集して並べ替えについて言及する前に、要件を満たしていると思われるjsfiddleを作成しました:http://jsfiddle.net/fENSD/4/

私が行ったことは、監視可能なアイテムを監視し、テーブルのレンダリングに必要な形状のネストされた配列を返す計算された監視可能オブジェクトを作成することでした。これは最も効率的な機能ではありませんが、いくつかの作業を行うことで、割り当てられるアレイの数を減らすことができます(現時点では、更新されるたびに4x4グリッド用に5つ程度が作成されます)。

self.items = ko.observableArray(["images/1.jpg", "images/2.jpg", "images/3.jpg", "images/4.jpg", "images/5.jpg", "images/6.jpg"]);

self.itemRows = ko.computed(function () { //computes the rows dynamically based on items
    var rows = [];
    var count = 0;
    var items = self.items(); //get the item array
    var current = [];
    for(var i in items)
    {
        var item = items[i];
        current.push(item);
        count++;

        if (count == 4)
        {
            count = 0;
            rows.push(current);
            current = []; //next array
        }
    }

    if (current.length > 0)
    {
        rows.push(current);
    }

    return rows;
});

次に、テーブルは次のようにレンダリングされます。

<table data-bind="foreach: itemRows">
    <tr data-bind="foreach: $data">
        <td><img data-bind="attr: { src: $data }" /></td>
    </tr>
</table>

JSFiddleには、監視可能なアイテムにアイテムを追加する例が含まれており、実際の動作を確認したい場合は、それを反映するようにテーブルが更新されます。JSFiddleには、items配列の長さを取得する1つの方法の例もあります(data-bind="text: items().length")。

ソート可能なバージョン

かなりの変更でしたが、ソートも機能するようになりました。jquery ui Webサイトから例をとると、次のようになります。

http://jsfiddle.net/fENSD/11/

テーブルで並べ替えるのは非常に難しいため、jquery uiの例では、実際には、各要素が特定の幅を占める、定義された幅を持つリストを使用しました。これにより、効果的にテーブルが作成されます。画像を使用しているので、すべて同じサイズにすることができると思います。

これを行うために、私はそのようないくつかのCSSを持っています:

#items { list-style-type: none; margin: 0; padding: 0; width: 200px; }
#items li { width: 48px; margin: 0px; padding: 0px; float: left; text-align: center; height: 48px; }

次に、次のような適切なバインディングハンドラーを作成しました。

ko.bindingHandlers['sortable'] = {
    init: function (element, valueAccessor) {
        var $element = $(element);
        var observable = valueAccessor();
        var value = ko.utils.unwrapObservable(observable);
        $element.sortable({
            stop: function(event, ui) {
                var prev = ui.item.prev();
                var data = ko.dataFor(ui.item[0]);
                var index = 0;
                if (prev.length > 0) {
                    //not the first item
                    var prevData = ko.dataFor(prev[0]);
                    var index = value.indexOf(prevData) + 1;
                }
                var oldIndex = value.indexOf(data);
                value.splice(oldIndex, 1);
                value.splice(index, 0, data);
                observable.valueHasMutated();
            }
        });
    }
};

ソート可能オブジェクトが更新されるたびに、バインディングに渡された監視可能な配列が変更されます。:これは非常に堅牢ではなく、値が変更されたことを通知する前に、渡された値が実際に監視可能であることを確認する必要があります。

ビューモデルは次のようになります。

function ViewModel() {
    var self = this;

    self.items = ko.observableArray(["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13"]);

    self.items.subscribe(function (value) {
        console.log(value); //this is so you can see that the array is indeed being re-sorted
    });

    self.add = function () {
        self.items.push("another thing");
    };
}

そしてレンダリングするには:

<ul id="items" data-bind="sortable: items, foreach: items">
    <li><img data-bind="attr: { src: $data }" /></li>
</ul>

この方法の制限は、アイテムのサイズが異なる場合、並べ替え可能な順序が実際にメモリに表示される順序と少し異なるように見えることです。ただし、すべての要素が同じサイズであれば、問題なく機能するはずです。もう1つの問題は、これが重複アイテムではうまく機能しないことです。ただし、これを解決するには、各要素を単純な古い文字列ではなく、値(場合によっては観測可能な値)を含むオブジェクトにするだけです。

于 2013-02-27T07:21:21.877 に答える