在选项卡导航上自动保存Knockout视图模型 - 如何获取绑定到DOM元素的视图模型

时间:2014-12-09 15:16:16

标签: javascript jquery twitter-bootstrap knockout.js

当用户从选项卡(Bootstrap 2)中导航时,我正在尝试在Knockout视图模型上调用我的保存方法

这可以在显示标签时触发保存

//This section should save when flipped away from
<a href="#cardiovascular" data-toggle="tab" data-bind="event: { shown: cardio.save }">Cardio</a>

//Click handler works here as well, navigating from Cardio to Respiratory should save Cardio
<a href="#respiratory" data-toggle="tab" data-bind="click: respiratory.save">Respiratory</a>

这是由Bootstrap文档给出的,可以绑定到选项卡上的事件

$('a[data-toggle="tab"]').on('shown', function (e) {
    e.target // activated tab
    e.relatedTarget // previous tab
})

有没有办法可以获取上一个标签的绑定上下文并保存?我唯一的想法是在主视图模型中使用开关编写函数或if / elseif将评估所选的选项卡并调用该存储方法,但这似乎很草率

在我的Knockout视图模型中,我有像这样的嵌套视图模型

var mainViewModel = function() {
    self.cardio = new cardioViewModel();
}

var cardioViewModel = function() {
   self.save = function() {
     //ajax call here
   }
}

并且每个嵌套的viewmodel都有一个save方法

修改

所以根据下面选择的答案,我有以下脚本

$('#generalAssessment a[data-toggle="tab"]').on('shown', function (e) {
    var boundElement = $(e.relatedTarget).attr("href");

    context = ko.contextFor($(boundElement)[0]);
})

这个想法是Bootstrap选项卡的目标是附加data-bind="with: whateverViewModel"的元素。下面是绑定到子视图模型的选项卡窗格的代码

<div id="cardiovascular" class="active tab-pane" data-bind="with:cardio">
    //All of my viewmodel stuff is bound here
</div>

但是,ko.contextForko.dataFor在这种情况下为我提供了根视图模型mainViewModel而不是由with子句绑定的viewmodel,cardioViewModel {1}}。有没有办法轻易引用那个上下文?

编辑2

由于ko.dataForko.contextFor获取所选元素的绑定上下文,因此选项卡本身仍然受mainViewModel的约束,因此按预期工作。

我只需要遍历一个与子视图模型绑定的额外元素,并选择执行以下操作

var boundElement = $(e.relatedTarget).attr("href");
var boundWithContext = $(boundElement).children().first();

ko.contextFor($(boundWithContext)[0]);

这将为我提供选定的标签窗格,因此在这种情况下

<div id="cardiovascular" class="active tab-pane" data-bind="with:cardio">
    //All of my viewmodel stuff is bound here
</div>

然后选择可以在新上下文中绑定的第一个子元素,在这种情况下是<h4>没有任何绑定上下文

 <h4 class="muted">Cardiovascular</h4>

将其记录到控制台会选择我正在寻找的相应内容

{ 
  $data: cardioViewModel,
  $parent: mainVieModel,
  $rawData: cardioViewModel,
  $root: mainViewModel
}

所以从那里我应该可以打电话给$data.save(),一切都会好的!谢谢你的帮助。

2 个答案:

答案 0 :(得分:0)

您应该能够在当前方法中使用relatedTarget来获取上一个标签

e.relatedTarget // previous tab

http://getbootstrap.com/2.3.2/javascript.html#tabs

答案 1 :(得分:0)

在bootstrap shown事件中,您可以使用ko.dataFor(element)ko.contextFor(element)来确定绑定到当前/上一个选项卡的视图模型。您在此处拥有ko.dataForko.contextFor的文档:Using unobtrusive event handlers。当然,如果您没有直接绑定到tab元素,则可以使用jQuery traversing functions在选项卡中查找绑定元素。

dataFor可以返回一个简单的observable,具体取决于传递的元素。 contextFor将允许访问整个上下文:绑定的可观察或视图模型,$parent$root等。

例如,如果你打电话给#o; ko.dataFor($(&#39; #vascular&#39;)[0])&#39;你得到cardioViewModel。请记住,您必须传递一个DOM元素,而不是jQuery集合,这是您在选择器之后使用[0]所需的方式。