Knockoutjs list, Alternate of Checkbox and Radio

March 4th, 2014 — 8 min read

Knockoutjs list, Alternate of Checkbox and Radio

So today, i am going to present an alternate of check boxes and radio buttons i have created using knockout. Sometimes you might want to use a simpler way to handle check boxes and radio buttons using knockout. I have written a code snippet to meet the needs which is simple and easy to handle.

Alternate of Single CheckBox

So lets’s start. First lets see knockout model we are going to use.

function Filter(settings){
    var self    =   this
    self.Active     =   ko.observable(false)
    self.Id         =   ko.computed(function(){
        if(settings.activeId){
            return settings.activeId
        }else{
            return ( self.Active() == true ) ? 1 : 0
        }
    })
    self.Class      =   ko.computed(function(){
        settings.activeClass    =   (settings.activeClass) ? settings.activeClass : 'selected'
        settings.inActiveClass  =   (settings.inActiveClass) ? settings.inActiveClass : ''
        return ( self.Active() == true ) ? settings.activeClass : settings.inActiveClass
    })
    self.Label      =   ko.computed(function(){
        settings.activeText     =   (settings.activeText) ? settings.activeText : 'True'
        settings.inactiveText   =   (settings.inactiveText) ? settings.inactiveText : 'False'
        if(settings.toggleText==true){
            return (self.Active() == false) ? settings.inactiveText : settings.activeText
        }else{
            return settings.activeText
        }
    })
    self.LabelColor =   ko.computed(function(){
        if(settings.toggleTextColor == true){
            if(settings.activeTextClass){
                return ( self.Active() == true ) ? settings.activeTextClass : settings.inActiveTextClass
            }else{
                return ( self.Active() == true ) ? '' : ''
            }
        }
    })
    self.Toggle = function(){
        self.Active(!self.Active())
    }
    self.LoadData = function(){
        self.Active(settings.active)
    }
    self.LoadData()
}

Now let’s see how we can use it. For this i am going to create a simple model which will use it.

var page    =   function(){
    var self    =   this
 
    self.IsRead     =   ko.observable('')
 
    self.InitializeData =   function(){
        var options =   {
            toggleText          :   true,
            active              :   false,
            toggleTextColor     :   true,
            activeId            :   23,
            activeClass         :   '',
            inActiveClass       :   'un_check',
            activeText          :   'I have accepted',
            inactiveText        :   'I have not accepted',
            activeTextClass     :   'selected_filter',
            inActiveTextClass   :   ''
        }
        self.IsRead(new Filter(options))
    }
    self.InitializeData()
}
 
$('document').ready(function(){
    ko.applyBindings(new page())
})

Now let me define its properties what it does.

Configuration

toggleText , activeText and inActiveText

We can set the value of toggleText to true or false. If we set it active the text will be toggled. If we give parameters in activeText and inActiveText these text will be toggled. And if we do not assign these parameters it will display True  and False keywords. If we set it to false always activeText will be displayed and if we do not assign active text it will always display True.

active

With this we can handle the default behaviour. Setting it true will check it by default and setting it false will display it as unchecked.

activeTextClass , inActiveTextClass , toggleTextColor

activeTextClass and inActiveTextClass are applied to activeText and inActiveText. this is handled with css binding. Toggling will work only when toggleTextColor is set to true.

activeClass, inActiveClass

activeClass and inActiveClass are applied to the anchor we will be using.

activeId

activeId  is the default value you want to give to the item. If you leave it you always have 1 when active and 0 when inactive.

OK. The settings has been defined. Now let’s see the binding.

<ul class="srh_fltr" data-bind="with:IsRead">
    <li>
        <label class="selected_filter" data-bind="text:Label,css:LabelColor">True</label>
        <div class="check_box">
            <a class="active selected" data-bind="css:Class,click:Toggle">
                <img src="http://imgh.us/spacer_4.gif" alt="" />
            </a>
        </div>
    </li>
</ul>

As you can see i am using `with` in ul tag so that i am able to use it as usual binding. label has text and css binding.  And anchor has css and click binding. Now to see it in action view the demo.

Demo

When you need to get the value you can do it easily with self.myproperty().Id() or for text self.myproperty().Label(). One thing to note here is that all the configuration is optional. It will have default values for everything. Here are some useful properties of Filter model which we have assigned in out observable.

  • Label
  • LabelColor (css class for handling label)

  • Class (css class for handling anchor or clickable tag)
  • Toggle (function for toggle between active and inactive)
  • Id (the id of current item we have set)

To get the id and text you can use Id and Label and you will have selected Id and selected text.

The single checkbox is finished here. Now we can move to see how we can use another code snippet as a list.

Radio Alternative List with Knockout

For a list which will work instead of radio boxes we need to understand some points.

  • We need an observableArray property which should have key value pairs.
  • The list is dependent on Filter model i have defined above. Using it means gain all the functionality of Filter model.
  • List have same configuration as Filter model but with some more parameters.

Ok. these were the points to understand. Now lets see the usage.

At first lets see the Filters model not Filter.

