Skip to content Skip to sidebar Skip to footer

Edit Newly Added Items Within Array Of Objects And Update Dom

Here's the JSFiddle. The array of objects looks like below: var data = [{ 'ConferenceUsers': [{ 'Id': 3006, 'ConferenceId': 8, 'Name': null, 'Email': 'mail@lala.c

Solution 1:

Like I commented: if you were to actually use the ConferenceUser view models with the observable properties, you would probable able to figure out how to both create new, and edit existing users. I do see some other points of improvement though, so I think it's still worth to formulate an answer to your question:

  • The edit/save/cancel logic is cluttering your Conference view model and can easily be separated into its own little widget
  • The way you're switching between the Add and Update button UI doesn't work well with knockout

I've written an answer that's more about the architecture because I feel that the answer from your question follows naturally from a well defined separation of concerns. And because I enjoy refactoring :)

Here's my suggestion after having moved stuff around. You can decide for yourself how much of it you'll use, but at least the answer to your question can be found in the code!

ConferenceList

Only serves to manage a list of conferences. Could easily be extended with removeConference or getConferencesFromServer etc.

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

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

Conference

Holds a list of ConferenceUser instances and a widget to edit and create new users. This is where your question is answered:

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

This is where we make sure the UI is updated after edits: note that the Email and PhoneNumber properties are observable. I didn't create observables for all properties to indicate not all properties are meant to be changed in the 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;
};

I've created a static create method for two reasons:

  1. It keeps track of an id inside a closure to make sure it's unique
  2. It's easy to use inside an Array.prototype.map method.

The code:

ConferenceUser.create = (function() {
  var id = 0;

  returnfunction(userOptions) {
    // Add an ID if not present in optionsreturnnewConferenceUser(Object.assign(userOptions, {
      Id: userOptions.Id || id++
    }));
  };
}());

UserEditor

This is the biggest improvement (I believe) to your code: an editor widget that helps you create, edit and save new users. The methods it exposes are much easier to understand and write because they're not inside your Conference viewmodel.

varUserEditor = function(users, conferenceId) {
  var self = this;

  // Holds the user that's being edited, is null when// creating a new userthis.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();
  };

};

Now, after all this code, you'll see your HTML is very straight forward. Here's your edit widget:

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

Kind of a long story to get to the fix, but if you've made it this far: here's an updated fiddle! https://jsfiddle.net/e2ox4doj/

Post a Comment for "Edit Newly Added Items Within Array Of Objects And Update Dom"