使用Ajax加载选项卡

时间:2016-01-01 22:46:35

标签: asp.net-mvc twitter-bootstrap knockout.js

我有一个bootstrap导航标签,我想在选择标签时动态显示内容。每个选项卡必须显示一个div,其中包含一些文本,这些文本是在控制器的操作GetSection()从ajax调用返回的。

<div class="tabbable">
    <ul class="nav nav-tabs" data-bind="foreach: sections">
        <li data-bind="css: { active: isSelected }">
            <a href="#" data-bind="click: $parent.selectedSection">
                <span data-bind="text: name" />
            </a>
        </li>
    </ul>

    <div class="tab-content" data-bind="foreach: sections">
        <div class="tab-pane" data-bind="css: { active: isSelected }">
            <span data-bind="text: 'In section: ' + retValue" />
        </div>
    </div>
</div>

Javascript代码:

var Section = function (name, selected) {
    this.name = name;
    this.retValue = "";
    this.isSelected = ko.computed(function () {
        return this === selected();
    }, this);
}

var ViewModel = function () {
    var self = this;
    self.selectedSection = ko.observable();
    self.sections = ko.observableArray([
        new Section('Tab One', self.selectedSection),
        new Section('Tab Two', self.selectedSection),
        new Section('Tab Three', self.selectedSection)
    ]);
    self.selectedSection(self.sections()[0]);

    self.selectedSection.subscribe(function () {
        $.ajax({
            url: '@Url.Action("GetSection")',
            data: { name: self.selectedSection().name },
            type: 'GET',
            success: function (data) {
                self.selectedSection().retValue=data.text;
            }
        });

    });

}

ko.applyBindings(new ViewModel());

问题是没有显示来自ajax的retValue。控制器动作如下:

public JsonResult GetSection(string name)
{
    var ret = new { text = name + "abcd" };
    return Json(ret, JsonRequestBehavior.AllowGet);
}

2 个答案:

答案 0 :(得分:1)

Knockout只能知道更新无法阻挡的属性的视图(因此名称),因此您需要使retValue可观察:

var Section = function (name, selected) {
    this.name = name;                                // <-- consider similar change here too
    this.retValue = ko.observable("");               // <-- change here
    this.isSelected = ko.computed(function () {
        return this === selected();
    }, this);
}

然后,你需要记住设置一个可以阻挡的值,方法是将它作为一个方法,将新值作为唯一的参数,例如:

    $.ajax({
        url: '@Url.Action("GetSection")',
        data: { name: self.selectedSection().name },
        type: 'GET',
        success: function (data) {
            self.selectedSection().retValue(data.text);    // <-- change here
        }
    });

最后,如果您要绑定到视图中的复杂表达式,则需要将其作为函数调用(使用 no 参数),以获取其值:

<span data-bind="text: 'In section: ' + retValue()" />

作为旁注,请注意,如果直接绑定到observable,可以省略括号(从敲击中考虑它的语法糖),例如:

<span data-bind="text: retValue" />

这实际上相当于:

<span data-bind="text: retValue()" />

在脚注上,我看到您已将此语法用于click绑定:

<a href="#" data-bind="click: $parent.selectedSection">...</a>

这有效...但只是巧合。你应该一起意识到这些事情:

  • $parent.selectedSection包含ko.observable()的结果,这意味着它实际上是一个可以调用的函数
  • click数据绑定将调用它作为函数获取的表达式,将上下文数据(在您的情况下为Section)传递给该函数

所以基本上,当click发生时,发生

$parent.selectedSection($data) // where $data == the current Section

有效选择章节。

如果$parent有一个函数,那就更加清晰了:

var self = this;
self.selectChild = function(section) {
  // Possibly handle other things here too, e.g. clean-up of the old selected tab
  self.selectedSection(section);
}

然后以这种清晰的方式使用点击装订:

<a href="#" data-bind="click: $parent.selectChild">...</a>

click上,将再次调用selectChild方法,并将上下文数据作为参数。

答案 1 :(得分:-1)

而不是这个 self.selectedSection()retValue = data.text;

这样做 self.selectedSection(数据);