【问题标题】:Unable to view data on an oservable无法查看 observable 上的数据
【发布时间】:2017-12-16 08:07:10
【问题描述】:

我有一个 View 模型,它有一个 loaddata 函数。它没有构造函数。如果 ID 字段有值,我希望它调用 loadData 方法。

该字段通过以下方式获得:

self.TemplateId = ko.observable($("#InputTemplateId").val());

然后,在我的 ViewModel 结束时,我有一些代码可以检查并调用我的加载函数:

if (!self.CreateMode()) {
        self.loadData();
    }

我的 load 方法调用了我的 .Net WebAPI 方法,该方法返回了一个稍微复杂的结构。该结构是一个类,有几个字段和一个数组/列表。该列表中的项目是一些基本字段和另一个列表/数组。然后那个对象只有几个字段。所以,它是3个级别。一个对象,带有一个对象列表,这些对象每个都有另一个对象列表...

我的 WebAPI 调用正在运行。我已经调试过了,数据恢复的很完美。

self.loadData = function () {
        $.get("/api/PlateTemplate/Get", { id: self.TemplateId() }).done(function (data) {
            self.Data(ko.mapping.fromJS(data));

        });
    }

我正在尝试将此调用的内容加载到一个名为“数据”的可观察对象中。之前已经声明过:

self.Data = ko.observable();

要加载它并保持一切可观察,我正在使用 Knockout 映射插件。

self.Data(ko.mapping.fromJS(data));

当我对此设置断点时,我看到了我对数据(API 调用的结果)和 self.Data() 的期望

self.Data 似乎是我加载的数据的可观察版本。所有数据都在那里,而且一切似乎都是正确的。

我能够提醒数据对象根中的一个字段的值:

alert(self.Data().Description());

我还可以在列表的第一项中看到一个字段。

alert(self.Data().PlateTemplateGroups()[0].Description());

这向我表明 Data 是可观察的并且包含数据。我想我以后可以将 self.Data 发布回我的 API 以保存/更新。

现在,问题开始了。

在我的视图中,我试图显示一个位于我的复杂项目的根类中的字段。我在上面提醒过的东西。

<input class="form-control" type="text" placeholder="Template Name" data-bind="value: Data.Description">

我没有错误。然而,文本框是空的。

如果我将输入框的代码更改为:

data-bind="value: Data().Description()"

显示数据。但是,我在控制台中遇到错误:

Uncaught TypeError: Unable to process binding "value: function (){return Data().Description() }" 消息:无法读取属性 未定义的“描述”

我认为这是由于视图加载,在从 WebAPI 调用加载数据之前,因此,因为我正在使用 ko.mapping - 视图不知道 Data().Description() 是什么...然后它就死了。

有没有办法解决这个问题,以便我可以实现我想要做的事情?下面是完整的 ViewModel。

function PlateTemplateViewModel() {
    var self = this;

    self.TemplateId = ko.observable($("#InputTemplateId").val());
    self.CreateMode = ko.observable(!!self.TemplateId() == false);

    self.IsComponentEditMode = ko.observable(false);
    self.IsDisplayMode = ko.observable(true);
    self.CurrentComponent = ko.observable();

    self.Data = ko.observable();

    self.EditComponent = function (data) {

        self.IsComponentEditMode(true);
        self.IsDisplayMode(false);
        self.CurrentComponent(data);

    }
    self.loadData = function () {
        $.get("/api/PlateTemplate/Get", { id: self.TemplateId() }).done(function (data) {
            self.Data(ko.mapping.fromJS(data));

        });
    }

    self.cancel = function () {
        window.location.href = "/PlateTemplate/";
    };

    self.save = function () {
        var data = ko.mapping.toJS(self.Data);
        $.post("/api/PlateTemplate/Save", data).done(function (result) {
            alert(result);
        });
    };

    if (!self.CreateMode()) {
        self.loadData();
    }
}

$(document).ready(function () {
    ko.applyBindings(new PlateTemplateViewModel(), $("#plateTemplate")[0]);
});

