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\$
  • \$\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\$ – 200_success May 13 '15 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\$ – Dawood Awan May 13 '15 at 10:18
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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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