编辑对象数组中新添加的项目并更新DOM

时间:2016-05-28 18:12:11

标签: javascript jquery knockout.js

这里是JSFiddle

对象数组如下所示:

ConferenceUsers

我需要能够添加和编辑新的var ConferenceUser = function (user) { this.ConferenceId = ko.observable(user.ConferenceId); this.Email = ko.observable(user.Email); this.Id = ko.observable(user.Id); this.Name = ko.observable(user.Name); this.PhoneNumber = ko.observable(user.PhoneNumber); };

添加新用户有效,但我无法对其进行编辑。

ConferenceUser ViewModel:

var createConferenceUser = function (user) {
    return new ConferenceUser(user);
};

var ConferenceList = function(conferencesJSON) {
  var self = this;

  var users = [];
  for (i = 0; i < conferencesJSON.length; i++) {
      users.push(conferencesJSON[i].ConferenceUsers);
  }

  this.conferences = ko.observableArray(conferencesJSON.map(createConference));
  this.conferenceUsers = ko.observableArray(users.map(createConferenceUser));

  this.addConference = function(conferenceJSON) {
    self.conferences.push(createConference(conferenceJSON));
  };
};

ko.applyBindings(new ConferenceList(data));

ConferenceList ViewModel和映射:

ConferenceUsers

问:如何更新现有/新添加的{{1}}和DOM,例如jsFiddle

1 个答案:

答案 0 :(得分:1)

就像我评论的那样:如果您实际使用具有可观察属性的ConferenceUser视图模型,您很可能能够弄清楚如何同时创建新编辑现有的用户。我确实看到了一些其他改进点,所以我认为仍然值得为你的问题制定一个答案:

  • 编辑/保存/取消逻辑使您的Conference视图模型变得混乱,可以很容易地分成自己的小部件
  • 您在添加更新按钮界面之间切换的方式与淘汰赛无法正常进行

我写了一个更多关于架构的答案,因为我觉得你的问题的答案自然地来自明确的关注点分离。因为我喜欢重构:)

这是我移动后的建议。您可以自己决定使用多少,但至少可以在代码中找到问题的答案!

<强> ConferenceList

仅用于管理会议列表。可以使用removeConferencegetConferencesFromServer等轻松扩展

var ConferenceList = function(conferencesJSON) {
  this.conferences = ko.observableArray(conferencesJSON.map(Conference.create));

  this.addConference = function(conferenceJSON) {
    self.conferences.push(Conference.create(conferenceJSON));
  };
};

<强>会议

保存ConferenceUser个实例和窗口小部件列表,以编辑和创建新用户。 这是您回答问题的地方:

var Conference = function(conferenceJSON) {
  var self = this;
  this.Id = conferenceJSON.Id;

  // Note that we're mapping the plain objects from the json to
  // ConferenceUser instances!
  this.users = ko.observableArray(
    conferenceJSON.ConferenceUsers.map(ConferenceUser.create));

  this.userEditor = new UserEditor(this.users, this.Id);

  this.onUserClick = function(user, event) {
    self.userEditor.edit(user);
  };
};

<强> ConferenceUser

这是我们确保在编辑后更新用户界面的地方:请注意EmailPhoneNumber属性是可观察的。我没有为所有属性创建observable,以指示并不是要在UI中更改所有属性。

var ConferenceUser = function(user) {
  this.Email = ko.observable(user.Email);
  this.PhoneNumber = ko.observable(user.PhoneNumber);

  this.ConferenceId = user.ConferenceId;
  this.Id = user.Id;
  this.Name = user.Name;
};

我创建了一个静态创建方法有两个原因:

  1. 它跟踪封闭内的id以确保它是唯一的
  2. Array.prototype.map方法中使用它很容易。
  3. 代码:

    ConferenceUser.create = (function() {
      var id = 0;
    
      return function(userOptions) {
        // Add an ID if not present in options
        return new ConferenceUser(Object.assign(userOptions, {
          Id: userOptions.Id || id++
        }));
      };
    }());
    

    <强> UserEditor

    这是对您的代码的最大改进(我相信):一个编辑器小部件,可帮助您创建,编辑和保存新用户。它暴露的方法更容易理解和编写,因为它们不在Conference视图模型中。

    var UserEditor = function(users, conferenceId) {
      var self = this;
    
      // Holds the user that's being edited, is null when
      // creating a new user
      this.editing = ko.observable(null);
    
      this.phoneInput = ko.observable("");
      this.emailInput = ko.observable("");
    
      this.clear = function() {
        self.phoneInput("");
        self.emailInput("");
      };
    
      this.add = function() {
        var newUserOptions = {
          Email: self.emailInput(),
          PhoneNumber: self.phoneInput(),
          ConferenceId: conferenceId
        };
        users.push(ConferenceUser.create(newUserOptions));
        self.clear();
      };
    
      this.edit = function(user) {
        self.editing(user);
    
        self.phoneInput(user.PhoneNumber());
        self.emailInput(user.Email());
      };
    
      this.reset = function() {
        self.editing(null);
        self.clear();
      };
    
      this.save = function() {
        var currentUser = self.editing();
    
        currentUser.Email(self.emailInput());
        currentUser.PhoneNumber(self.phoneInput());
    
        self.reset();
      };
    
    };
    

    现在,在所有这些代码之后,您将看到您的HTML非常直接。这是您的编辑小部件

    <div data-bind="with: userEditor">
      <input type="tel" placeholder="phone number" 
        data-bind="value: phoneInput" />
      <input type="email " placeholder="email" 
        data-bind="value: emailInput" />
      <!-- ko ifnot: editing -->
      <button data-bind="click: add">Add</button>
      <!-- /ko -->
      <!-- ko if: editing -->
      <button data-bind="click: save">Save</button>
      <button data-bind="click: reset">Cancel</button>
      <!-- /ko -->
    </div>
    

    有一个很长的故事来修复,但如果你已经做到这一点:这是一个更新的小提琴! https://jsfiddle.net/e2ox4doj/