在knockout中引用视图模型外部的对象构造函数的属性

时间:2016-03-21 18:18:23

标签: javascript knockout.js

所以,我不完全确定如何将这个问题说出来,因为它有点二合一。我有一个奇怪的问题,我有一个对象构造函数从HTML表单创建新的'项目',然后在提交表单时将其推送到observableArray。一切正常,但要引用相关的observable,我必须使用'value:Project.title'或'value:Project.whatever'。我还没有看到'value:NameOfConstructor.property'在我见过的任何例子中使用过。我假设这是这样工作的,因为构造函数在我的视图模型之外。

我的问题是:有没有更好的方法在不在我的视图模型中的构造函数中分配属性的值?换句话说,是否有比'Project.title'更好或更正确的方法,等等? 我部分问,因为我的代码中的一件事目前不起作用;敲门启用属性在我的“新建项目”按钮上不起作用,即使在“标题”输入框中写入了某些内容,它也会保持禁用状态。我感觉这是因为它被写成data-bind ='enable:Project.title'但我无法想象如何编写它。

我已经包含了一个jsfiddle供参考,但由于外部依赖性,它显然无效。 https://jsfiddle.net/bmLh0vf1/1/

我的HTML:

<form id='addBox' action='#' method='post'>
    <label for='pTitle'> Title: </label>
    <input id='pTitle' data-bind='value: Project.title' />
    <br/>
    <label for='pPriority'> Priority </label>
    <select id='pPriority' data-bind='options: priorityOptions, value: Project.priority'></select>
    <br/>
    <button data-bind='enable: Project.title, click: newProject'>New Project</button>
  </form>

我的Javascript:

function Project(title, priority) {
  this.title = ko.observable(title);
  this.priority = ko.observable(priority);
};


function ProjectViewModel() {
  var self = this;
  this.priorityOptions = ko.observableArray(['High', 'Medium', 'Low'])
  this.projectList = ko.observableArray([
    new Project('Create App', 'High')
  ]);
  this.newProject = function() {
    var np = new Project(Project.title, Project.priority);
    self.projectList.push(new Project(Project.title, Project.priority));
    console.log(self.projectList().length);
    if (self.projectList().length > 1) {
      console.log(self.projectList()[1].title());
    };
  }
};

var viewModel = new ProjectViewModel();
$(document).ready(function() {
  ko.applyBindings(viewModel);
});

最后,如果我错过任何发布约定或者我的代码特别糟糕,我会道歉。我很新,还在教自己。

1 个答案:

答案 0 :(得分:2)

您的代码在title创建的对象上设置了prioritynew Project属性,但稍后您希望在Project本身上看到这些属性。它没有它们; Project是函数,而不是new Project创建的对象。因此Project.titleProject.priority将为您提供undefined(而不是value绑定的可观察目标,因此没有用。

相反,有一个&#34;编辑&#34;您使用的Project 实例,将输入的value绑定到编辑&#39;实例titlepriority,然后在newProject中获取该实例并将其替换为新的实例。

粗略地说,在ProjectViewModel的构造函数中:

this.editing = ko.observable(new Project());

Project更新为默认titlepriority

function Project(title, priority) {
  this.title = ko.observable(title || "");
  this.priority = ko.observable(priority || "Medium");
}

在绑定中:

<input id='pTitle' data-bind='value: editing().title' />
<select id='pPriority' data-bind='options: priorityOptions, value: editing().priority'></select>

newProject

var np = this.editing();
this.editing(new Project());

然后在添加到数组时使用np(而不是另一个new Project)。

这是一个简单的例子:

&#13;
&#13;
function Project(title, priority) {
  this.title = ko.observable(title || "");
  this.priority = ko.observable(priority || "Medium");
}


function ProjectViewModel() {
  var self = this;
  this.priorityOptions = ko.observableArray(["High", "Medium", "Low"]);
  this.projects = ko.observableArray();
  this.editing = ko.observable(new Project());
  this.addProject = function() {
    this.projects.push(this.editing());
    this.editing(new Project());
  };
}

ko.applyBindings(new ProjectViewModel(), document.body);
&#13;
<div>
  <div>
    <label>
      Title:
      <input type="text" data-bind="value: editing().title, valueUpdate: 'input'">
    </label>
  </div>
  <div>
    <label>
      Priority:
      <select data-bind='options: priorityOptions, value: editing().priority'></select>
    </label>
  </div>
  <div>
    <button type="button" data-bind="click: addProject, enable: editing().title">Add Project</button>
  </div>
  <hr>
  <div>Projects:</div>
  <div data-bind="foreach: projects">
    <div>
      <span data-bind="text: title"></span>
      (<span data-bind="text: priority"></span>)
    </div>
  </div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
&#13;
&#13;
&#13;