也许答案是在ready()函数内部进行加载,并将数据作为参数传入?不确定当我想创建一个新项目时会发生什么,但我可以做到。

此外,当我尝试保存时,我注意到即使我可能会更改视图中的字段(例如更新描述),观察到的视图模型 (self.Data) 中的数据也不会更改。

【问题讨论】:

  • 通过Data.Description,您希望指向视图模型中的Data属性或每个中的Data你的PlateTemplateGroups?换句话说,这个data-bind=... 究竟在哪里(在什么范围内)?另外,你试过value: Data() &amp;&amp; Data().Description &amp;&amp; Data().Description()吗?
  • 你可以试试这个:ko.mapping.fromJS(data, {}, self.Data); (knockoutjs.com/documentation/plugins-mapping.html, '指定更新目标')。
  • 谢谢@JoseLuis - 我都试过了。当我尝试这个时,我在尝试绑定我的视图的第一个字段上出现错误:无法处理绑定“值:函数(){return Data().Description()}”......当我删除(),编辑框为空。之前,它有来自 this.Data() 的数据。所以我不确定哪种方式是正确的以及为什么我没有得到任何数据。
  • @Craig 在这个 CodePen 中:codepen.io/anon/pen/KqJQqJ,如果你点击“加载数据”,数据就会更新。 ko.mapping.fromJS(parsed, {}, self.Data); 工作正常。
  • 等待等待等待!!!那行得通!你是一个美丽的人!哇...嗯,我得到了改进的结果。更改将返回到服务器!哇!我会修复它,因为它都被黑了,看看我是否完成了。谢谢。

标签: javascript c# asp.net-web-api knockout.js


【解决方案1】:

您的输入字段可能是这样的:

<div data-bind="with: Data">
    <input class="form-control" type="text" placeholder="Template Name" data-bind="value: Description">
 </div>

我更喜欢使用with 作为它的清洁剂,应该可以避免您遇到的困惑和问题。

出现错误的原因是在加载数据之前已经绑定了html。所以要么在加载数据之前不要应用绑定:

$.get("/api/PlateTemplate/Get", { id: self.TemplateId() }).done(function (data) {
        self.Data(ko.mapping.fromJS(data));
        ko.applyBindings(self, document.getElementById("container"));
    });

或者用if 包装模板,因此它不会给你这个错误,因为数据最初是未定义的。

self.Data = ko.observable(); // undefined

<!-- ko if: Data -->
<div data-bind="with: Data">
    <input class="form-control" type="text" placeholder="Template Name" data-bind="value: Description">
 </div>
<!-- /ko -->

此外,如果您知道数据模型将是什么,您可以将数据默认为这个。

self.Data = ko.observable(new Data());

应用绑定方法:

var viewModel = null;
$(document).ready(function () {
    viewModel = new PlateTemplateViewModel();
    viewModel.loadData();
});

【讨论】:

  • 在我的 document.Ready - 我应该删除 ko.ApplyBinding 吗?并将其移至我的 loadData 函数?如果是这样,它永远不会运行。
  • 在你的 documentReady 中替换 ko.applyBindings(viewModel, document.getElementById("container"));与 viewModel.loadData();
  • 该死,.. 我已经尝试过了,得到了相同的结果。发回我加载的原始模型。不是更新的。 this.Data 在我编辑字段时似乎没有更新。
  • 只是为了确认,在我的输入框中,我是这样绑定的: data-bind="value: Data().Description()" .... 显示数据,但不回发.
  • 你能搞定它吗?我不认为让它太工作有问题。但我相信,与其使用 self.Data(ko.mapping.fromJS(data)),不如使用 self.Data(new PlateTemplateData(data)) 而不是使用那里的映射,这会给你更多的控制权,然后就像我说的有问题而不是 self.Data = ko.observable() 即 undefined 您将拥有 self.Data = ko.observable(new PlateTemplateData()) 即一个空但绑定的形式
猜你喜欢
  • 1970-01-01
  • 2013-04-01
  • 1970-01-01
  • 2021-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多