Search code examples
knockout.jsdurandalhottowel

Inject some buttons in my header specific to the current view with durandal


I develop an ASP.NET MVC solution with the Durandal framework.

On the shell page, I have the side bar (which contains my main menu) and also the header bar. This header bar contains button specific to the current view.

So for example, if I display a search view, I need to 'inject' specific button in the header bar like 'Search' or 'Reset' buttons.

Another example, if I display a detail view, I need to 'inject' specific button in the header bar like 'Save' or 'Cancel' buttons.

My question: how to proceed to be able to 'inject' some html elements (buttons) in my header bar specifically for the current view?

Maybe I need to refactor my shell to code my header bar somewhere else?

Below is an extract of my shell page:

<div class="page secondary with-sidebar">
    <div id="header">
         ....
    </div> <!--header-->

    <div class="page-sidebar">
         ....
    </div>
    <div class="page-region">
        <div class="page-region-content">

            <div class="grid">   
                <div class="row">
                        <div class="container-fluid page-host">
                            <!--ko compose: { 
                                model: router.activeItem, //wiring the router
                                afterCompose: router.afterCompose, //wiring the router
                                transition:'fade', //use the 'fade' transition when switching views
                                cacheViews:true //telling composition to keep views in the dom, and reuse them (only a good idea with singleton view models)
                            }--><!--/ko-->
                        </div>
                </div>
            </div> <!--grid-->   
        </div> <!--page-region-content-->
    </div> <!--page-region-->
</div> <!--page secondary-->

Solution

  • Here is one approach you could consider.

    It assumes that each of your modules follows a set of conventions. For example a searchable module will expose a search function and a saveable module will expose a save function.

    Given that, you can build out your header like this to contain the buttons and hide/show them as necessary.

    <div id="header">
    
        <!-- other header content -->
    
        <!-- injected header buttons -->
    
        <!-- will only be shown if the activeItem has a search function -->
        <button data-bind="visible: router.activeItem().search, 
                           click: router.activeItem().search">Search</button>
    
        <!-- will only be shown if the activeItem has a resetfunction -->
        <button data-bind="visible: router.activeItem().reset, 
                           click: router.activeItem().reset">Reset</button>
    
        <!-- will only be shown if the activeItem has a save function -->
        <button data-bind="visible: router.activeItem().save, 
                           click: router.activeItem().save">Save</button>
    
        <!-- will only be shown if the activeItem has a cancel function -->
        <button data-bind="visible: router.activeItem().cancel, 
                           click: router.activeItem().cancel">Cancel</button>
    </div>
    

    If your modules expose any of the functions that you mentioned then the buttons will be shown accordingly.