1
\$\begingroup\$

I have a situation where I have a ViewModel:

// Main_ViewModel

function MainViewModel()
{
     var self = this;
     this.customerList = ko.observableArray(GetCustomersFromServer());
}

// BIND VIEWMODEL

ko.applyBindings(new MainViewModel());


// GET CUSTOMERS FROM SERVER

function GetCustomersFromServer (){

  var customers = [];
  $.ajax({
        //.....other options...
        success: function(response){ 

        for(var i =0; i < response.length; i++){
             customers.push(new Customer(response[i]));
         }
    }   
   });
  return customers;
}

// HTML:

<div class="customerSection" data-bind="foreach: customerList">
  <div class="form-group">
     <label class="main-label">Customer Name</label>
      <input type='text' class="form-control" data-bind="value: CustomerName" /> 
  </div>
</div>

// CUSTOMER VIEW MODEL

function Customer(customer) {
    var self = this;

    if (customer === undefined || customer === null) {
        self.CustomerId = ko.observable();
        self.CustomerName = ko.observable();
        self.DateOfBirth = ko.observable(new Date());
        self.EmailAddress = ko.observable();

        self.CustomerContacts = ko.observableArray();
    }
    else {
        self.CustomerId = ko.observable(customer.CustomerId);
        self.CustomerName = ko.observable(customer.CustomerName);
        self.DateOfBirth = ko.observable(customer.DateOfBirth);
        self.EmailAddress = ko.observable(customer.EmailAddress);

        self.CustomerContacts = ko.mapping.fromJS(customer.CustomerContacts, customMapping);

    }
}

There are two ways to declare ViewModel:

  1. var customer = new Customer(); will be used to create a new Customer. This will add a new customer.
  2. var customer1 = new Customer(customerParameter); is used to update an existing customer. Customer Object is returned from server (JSON format) and assigned to the viewModel.

Is there a cleaner way to define this ViewModel?

Like in C#, we have multiple constructors:

public class Customer
{

    public int CustomerId {get;set;}
    public DateTime DateOfBirth {get;set;}

    public Customer(int customerId): this()
    {
        CustomerId = customerId;
    }

    public Customer()
    {
        DateOfBirth = DateTime.Now;
    } 
}

Is there something similar I can do in JavaScript - KnockoutJS?

\$\endgroup\$
2
  • \$\begingroup\$ Please provide more details about your no-argument and one-argument use cases. For example, what does it mean to have no CustomerId, and how would the CustomerId get assigned later? \$\endgroup\$ May 13, 2015 at 9:41
  • \$\begingroup\$ I have added the information you asked for, but I don't see how it is related to the Question, as my Question is only related to the Customer ViewModel \$\endgroup\$ May 13, 2015 at 10:18

1 Answer 1

3
\$\begingroup\$

The issue that I have with the viewmodel, and I suspect that it is the issue that you're having, is that you have two code paths to keep in sync when initializing the object.

By getting rid of the if {} else {} and having a default value going into the knockout observable as an alternative value then you reduce the lines of code and you only define the properties of the object once.

Something like this: I have used undefined as the default in this case

function Customer(customer) {
    var self = this;
    self.CustomerId = ko.observable(customer.CustomerId || undefined);
    self.CustomerName = ko.observable(customer.CustomerName || undefined);
    self.DateOfBirth = ko.observable(customer.DateOfBirth || undefined);
    self.EmailAddress = ko.observable(customer.EmailAddress || undefined);
    self.CustomerContacts = customer ?  ko.mapping.fromJS(customer.CustomerContacts, customMapping): ko.observableArray();
}
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.