【问题标题】:Autosaving a Knockout viewmodel on tab navigation - how to get view model bound to DOM element在选项卡导航上自动保存 Knockout 视图模型 - 如何将视图模型绑定到 DOM 元素
【发布时间】:2015-02-07 13:08:40
【问题描述】:

当用户从选项卡离开导航时,我试图在 Knockout 视图模型上调用我的保存方法(引导程序 2)

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

//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
   }
}

每个嵌套的视图模型上都有一个save 方法

编辑

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

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

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

这个想法是引导选项卡的目标是附加了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 子句绑定的视图模型 cardioViewModel。有什么方法可以轻松引用那个上下文?

编辑 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>

然后挑选出可以在新上下文中绑定的第一个子元素,在这种情况下是&lt;h4&gt;,没有任何绑定上下文

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

将其记录到控制台可以找到我正在寻找的合适的东西

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

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

【问题讨论】:

  • 一开始我不明白你的问题,但现在我已经更新了我的答案,我想这次我正在提供你需要的东西,以及相关的文档。

标签: javascript jquery twitter-bootstrap knockout.js


【解决方案1】:

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

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

例如,如果您调用 'ko.dataFor($('#cardiovascular')[0])',您会得到 cardioViewModel。请记住,您必须传递一个 DOM 元素,而不是 jQuery 集合,这就是您需要在选择器之后添加 [0] 的方式。

【讨论】:

  • 我想我可以做到!谢谢!我知道 Knockout 有办法完成这项工作,但不知道这对我的生活有什么影响。
  • 这是 99%,但我将用更多信息更新我的问题以解决问题。
  • 其实我想我明白了!通过第二次编辑更新问题。如果您有比我想出的更好的主意,我们将不胜感激!
  • 不,没有比这更好的选择了。请注意我的回答中的“您可以使用 jQuery 遍历函数来查找选项卡内的绑定元素”。这完全是故意的。但是根据引导选项卡插件文档,这应该足够了:var boundElement = $(e.relatedTarget).children()[0]; 然后ko.contextFor(boundElement) 应该给你相同的结果。我不明白你为什么要提取href 属性,然后用它来获取选项卡元素,但我没有使用引导选项卡的经验,所以我可能是错的。但是您可以在children().first()[0] 中省略first())。
  • href 包含它需要显示的标签面板的 ID。我使用该 ID 来查找绑定了我的子视图模型的选项卡面板。 e.relatedTarget 只是给了我上一个标签的元素,我不需要。
【解决方案2】:

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

e.relatedTarget // previous tab

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

【讨论】:

  • 你错过了我想要做的事情。我正在尝试使用之前的选项卡 e.relatedTarget 并获取它与 Knockout 绑定的数据上下文,或者实现一个可以在我的 Knockout 视图模型上调用 ajax 保存的函数
  • 您是为每个选项卡绑定不同的上下文还是它们都包含在一个 ko 模型中?
  • 如上所述,我的mainViewModel 有嵌套的子视图模型。我的页面使用with Knockout 绑定与那些子视图模型绑定
猜你喜欢
  • 2014-09-24
  • 1970-01-01
  • 2013-01-03
  • 2012-08-04
  • 1970-01-01
  • 2014-03-06
  • 1970-01-01
  • 1970-01-01
  • 2014-07-31
相关资源
最近更新 更多