2016-12-06 3 views
2

ブートストラップカルーセルを使用して、各カルーセル項目に2列のデータを表示します。これは私がやっているの簡単な例です:データをノックアウト付きの2つのブートストラップカラムに分割する

<div class="carousel-inner col-sm-12" role="listbox" data-bind="foreach: { data: dataSlides, as: 'slide' }"> 
    <div class="item" data-bind="css: { active: $index() == 0 }"> 
     <div class="col-sm-6" data-bind="foreach: { data: dataLeft, as: 'data' }"> 
      <div data-bind="text: data"></div> 
     </div> 
     <div class="col-sm-6" data-bind="foreach: { data: dataRight, as: 'data' }"> 
      <div data-bind="text: data"></div> 
     </div> 
    </div> 
</div> 

と私が持っているデータモデル、この構造体を使用しています。

self.dataSlides = ko.observableArray(
[ 
    { dataLeft: ['data 1', 'data 2', 'data 3'], dataRight: ['data 4', 'data 5', 'data 6'] }, 
    { dataLeft: ['data 7', 'data 8', 'data 9'], dataRight: ['data 10', 'data 11', 'data 12'] } 
]); 

これは期待通りに動作しますが、1つの問題で。私のデータ<div data-bind="text: data"></div>を表示している部分は、実際の実装ではかなり複雑です。ご覧のとおり、2回書く必要があります。私の左のデータと右のデータのために一度。

私のやりたいことは、データを1つのデータ配列(dataLeft/dataRightなし)に入れて、データの左半分を残りの半分を右列に表示することです。この方法では、データ表示ループを2回書く必要はありません。

これを行うには、foreachがデータの半分を通過しているときに何らかの形で列タグを閉じて再度開く必要があります。私は以下を試しましたが、これはforeachを壊すので動作しません:

<!-- ko if: $index() == data().length/2 --> 
</div> 
<div class="col-sm-6"> 
<!-- /ko --> 

どうすればいいですか?

+0

も ​​'データ()。'lenght'は' length 'でなければなりません。 – gkb

答えて

1

データを変更してビューとデータバインドを単純化することは悪い考えではないと思います。手動で行うべきではありません。 「あなたのケースでは、スライド

  • つ以上のデータの配列を:

    1. (観測可能な)データソース

      問題のこれらの種類には良いアプローチは、2つの変数で動作するようですあなたのビューの目的に合うようにフィルター、並べ替え、または再構成するデータの自動(computed)バージョンです。

    だから、あなたのケースのために、私はあることko.pureComputed変数を提案したい:

    1. は、元のデータソースを監視し、自動的に計算し、各zスライドと各y列を持つ
    2. x行。

      var dataSlides = ko.observableArray(["slide 1","slide 2","slide 3","slide 4","slide 5","slide 6","slide 7","slide 8","slide 9","slide 10","slide 11","slide 12"]); 
       
      
       
      var dataTable = ko.pureComputed(function() { 
       
          var rows = []; 
       
          var slidesPerCol = 3; 
       
          var colPerRow = 2; 
       
          var slidesPerRow = slidesPerCol * colPerRow; 
       
          
       
          dataSlides().forEach(function(slide, index) { 
       
          var rowNr = Math.floor(index/slidesPerRow); 
       
          var colNr = Math.floor((index % slidesPerRow)/slidesPerCol); 
       
          
       
          rows[rowNr] = rows[rowNr] || getRow(colPerRow); 
       
          rows[rowNr][colNr].push(slide); 
       
          }); 
       
          
       
          return rows; 
       
      }); 
       
      
       
      ko.applyBindings({ 
       
          dataTable: dataTable, 
       
          pushSlide: function(){ 
       
          dataSlides.push("slide " + dataSlides().length); 
       
          } 
       
      }); 
       
      
       
      // Util 
       
      function getRow(c, s) { 
       
          return Array(c) 
       
          .fill(null) 
       
          .map(function() { return []; }); 
       
      }
      .table { 
       
          border: 1px solid black; 
       
      } 
       
      
       
      .row { 
       
          display: flex; 
       
          justify-content: space-between; 
       
      } 
       
      
       
      .row:nth-child(odd) { 
       
          background: rgba(0,0,0,0.1); 
       
      } 
       
      
       
      .col { 
       
          flex: 1; 
       
          display: flex; 
       
          flex-direction: column; 
       
          justify-content: stretch; 
       
      } 
       
      
       
      .col + .col { border-left: 1px solid black; } 
       
      
       
      .slide { 
       
          flex: 1; 
       
          text-align: center; 
       
          padding: .5rem; 
       
      }
      <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
       
      
       
      <div data-bind="foreach: { data: dataTable, as: 'row' }" class="table"> 
       
          <div data-bind="foreach: { data: row, as: 'col' }" class="row"> 
       
          <div data-bind="foreach: { data: col, as: 'slide'}" class="col"> 
       
           <span data-bind="text: slide" class="slide"></span> 
       
          </div> 
       
          </div> 
       
      </div> 
       
      <button data-bind="click: pushSlide">add slide</button>

    サンプル実装(ではないそれを行うには「賢い」方法、私はそれが簡単に読むために...とスタイリングを気にしない作ってみました)

  • +0

    私のデータは水平ではなく垂直に表示され、' data 1/2/3 'は互いに下にあります。各カルーセル項目には、データがソリューションに90°回転された2つの列が含まれています。 –

    +0

    それは私が推測するCSSの変更の多くです...私は 'フレックス方向'を 'right'にすべき' column'に変更しました。それでも、本当の答えは 'ko.pureComputed'です。 – user3297291

    +0

    古いIE版をサポートしなければならないのでflexを使うことができないので、これは実際のオプションではありません。 –

    0

    私は、左の列と右の列のコンテナをそれぞれ持っているはずで、各列のリストの半分をforeachする必要があると思います。この例のように

    https://jsfiddle.net/Salmin/2ytouxvs/2/

    self.dataSlides = ko.observableArray(
        [ 
         ['data 1a', 'data 2a', 'data 3a', 'data 4a', 'data 5a', 'data 6a'], 
         ['data 1b', 'data 2b', 'data 3b', 'data 4b', 'data 5b', 'data 6b'] 
        ]); 
    
    
    <div class="carousel-inner col-sm-12" role="listbox" data-bind="foreach: dataSlides, as: 'slide'"> 
    
        <div class="item-2"> 
        <div class="col-sm-6" data-bind="foreach: $data"> 
        <!-- ko if: $index()+1 < $data.length/2 --> 
         <div data-bind="text: $data"></div> 
        <!-- /ko --> 
        </div> 
        </div> 
    
        <div class="item-2"> 
        <div class="col-sm-6" data-bind="foreach: $data"> 
        <!-- ko if: $index()+1 > $data.length/2 --> 
         <div data-bind="text: $data"></div> 
        <!-- /ko --> 
        </div> 
        </div> 
    
    </div> 
    
    +0

    回答ありがとうございます。これは、表示部分 '

    'を2回書かなければならないという私の問題を解決するものではありません。私の実装ではこれはかなりのコードであり、私は一度だけそれを持っていたいと思います。 –

    関連する問題