Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout conditional styling of the option elements of an "unbound" SELECT element

The various inputs on my page are bound via knockout to a view model, let's say a customer record. That's all working fine.

Now, I want to put a SELECT at the top of the page that contains a list of all customers. The user will pick a customer, the record will be fetched from the database, and the data will be bound to the view model.

My question concerns conditional styling of the items in that SELECT list. It will be bound to an array of customer objects. The Customer object definition has a function called hasExpired:

   var Customer = function (id, name, expiryDate) {
    this.id = id;
    this.customerName = name;
    this.expiryDate = expiryDate;
    this.hasExpired =  function() {
        return this.expiryDate == null ? false : true; 
      };
    };

The ViewModel, to which the inputs on the page are bound, looks like this:

      function ViewModel() {
            var self=this;
             self.customerRegion = ko.observable(),
             self.customerName = ko.observable(),
             .
             .
             .
             self.allCustomers = Customers,  // Customers is an array of Customer objects
             self.selectedCustomer = ko.observable()



     }

This knockout binding works; the SELECT is correctly populated with the list of customers:

    <select id="customerSelect" 
             data-bind="options: allCustomers,
            optionsText: 'customerName', 
            value:   selectedCustomer />

I want to style the individual OPTIONS, adding an "expired" class if appropriate.

The individual items in the Customers SELECT are not bound to the view model. The SELECT functions like a navigation menu. The options are bound to the customer objects in the allCustomers array.

How to tell knockout to consult the hasExpired property of the customer object bound to each OPTION, to determine whether that particular option should get the expired property?

I want the customer to remain in the Select list but to appear with strike-through formatting.

Does the SELECT require its own view model?

like image 691
Tim Avatar asked Feb 13 '23 04:02

Tim


1 Answers

The options binding has a parameter (optionsAfterRender) that allows for additional processing of the options elements. See Note 2: Post-processing the generated options (via the linked documentation).

Unless I have misinterpreted the structure of your data models, all that is required is a callback

self.setOptionStyling = function(option, item) {
   ko.applyBindingsToNode(option, {css: {expired: item.hasExpired()} }, item);
}

bound to the optionsAfterRender parameter:

<select id="customerSelect" 
        data-bind="options: allCustomers,
                   optionsText: 'customerName', 
                   value: selectedCustomer,
                   optionsAfterRender: setOptionStyling" />

Where the expired css class is defined as:

.expired {
   text-decoration: line-through;
}

Fiddle

like image 166
Origineil Avatar answered Feb 15 '23 09:02

Origineil