2017-02-07 84 views
0

我正在使用$ .observable(array).insert()將項目追加到列表。這是更新我的視圖,因爲它應該:新的列表項被呈現給DOM。然而,我想在新的DOM節點上發出一個點擊事件(我依靠這個事件來添加一個類來展開該項目並將另一個偵聽器附加到該主體以便該區域可以關閉)。

我曾經嘗試都

$.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); 

} 

而且,無論他們的工作,但是,如果我換了jQuery方法在setTimout,像setTimeout(function() { $leadTimes.find('.lead-time-data').last().find('.start-editing').click(); }, 400);,它確實工作,導致我相信這是一個時間問題,在我的jQuery click()方法被調用之前,DOM渲染以某種方式沒有完成。

由於可能性很大,你會看到這個,Borris,謝謝你的圖書館和你所做的一切!我認爲jsViews是一個非常好的中間地帶,在那裏的單體框架和普通的舊jQuery沒什麼區別!


編輯17年2月9日

原來我的問題是重疊的單擊事件 - 我是無意中處理點擊取消對它的選擇後我的元素。然而,我藉此機會重寫了一些事情,以便在Borris的關聯示例之後使用更多的聲明性方法。

現在在我的模板,我使用的是計算觀察到,isSelected來切換.editing類:

{^{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); 

選擇是獲取添加,同步,上新插入的項目。

您的渲染中是否有其他異步代碼?

順便說一句,如果您使用委託模式,通常您不需要爲添加的元素添加新的點擊處理程序。例如,在同一樣本中,刪除電影的點擊處理程序首先通過代理選擇器".removeMovie"(請參閱code)添加到容器"#movieList"。即使是稍後添加的電影,這也可以工作。

同樣的情形適用於使用{{on}}http://www.jsviews.com/#link-events「時,選擇參數可以針對以後添加元素」

+0

謝謝你的指導;我會研究這個!我想添加/刪除的點擊事件位於主體上。我的想法是,我觸發新項目上的點擊事件,以便在添加時擴展它,並且用戶可以單擊外部(在主體上)關閉它。我正在尋找一種類似於上面鏈接的示例的更加陳述式的方法。 – HowlingFantods