Search code examples
javascriptjqueryknockout.jsbootstrap-4knockout-3.0

Knockout Menu binding switch view and change css


I have a single page application written using knockout/jquery. However, I am struggling to find a better way to handle what view to show. As i need more menu items you can see how the code will be more unmanageable. I would like to be able to show a view based on what is selected and change the CSS so you can see which tab is selected too.

  <div class="col-md-2 sidebar">
        <div class="list-group">
            <a href="#" class="list-group-item list-group-item-action active" data-bind="click: ShowDashboard, css: DashboardSideBarCss">
                Dashboard
            </a>
            <a href="#" class="list-group-item list-group-item-action non-active-sidebar"
               data-bind="click: ShowCompanyDetails, css: CompanyDetailsSideBarCss">
                Company Details
            </a>
            <a href="#" class="list-group-item list-group-item-action non-active-sidebar"
               data-bind="click: ShowEmployees, css: EmployeesSideBarCss">
                Employees
            </a>
            <a href="#" class="list-group-item list-group-item-action non-active-sidebar"
               data-bind="click: ShowEtc, css: EtcCss">
                etc....
            </a>
        </div>

    </div>

Solution

  • use a single class/click for the view change-links and add a new attribute containing a "key" of your view, sth like:

    <a href="#" data-view="dashboard" data-bind="click: changeContent">
    

    in your changeContent function read the attribute and set it to a new observable e.g 'currentView'

    sth. like:

    vm.currentView($(this).attr('data-viewkey'))
    

    (or however you are used to code)

    you can then just show the correct content like:

    <div style="display:none" data-bind="visible:vm.currentView()=='dashboard'" >
    ....
    

    or you can toggle an 'activeclass'

    data-bind="attr:{class:'static_classes '+(vm.currentView()=='dashboard' ? 'active' : 'inactive' )}"
    

    or add individual dynamic selectors

     data-bind="attr:{class:'content_'+vm.currentView()}" 
    

    tl;dr introduce a new observable holding a "viewkey" on which everything is based on and you can do whatever you want