function Filters(settings){
    var self            =   this
    self.List           =   ko.observableArray([])
    self.Id             =   ko.observable()
    self.Ids            =   ko.observableArray([])
    self.Description    =   ko.observable()
    self.Descriptions   =   ko.observableArray([])
 
    self.SetActive = function(){
        var result          =   []
        var defaultKey      =   (settings.matchKey) ? settings.matchKey : 'Id'
        var activeText      =   (settings.activeText) ? settings.activeText : 'Value'
        var inactiveText    =   (settings.inactiveText) ? settings.inactiveText : 'Description'
        var activeIds       =   settings.activeIds
        var ids             =   []
        var items = ko.utils.arrayForEach(settings.List,function(item){
            if(in_array(item[defaultKey],activeIds)){
 
                if(!settings.isMultiselect){
                    self.Id(item[defaultKey])
                    self.Description(item[activeText])
                }else{
                    self.Ids.push(item[defaultKey])
                    self.Descriptions().push(item[activeText])
                }
            }
            var active  = in_array(item[defaultKey],activeIds) ? true : false
            var options =   {
                toggleTextColor     :   (settings.toggleTextColor) ? settings.toggleTextColor : false,
                toggleText          :   (settings.toggleText) ? settings.toggleText : false,
                active              :   active,
                activeId            :   item[defaultKey],
                activeClass         :   (settings.activeClass) ? settings.activeClass : 'selected',
                inActiveClass       :   (settings.inActiveClass) ? settings.inActiveClass : '',
                activeText          :   (item[activeText]) ? item[activeText] : 'True',
                inactiveText        :   (item[inactiveText]) ? item[inactiveText] : 'False',
                activeTextClass     :   (settings.activeTextClass) ? settings.activeTextClass : '',
                inActiveTextClass   :   (settings.inActiveTextClass) ? settings.inActiveTextClass : ''
            }
            result.push(new Filter(options))
        })
 
        self.List(result)
    }
 
    self.ConvertToInteger = function(accepted){
        var AcceptedChoices =   []
        ko.utils.arrayForEach(accepted, function(item) {
            AcceptedChoices.push(parseInt(item))
        })
        return  AcceptedChoices
    }
 
    self.ToggleClick    =   function(data){
        if(settings.isMultiselect){
            var selectedItems   =   []
            var selectedDescriptions    =   []
            var items   =   ko.utils.arrayForEach(self.List(), function(item) {
                var index   =   self.List().indexOf(item)
                if(item.Id() == data.Id()){
                    self.List()[index].Toggle()
                }
            })
            var items   =   ko.utils.arrayForEach(self.List(), function(item) {
                var index   =   self.List().indexOf(item)
 
                if(item.Active() == true){
                    selectedItems.push(item.Id())
                    selectedDescriptions.push(item.Label())
                }
            })
            self.Ids(selectedItems)
            self.Descriptions(selectedDescriptions)
        }else{
            var items   =   ko.utils.arrayForEach(self.List(), function(item){
                var index   =   self.List().indexOf(item)
 
                if(item.Active() == true){
                    self.List()[index].Toggle()
                }
 
                if(item.Id() == data.Id()){
                    self.List()[index].Toggle()
                }
 
            })
            self.Id(data.Id())
            self.Description(data.Label())
        }
    }
    /*  Initialization  */
    self.LoadData = function(){
        self.SetActive()
    }
    /*  Initialization End Here */
    self.LoadData()
}

Here is the model we are going to use.

self.MyChoice   =   ko.observable('')
 
self.Choices    =   ko.observable([
    {Id:1,Value:'First Option',Description:'This is first option'},
    {Id:2,Value:'Second Option',Description:'This is second option'},
    {Id:3,Value:'Third Option',Description:'This is third option'},
    {Id:4,Value:'Forth Option',Description:'This is forth option'},
    {Id:5,Value:'Fifth Option',Description:'This is fifth option'},
    {Id:6,Value:'Sixth Option',Description:'This is sixth option'}
])
var options =   {
    isMultiselect       :   false,
    matchKey            :   'Id',
    activeText          :   'Value',
    inactiveText        :   'Description',
    List                :   self.Choices(),
    toggleText          :   true,
    toggleTextColor     :   true,
    activeIds           :   [4],
    activeClass         :   '',
    inActiveClass       :   'un_check',
    activeTextClass     :   'selected_filter',
    inActiveTextClass   :   ''
}
self.MyChoice(new Filters(options))

OK. You can see i have created an observable array called Choices. And MyChoice is an observable property which will have Filters model. You can see i have added some more parameters in configuration. Let me define them.

isMultiSelect

if set to false it will act like a group of radio buttons. Only one is selected at a time. If set it to true the list will now act like multiple checkboxes and many or all of them can be selected.

matchKey , activeText , inactiveText

These will have names of indexes of observable array. Here i have assigned Id in Key from Choices observable array. Value as active text and description as inActiveText. If you select the toggleText to false it will always display Value as activeText.

activeIds

If you want to select an item by default you can assign its value in the form of array in activeId. When the list is generated the id you assigned will be selected.

List

This is the property you need to assign an observable array which will have key and value pairs.

To see it in action lets’ have its demo on fiddle.

Demo

The binding is the previous one except two things. I have used List to generate the list. And i have used ToggleClick instead of Toggle. And to get the value you can use self.myproperty().Id() and to get text you can use self.myproperty().Description().

Checkbox Alternative List with Knockout

For this all we need to do is set isMultiSelect to true and you will be able to select multiple items from the list. For multiple default selections you can give multiple ids in activeIds.  Here is the fiddle demo for this.

Demo

Now to get the selected values you can use self.myproperty().Ids() and to get selected texts you can use self.myproperty().Descriptions().

This way you will now be able to make lists which will work instead of checkboxes and radio buttons. Moreover you can handle them with css classes.