2012-04-12 14 views
46

私はknockout.jsを使用して動的リストを作成していますが、私は観測可能な配列内のオブジェクトに関連付けられたDOMオブジェクトをどのように取得できるかを調べようとしています。具体的には、行のjQueryを取得します。Knockout.jsはデータに関連付けられたDOMオブジェクトを取得します

例:getDomObject機能で

<ul data-bind="foreach: Item"> 
    <li data-bind="events: {click: getDomObject}, text: 'text: ' + text"> 
    </li> 
</ul> 

、私はそれにいくつかのjQueryの操作を行うことができるように、特定の<li></li> DOMオブジェクトを取得できるようにしたいと思います。

私は、アイテムViewModelにidメンバーを追加し、そのIDを広告申込情報のhtml idとして追加し、それに基づいて選択することを考えましたが、より簡単な方法があるはずです。

knockout.jsによって生成されたダイナミックHTMLを参照する適切な方法は何ですか?

答えて

64

イベントハンドラには、click get passed two argumentsがあります。これはa)あなたのforeachバインディング(あなたのケースでは "Item")でレンダリングしている観測可能な配列のエントリのような、このイベントが属するアイテムです。 b)実際のイベントに関する詳細情報を提供するイベントオブジェクト。このオブジェクトは、(キー「ターゲット」)をクリックしてしまったDOM要素が含まれています

getDomObject = function(item, event) { 
    var $this = $(event.target); 
    // ... 
} 

ジャストノート:ノックアウトとネイティブjQueryのDOM操作を混在させないでください - あなたは賢いノックアウトバインディングと同じ結果を得ることができれば、私はそれに行くことをお勧めします。 http://jsfiddle.net/KLK9Z/213/

+0

ありがとうございます!これは素晴らしい作品です! jQueryの操作についてお礼をありがとう。私は特定の行にオートコンプリートを使用しているので、私はコを介してそれを行うことはできないと思います。大きな解決策 –

+0

は、オートコンプリートパダワンのカスタムバインディングを使用します。 :私は3ヶ月後にkoと分かち合って学んだことの1つ:jquery/jquery ui stuffでカスタムバインディングを使用します。 –

+0

私は年齢を重ねてノックアウトをしてきましたが、イベントのパラメータはわかりませんでした。ありがとう –

20

$(event.target)それは、アイテムのDOM要素がターゲットになっている、すでに発生した事象に関連している場合ソリューションは良好である:ここ

とは、簡単なデモです。しかし、イベントがないため(たとえば、ユーザーが身振りしていない項目にリストをスクロールする場合など)、対象アイテムがないことがあります。アイテムのDOM要素のIDを与えることができますこのような場合には

は、アイテムIDが含まれているユニークな属性値:まだ追加するには

getDomObject = function(item) { return $("#item_" + item.id); } 
+0

IMHO、この答えは正確にyuvalr80が述べた理由よりはるかに完全です。 –

+0

この回答は私が必要としていたものですが、受け入れられた答えは元の質問の方が優れています。この回答を投稿してくれてありがとう、まさに私が必要なもの。 MVVMのラインを渡ることに夢中ではありませんが、私はちょうど表示するためにアイテムをスクロールする効率的な方法を必要とし、これのために私のリストのすべてのオブジェクトに余分なオブザーバブルを追加する気がしません。 – eselk

+1

それは動作しますが、IDを渡して、そのIDでDOMを取得します。それはいくつかの規則を破る。すべての非IDソリューションは高く評価されます。 –

7

<li data-bind="attr: {id: 'item_' + id}"> 

、その後getDomObject()は次のようになります3つ目のオプションは、あなたがイベントを持っていない場合(イベントがある場合、受け入れられた答えは最適/最適化されています)です。

などのカスタムバインディングを作成します。上記の場合

<li data-bind="scrollTo: $parent.scrollTo() && $parent.scrollTo().id == id"> 

を、$の親は私のビューモデルである:

ko.bindingHandlers.scrollTo = { 
    update: function(element, valueAccessor) { 
     var value = ko.utils.unwrapObservable(valueAccessor()); 
     if (value) { 
      var scrollParent = $(element).closest("div"); 
      var newTop = $(element).position().top + scrollParent.scrollTop(); 
      scrollParent.scrollTop(newTop); 
     } 
    } 
}; 

使い方は以下のとおりです。私は一意のIDを含む観測可能なオブジェクトを持っています。そのscrollTo()オブジェクトを設定するたびに、リストはその項目にスクロールします。

私のコードでは、LIの親DIVがスクロールバー(オーバーフロー:自動/スクロール)を持っていることを前提としています。ニーズに合わせて調整することができます。親クラスを使用してjQueryセレクタに使用するか、データバインドオプションを使用してセレクタに渡すことができます。私にとっては、スクロール可能なセクションに常にdivを使用するので、これで十分でした。

+0

私は何か似たようなことをして、それはかなりうまくいく!投稿ありがとう –

1

私にも同様の問題がありました。私は、backbone.jsのelおよび$ el参照の使用に似た解決策を思いつきます。あなたのViewModelで

:HTMLで

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

    //html element 
    self.el = ko.observable(); 

    //jquery wrapped version 
    self.$el = ko.observable(); 
} 

(例えば、リストの要素のための):bindingHandlersで

<!-- left side is the name of the handler, right side is name of the observable --> 
<li class="myclass" data-bind="el: el, $el: $el"></li> 

(INITに可能なすべての引数を示す):

ko.bindingHandlers.el = { 
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { 
    var value = valueAccessor(); 
    //assign value to observable (we specified in html) 
    value(element); 
    } 
}; 

ko.bindingHandlers.$el = { 
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { 
    var value = valueAccessor(); 
    //here we first create a jQuery object by using $(myelem) 
    //before updating observable value 
    value($(element).first()); 
    } 
}; 

たとえば、$ elは次のように使用できます。

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

    //plain DOM element reference 
    self.el = ko.observable(); 

    //jquery object reference 
    self.$el = ko.observable(); 

    self.myFunction = function() { 
    console.log(self.$el().html()); 
    self.$el().addClass("myCssClass"); 
    } 
} 

希望します。 (結合 "値" の有効な)

1

私のソリューション

ko.bindingHandlers.value.preprocess = function(val, name, cb) { 
    /* every time I set a data-bind="value: xxxx" with an 
    * observable xxxx add also a data-bind="domElement: xxxx" */ 
    cb('domElement', val); 
    return val; 
} 

ko.bindingHandlers.domElement = { 
    /* For each data-bind="domElement: xxxx" add an extension "element" */ 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) { 
     valueAccessor().extend({element: element }); 
    } 
    }; 

ko.extenders.element = function (target, element) { 
    /* element extension add el and $el to observable xxxx */ 
    target.el = element; 
    target.$el = $(element); 
} 

は、今あなたが持っているyourobservable。$ jQueryとDOM要素にバインドエルとyourobservable.el。

関連する問題