绑定不来自ViewModel的价值观

时间:2012-11-01 16:50:07

标签: grails knockout.js

我正在尝试将KnockoutJS逐渐洒入我现有的应用程序中。我对此的第一个尝试是采用一些小的现有形式,并将它们的值推送到服务器上,并通过绑定更新一些元素。

我遇到的问题是,当首次显示表单时,它不会通过knockout填充。我正在使用表单中已有的数据呈现页面。所以我设置了这样的淘汰赛:

function DomainViewModel() {
  this.name = "";
  this.description = "";
}

ko.applyBindings(new DomainViewModel());

我的表格是这样的:

<input data-bind="value: name" value="${domainInstance.name.encodeAsHTML()}"/>
<textarea data-bind="value: description" >${domainInstance.description.encodeAsHTML()}</textarea>

所以正在发生的是我的表单被显示然后knockout将ViewModel中的值应用到表单中,这会消除服务器放置的值。我理解为什么会发生这种情况并且这不是一个错误。但是,我想知道这里是否还有其他选择。

我知道我可以做以下事情:

function DomainViewModel() {
  this.name = "${domainInstance.name}";
  this.description = "${domainInstance.name}";
}

但这需要我将一些javascript直接放在GSP中(我使用的是Grails)而不是外部脚本文件。

1 个答案:

答案 0 :(得分:5)

所以,你有几种方法可以做到这一点。首先,永远不要这样做

function DomainViewModel() {
  this.name = "${domainInstance.name}";
  this.description = "${domainInstance.name}";
}

您的viewmodel刚刚变得不可重复使用。如果你想使用grails来填充viewmodel,在页面上设置一些javascript对象,并将其传递到你的外部javascript文件viewmodel定义,就像这样(不要忘记让你的属性可观察!):

var grailsData = {
    name : "${domainInstance.name}",
    description : "${domainInstance.name}"
};

  ...
function DomainViewModel(data) {
  this.name = ko.observable(data.name);
  this.description = ko.observable(data.description);
}

ko.applyBindings(new DomainViewModel(grailsData);

我会推荐这种方法,因为稍后当您更改数据源时,您不必更改HTML。但是,还有另一种选择。您可以创建一个从元素中收集值的绑定,并使用它来设置初始可观察值。这种绑定可能如下所示:

ko.bindingHandlers.valueWithInit= {
    init: function(element, valueAccessor) {
        valueAccessor()(element.value);
    },
    update: function(element, valueAccessor) {
        var value = valueAccessor();
        element.value = ko.utils.unwrapObservable(value);
    }
};

以下a fiddle演示了此方法的实施