【问题标题】:Customizing object "create" in knockoutjs - property bindings work on load, but not when creating new object在 knockoutjs 中自定义对象“创建”-属性绑定在加载时起作用,但在创建新对象时不起作用
【发布时间】:2013-02-02 07:36:08
【问题描述】:

我正在使用 ko.mapping.fromJS(data, mapping) 方法从服务器转换我的模型,以便我可以向我的子模型添加更多属性。

按照此处的示例: http://knockoutjs.com/documentation/plugins-mapping.html => "使用“create”自定义对象构造

这是我的代码:

var Employer = function (data) { 
        ko.mapping.fromJS(data,{}, this); 
        this.Foo = ko.observable("bar"); // added properties will go here. 

        console.log(this.Foo());      // i see this getting called OK on initial creation, and subsequent creations
        console.log(this.Name()); // ** this is only OK during initial creation, but on subsequent times i get "[Object] does not have a property Name" this property comes from the server model..** 
        }; 

        var mapping = {     
            'Employers' : { 
                create: function (options) {
                     var e = new Employer(options.data);
                     return e;
                } 
            } 
        }; 

        model = ko.mapping.fromJS(data, mapping); 

到目前为止,一切正常!

问题发生在这里:

        model.addEmployer = function (options, o2) {
            var e = new Employer(options);
             this.Resume.Employers.push(e);
        }; 

我在这里遗漏了一些东西..当我想向集合中添加一个新对象时,它丢失了来自模型(来自服务器)的所有属性,这些属性是通过这一行添加的“ko.mapping。 fromJS(data,{}, this); " 在 Employer 构造函数中。

我猜我需要在 addEmployer 函数中重复一些类似的映射,这会将所有服务器端属性重新绑定到客户端模型

我是这样称呼 addEmployer 的:

 <button data-bind="click: addEmployer">...</button>

更新

归结为,当在映射中声明 'create' 事件时,该函数接收 options 对象,该对象具有 options.data 可用于此调用:ko.mapping.fromJS(data,{}, this); .. 我不确定如何在我的 addEmployer 处理程序中获取此类对象,以便为所有属性提供必要的绑定存在于服务器上的 Employer 对象上。

我可以通过保留初始绑定中的 options.data 并在 addEmployer 处理程序中重新使用它来破解它。问题在于,它将具有从该初始对象设置的所有属性。

我基本上需要的是 EmployerMappingOptions 对象,它是空的。在上面的实现中,options.data 预先填充了我集合中第一个 Employer 对象的数据。 如何获取空 Employer 模型的映射数据

【问题讨论】:

  • 在 addEmployer 方法中传递 this 作为映射转换的目的地是正确的吗?也许您想将数据加载到新雇主 e 中?
  • @Grim 是的,我在这里尝试了一些方法。我会用它来更新我的问题。
  • 为什么要先映射两次,在构造函数中,然后在返回时再次映射?
  • 如何调用模型的 addEmployer 方法?来自服务器的数据?还是直接在页面内(例如,来自绑定,直接或不直接)?
  • @Grim 从绑定中调用它。我添加了代码。

标签: knockout.js


【解决方案1】:

你的问题是在add函数中映射时没有添加任何数据

要么:给它一个虚拟数据对象 http://jsfiddle.net/mfauL/1/

this.Employers.push(new EmployerViewModel({ Name: "" }));

或显式声明可观察的名称(首选方式) http://jsfiddle.net/mfauL/2/

EmployerViewModel = function (data) { 
    this.Foo = ko.observable("bar"); 
    this.Name = ko.observable(); 

    ko.mapping.fromJS(data,{}, this); 
}; 

【讨论】:

  • 就像我说的模型来自服务器。初始数据变量包含我的模型和子模型的整个 JSON。这样做的重点是仍然能够向子模型添加东西。 ..并且该映射的重点是添加来自服务器的该模型的所有属性。这实际上适用于第一个绑定..当我添加新雇主时它会丢失
  • 我试图避免在 javascript 代码中重新定义我的整个模型,因为它来自服务器。
  • 我想到了这一点:ko.mapping.fromJS(data,{}, this);在构造函数中,它会将所有绑定添加到来自初始 JSON 的属性
  • 不,它不是自动的,javascript 是无类型的,它不能跟踪视图模型类型。然而,它确实有助于保持视图模型与服务器数据同步
  • 正确。我没想到它会给 js 提供强类型。但是它确实第一次工作,因为它使用来自服务器的对象(在 json 转储中)来确定应该在其上的属性。我只需要在添加新对象时重复这个过程。这肯定是一个常见的用例吗?
【解决方案2】:

想出了一个解决方案。

  1. 将有问题的子类(子模型)作为主模型的属性公开

    公开简历雇主 EmptyEmployer { 获取 { 返回新的 ResumeEmployer(); } }

  2. 创建它的 JSON 表示

    var newEmployerJson = @Html.Raw(Json.Encode(Model.EmptyEmployer));

  3. 在客户端创建新雇主时,使用空定义 json 进行绑定

        var Employer = function (data) { 
            if (data)
                ko.mapping.fromJS(data,{}, this);   // existing data in serialized model
            else
                ko.mapping.fromJS(newEmployerJson, {}, this); // json of single empty Employer class 
            ... 
         }                  
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    • 2015-10-08
    • 2017-10-24
    • 1970-01-01
    • 1970-01-01
    • 2017-03-27
    相关资源
    最近更新 更多