0

このトピックに関するthis questionthis other oneを見てきましたが、どれも私の問題を解決していないようです。

テーブルの各行内の要素の javascript プラグイン (BootStrap javascript ツールチップ) を初期化しようとしています。

そのためには、テーブルを DOM でレンダリングする必要があります。そして、そこが問題です。私の知る限り、knockout.js はforeachテーブル全体をいつレンダリングしたかを知る適切な方法を提供していません。

投稿した最初のリンクで提供されているソリューションを適用して解決しようとしましたが、これはカスタム バインディングを作成することによって行われましたが、私の場合はうまくいきません。AJAX呼び出しからAPIを呼び出してデータを表示しているためだと思います。

問題の再現

ko.bindingHandlers.doSomething = {
    update: function (element) {
        console.log("table loaded???");

        //applying the tooltip
        $('.actions').tooltip({
            title: 'Actions'
        });
    }
};

function ViewModel(){
    var self = this;
    self.myItems= ko.observableArray(['A', 'B', 'C']);

    //emulating the delay of calling an external API 
    self.getdata = function(){
        setTimeout(function(){
            self.myItems.push('D');
            self.myItems.push('E');
            self.myItems.push('F');
        }, 200);       
    };

    self.addItem = function () {
        this.myItems.push('New item');
    };

    //getting the data on loading    
    self.getdata();
}

ko.applyBindings(new ViewModel());

afterRenderKnockout.js によって提供されるコールバックをケースに使用しないことをお勧めforeachします。これは、プラグインを最後に 1 回だけではなく、反復ごとに初期化する必要があるためです。

私が見つけた唯一の解決策はsetTimeout、ツールチップ プラグインを適用する前に , を適用することでしたが、理想とはほど遠いものです。

ko.bindingHandlers.doSomething = {
    update: function (element) {
        console.log("table loaded???");

        setTimeout(function(){
            //applying the tooltip
            $('.actions').tooltip({
                title: 'Actions'
            });
        }, 2000);
    }
};

tooltipもう 1 つの解決策は、API からデータを取得した後にプラグインを呼び出すことでした。

//emulating the delay of calling an external API 
self.getdata = function(){
    setTimeout(function(){
        //simulating 
        $.get(url, function(data){
            self.orders(data);
            self.loading(false);

            $('.actions').tooltip({
                title: 'Actions'
            });
        });
    }, 200);       
};

それに対するより良いアプローチはありますか?

4

1 に答える 1

1

これは、すでに知っていることのいくつかを別の方法で混ぜて、より口当たりの良い方法にするオプションです。

http://jsfiddle.net/xveEP/260/

最初に というビューモデルに変数を追加しましたtooltipHandlesetTimeoutこの変数は、ツールチップを適用するために行われるすべての呼び出しへの参照 (またはポインター) になります。

<li>親要素ではなく要素のカスタム バインディングを作成しました<ul>setTimeoutこのカスタム バインディングは、最初にツールヒントを追加するための既存のインスタンスをすべてクリアします。次に、5 ミリ秒で実行される新しいsetTimeoutインスタンスを作成します。この関数は、ツールチップが適用されていないクラスを持つsetTimeoutすべての要素にツールチップを適用します。.actions

あなたの例では、合計6つの要素が追加されています.3つはすぐに、3つは200ms後に追加されます。私のバインディングは 6 回実行されますが、ツールチップは 2 回しか適用されません。最初の 3 に対して 1 回、2 番目の 3 に対して 1 回tooltipHandleですsetTimeout。 2セットそれぞれ製本済みです。前の例では 2 回しか呼び出されないことがわかるようconsole.logに、関数に呼び出しを追加しました。setTimeout

さらに、[追加] ボタンをクリックするとバインドが実行され、新しく追加された要素にのみツールヒントが適用されます。

<ul data-bind="foreach: myItems">
    <li data-bind="text: $data, doSomething2: true" class="actions"></li>
</ul>

ko.bindingHandlers.doSomething2 = {
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        clearTimeout(bindingContext.$parent.tooltipHandle);
        bindingContext.$parent.tooltipHandle = setTimeout(function() {
            $('.actions:not([data-original-title])').tooltip({
                title: 'Actions'
            });
            window.console.log('tooltip applied');
        }, 5);
    }
};

function ViewModel(){
    var self = this;
    self.tooltipHandle = undefined;
    self.myItems= ko.observableArray(['A', 'B', 'C']);

    //emulating the delay of calling an external API 
    self.getdata = function(){
        setTimeout(function(){
            self.myItems.push('D');
            self.myItems.push('E');
            self.myItems.push('F');
        }, 200);       
    };

    self.addItem = function () {
        this.myItems.push('New item');
    };

    //getting the data on loading    
    self.getdata();
}

ko.applyBindings(new ViewModel());
于 2015-07-01T21:17:35.683 に答える