2013-04-07 85 views
1

我试图绑定一个可观察数组的人两个两列响应布局与点击事件使用knockoutjs。KnockoutJS自定义绑定调用点击事件绑定期间,而不是点击

我创建了一个名为TwoCol的自定义绑定,它循环遍历数组,并将节点添加到DOM以创建我的建议布局,但是当我尝试将它们应用于嵌套的自定义绑定中时,点击事件给我带来麻烦一个循环。

我已经玩了很多次,并且遇到了所有类型的结果,但是现在我在绑定期间正在调用我的〜click_事件,而不是点击。

http://jsfiddle.net/5SPVm/6/

HTML:

<div data-bind="TwoCol: Friends" id="" style="padding: 20px"> 

JAVASCRIPT:

function FriendsModel() { 
    var self = this; 
    this.Friends = ko.observableArray(); 
    this.SelectedFriend = ""; 
    this.SetSelected = function (person) { 
     alert(person); 
     self.SelectedFriend = person; 
    } 
} 
function isOdd(num) { 
    return num % 2; 
} 
ko.bindingHandlers.TwoCol = { 
    update: function (elem, valueAccessor) { 
     var i = 0; 
     var rowDiv; 
     var vFriends = ko.utils.unwrapObservable(valueAccessor()); 
     $(elem).html(''); 
     while (i < vFriends.length) { 
      //create row container every other iteration 
      if (!isOdd(i)) { 
       rowDiv = document.createElement("div"); 
       $(rowDiv).addClass("row-fluid"); 
       elem.appendChild(rowDiv); 
      } 
      //add column for every iteration 
      var colDiv = document.createElement("div"); 
      $(colDiv).addClass("span6"); 
      rowDiv.appendChild(colDiv); 
      //actual code has fairly complex button html here 
      var htmlDiv = document.createElement("div"); 
      var htmlButton = vFriends[i] 
      htmlDiv.innerHTML = htmlButton; 
      colDiv.appendChild(htmlDiv); 
      //i think i need to add the event to the template too? 
      //$(htmlDiv).attr("data-bind", "click: { alert: $data }") 
      //it seems that the SetSelected Method is called while looping 
      ko.applyBindingsToDescendants(htmlDiv, { click: friends.SetSelected(vFriends[i]) }); 
      i++; 
     } 
     return { controlsDescendantBindings: true }; 
    } 
} 

var friends = new FriendsModel(); 
friends.Friends.push('bob'); 
friends.Friends.push('rob'); 
friends.Friends.push('mob'); 
friends.Friends.push('lob'); 
ko.applyBindings(friends); 
+0

在小提琴的代码不匹配,你有什么这里有几个语法错误 – 2013-04-07 17:48:39

+0

好吧,我打了更新,现在(和附加/ 6 /),给它一个再试一次? – Justin 2013-04-07 17:51:55

回答

1

你正确使用ko.applyBindingsToDescendants我不认为。我承认我对代码中某些值的含义有点困惑,所以我可能会错误地解释某些东西。

这里有一个小提琴,我认为这是工作,你希望的方式: http://jsfiddle.net/5SPVm/7/ http://jsfiddle.net/5SPVm/8/

注意,如果手动控制后代绑定(return { controlsDescendantBindings: true };),你需要设置了在init回调,而不是更新。更新回调为时已晚。

的变化(编辑)快速破败

  1. 移动controlsDescendantBindingsinit
  2. 添加了必要的参数名称绑定回调到绑定PARAM列表访问附加价值。
  3. 我重新启用了html.attr调用。请注意,现在,由于绑定上下文被设置为实际项目,因此SetSelected方法不再存在于该级别,因此有必要使用$parent.SetSelected

     $(htmlDiv).attr("data-bind", "click: $parent.SetSelected") 
    
  4. 修正了ko.applyBindingsToDescendants电话。此方法采用绑定上下文,该绑定上下文是从当前绑定上下文创建的,并且还将该元素应用于绑定。你不想重新使用绑定,这就是为什么整个事情需要在init处理程序中。

     var childBindingContext = bindingContext.createChildContext(vFriends[i]); 
        ko.applyBindingsToDescendants(childBindingContext, colDiv); 
    
+0

谢谢!这很好,但在我的生产场景中,所有项目都是在初始绑定之后添加的,并且在它们被推送时似乎没有调用init。你可能会帮我在初始化和更新之间拆分代码以适应这种情况?我用你的小提琴“摆弄”,但它只是让我头疼。 – Justin 2013-04-07 21:06:05

+0

我错了applyBindingsToDescendants在init中。我会更新答案。 'controlDescendantsBindings:true' * does *需要在init中。更新中的其他一切都很好。 http://jsfiddle.net/5SPVm/8/。 – 2013-04-07 22:37:27