从observableArray绑定未定义的字段或提供默认值

时间:2014-07-17 08:27:43

标签: javascript node.js mongodb knockout.js mongoose

问题是什么

假设我想对MongoDB进行查询并在表格中显示结果。有些文件比其他文件有更多或更少的字段 - 这对我来说很好。但是我在客户端遇到了一个问题。

我正在使用“mongoose”与模型通过NodeJS检索数据然后在客户端上,我正在使用“knockout.js”将列表绑定到表中。现在问题出现了 - 只要任何字段不存在,但是绑定在表中,KO就会抛出异常并停止处理。

我尝试了什么

  • 我尝试在mongoose-model上定义默认值,但这不会添加不存在的字段。此外,它会增加通过电线的有效载荷; - (

  • 我尝试了“knockout.punches”和“默认”文本过滤器,它可以正常工作,但只有当值为null或为空时。未定义仍会引发异常。

  • 我尝试了几种方法来使用KO的扩展机制,但是我必须在绑定中编写有线语法,或者它也不适用于未定义。

  • 我到目前为止没有尝试的另一种可能是在客户端上创建模型,然后将其映射到响应 - 老实说,我只是不想这样做,因为在大多数情况下,数据结构来自DB完全没问题,只是意味着额外的努力。

我在寻找什么

有没有人有一个解决方案可以自动将猫鼬模型中缺少的字段添加到响应中或让它运行,以便KO不会停止处理未定义的字段(可能有一些参数)。在我的例子中,它是一个可观察的阵列,这里的大多数解决方法和解决方案都是关于单个字段的。如此有趣的是具有未定义字段的列表的解决方案。

由于

[{"firstname":"Foo", "lastname":"Bar"},{"firstname":"John"}];

self.allUsers = ko.observableArray();

self.onResponseAllUsers = function (response) {
            if (response && response.length > 0) {                
                self.allUsers(response);
            }
        };

<tbody data-bind="foreach: allUsers">
<tr>
<td data-bind="text: firstname"></td>                           
<td data-bind="text: lastname"></td>   <<<< This is undefined for one row, and KO stops processing.
</tr>
</tbody>

1 个答案:

答案 0 :(得分:1)

有两种方法可以解决这个问题。

  1. 您可以使用||在绑定中,如果缺少属性,则给出默认值,因此绑定将如下所示: -

    <tbody data-bind="foreach: allUsers">
       <tr>
        <td data-bind="text: $data.firstname"></td>
        <td data-bind="text: $data.lastname || 'NA'"></td> // used $data context property
       </tr>
    </tbody>
    

    Fiddle Demo

  2. 您可以迭代所有记录以检查是否缺少任何属性,如果缺少某些内容,则可以提供一些默认值。

    function User(item) {
      this.firstname = item.firstname || "NA";
      this.lastname = item.lastname || "NA";
    }
    var viewmodel = function (data) {
      var self = this;
      self.allUsers = ko.observableArray();
      self.onResponseAllUsers = function (response) {
      if (response && response.length > 0) {
         ko.utils.arrayForEach(response, function (item) {
            self.allUsers.push(new User(item));
         });
      }
     };
      self.onResponseAllUsers(data);
    }
    

    Fiddle Demo