2017-02-07 6 views
0

$ .observable(array).insert()を使用して項目をリストに追加しています。これは私のビューを更新するものです:新しいリストアイテムはDOMにレンダリングされます。しかし、新しいDOMノードでclickイベントを発行したいと思います(クラスを追加してアイテムを展開し、別のリスナーを本体に追加してエリアを閉じることができます)。

それは、私が

$.observable(_model.leadTimes).insert(leadTime); 
$leadTimes.find('.lead-time-data').last().find('.start-editing').click(); 

...と

function watchLeadTimes() { 

    var changeHandler = function (ev, eventArgs) { 
     if (eventArgs.change === 'insert') { 

      $leadTimes.find('.lead-time-data').last().find('.start-editing').click(); 

     } 
    }; 

    $.observe(_model.leadTimes, changeHandler); 

} 

の両方を試してみましたそして、私はsetTimeout(function() { $leadTimes.find('.lead-time-data').last().find('.start-editing').click(); }, 400);のように、setTimoutでjQueryのメソッドをラップする場合は、それらのどちらも、しかしを働きましたになります。これは、これが、jQueryのclick()メソッドが呼び出される前に、何らかの仕方でDOMレンダリングのタイミングが問題になっていると思うのを導きます。

あなたがこれを見ることができるようにオッズがあるので、Borris、あなたとあなたがしているライブラリに感謝します! jsViewsはモノリシックなフレームワークと普通の古いjQueryのヌードルの間の優れた中間地だと思います!


編集02/09/17

それは私の問題は、クリックイベントが重複して判明 - 私はうっかりそれを選択した直後に私の要素の選択を解除するには、クリックを処理しました。しかし私は、Borrisのリンクされた例の後に、より宣言的なアプローチを使うように物事を書き直す機会を得ました。

は今私のテンプレートで、私は.editingクラスを切り替えるには、isSelectedを計算し、観察を使用しています:

{^{for leadTimes}} 
    <tr class="lead-time-data" data-link="class{merge:~isSelected() toggle='editing'}"> 
     <span>{^{:daysLead}}</span> 
    </tr> 
{{/for}} 

そして、これはJS:

function addNewLeadTimeClickHandler() { 

    var onNewLeadTimeClick = function() { 

     e.stopPropagation(); // this is what I was missing 

     var leadTime = { 
      daysLead: 1, 
      description: '' 
     }; 

     $.observable(_model.activityMapping.leadTimes).insert(leadTime); 
     selectLeadtime(_model.activityMapping.leadTimes.length -1); 

    } 
    $leadTimes.on('click', '.add', onNewLeadTimeClick); 

} 

function selectLeadtime(index) { 

    var addStopEditingClickHandler = function() { 

     var onClickHandler = function (event) { 
      if ($(event.target).closest('tr').hasClass('editing')) { 
       setHandler(); 
       return; 
      } 

      selectLeadtime(-1) 

     }; 

     function setHandler() { 
      var clickEvent = 'click.ActivityChangeRequestDetailController-outside-edit-row'; 
      $('html:not(.edit)').off(clickEvent).one(clickEvent, onClickHandler); 
     }; 

     setHandler(); 

    } 

    if (_model.selectedLeadtimeIndex !== index) { 
     $.observable(_model).setProperty('selectedLeadtimeIndex', index) 
     addStopEditingClickHandler(); 
    } 

} 
function isSelected() { 
    var view = this; 
    return this.index === _model.selectedLeadtimeIndex; 
} 
// isSelected.depends = ["_model^selectedLeadtimeIndex"]; 
// for some reason I could not get the above .depends syntax to work 
// ...or "_model.selectedLeadtimeIndex" or "_model.selectedLeadtimeIndex" 
// but this worked ... 
isSelected.depends = function() {return [_model, "selectedLeadtimeIndex"]}; 

答えて

1

観測可能insert()方法が同期しています。あなたのリスト項目が単に{^{for}}を使用してレンダリングされる場合、それも同期的です。したがって、setTimeoutまたはコールバックを使用する必要はありません。 (そこなコールバックが用意されていますが、このシナリオのためにそれらを必要はありません。)

は、たとえばhttp://www.jsviews.com/#samples/editable/tagsを参照してください(コードhere):

$.observable(movies).insert({...}); 
// Set selection on the added item 
app.select($.view(".movies tr:last").index); 

は、選択は、新たに挿入された上で、同期、追加取得されます項目。

他の非同期コードがレンダリングのどこかにありますか?

ところで、一般的に、デリゲートパターンを使用する場合、追加された要素に新しいクリックハンドラを追加する必要はありません。たとえば、同じサンプルでは、​​ムービーを削除するクリックハンドラは、コンテナ"#movieList"にデリゲートセレクタ".removeMovie"codeを参照)を使用して最初に追加されます。それは後で追加される映画でも機能します。

同じシナリオが{{on}}参照http://www.jsviews.com/#link-eventsを使用して動作します:指導のための

+0

感謝を「セレクタ引数が後から追加された要素をターゲットにすることができます」。私はこれを調べます!追加/削除したいクリックイベントは、本文にあります。そのアイデアは、新しいアイテムのクリックイベントをトリガし、追加されたときに拡大され、ユーザが(本体上で)外側をクリックして閉じることができるということです。私はあなたが上にリンクしたサンプルに似たもっと宣言的なアプローチを検討しています。 – HowlingFantods

関連する問題