locked
Boostrap Tabs with knockout RRS feed

  • Question

  • User1308732545 posted

    Hi All,

    I have a page with 2 boostrap tabs , the tab name  comes from the model  and the markup looks like this

    <div>
            @{
                <ul class="nav nav-tabs" role="tablist">
                    @foreach (var tab in Model.Tabs)
                    {                   
                       <li role="presentation">
                        <a data-toggle="tab"  role="tab" data-src="">@tab.Name</a>
                       </li>                   
                    }
                </ul>
            }
        </div>
        <div class="tab-content">
                  <div role="tabpanel" class="tab-pane active">           
                        @Html.Partial("Tab1");
                    </div>                
               
                    <div role="tabpanel" class="tab-pane">
                        @Html.Partial(Tab2);
                    </div>            
            </div>  

    on click of each tab a partial view should be displayed , and I have to do this in Knockout js

    I am very new to knockout , so could anyone please help me do this

    Thanks

    Tuesday, September 20, 2016 3:02 PM

Answers

  • User1881638666 posted

    Hi,

    I have added very simple sample here. 

    This can be done in various way. Hence, i have just sketched a sample for you to go ahead.

    1. Create new mvc5 web project.

    2. Add the KnokocutJs to the project.

    3. Add model classes required.

    namespace TestWebApp.Models
    {
        public class Tab
        {
            public string Name;
            public bool IsActive { get; set; }
        }
    
        public class AnotherModel
       {
           public IEnumerable<Tab> Tabs { get; set; }
            
           // some other properties.
       }
    }
    

    One model for represents tab info while other one is to wrap the data for index view.

    4. Create mvc controller.

    using System;
    using System.Collections.Generic;
    using System.Web.Mvc;
    using TestWebApp.Models;
    
    namespace TestWebApp.Controllers
    {
        public class TabController : Controller
        {
            // GET: Tab
            public ActionResult Index()
            {
                var tabs = new List<Tab>
                {
                    new Tab { Name = "Tab1", IsActive = true },
                    new Tab {Name = "Tab2" },
                    new Tab {Name = "Tab3" }
                };
    
                var model = new AnotherModel
                {
                    Tabs = tabs
                };
    
                return View(model);
            }
    
            public ActionResult GetTabContent(string tabName)
            {
                var partialViewName = 
                    String.Format("_Partial{0}", tabName);
    
                return PartialView(partialViewName);
            }
        }
    }

    This simply have index view to display tabs. And another action method to send the partial view of the given tab when requested.

    The second one is used to get the updated tab content.

    5. Create index view.

    @model TestWebApp.Models.AnotherModel
    
    @{
        ViewBag.Title = "Index";
    }
    
    <h2>Index</h2>
    
    <div class="container">
        <div class="row">
            <div class="col-md-12">
                <h4>Tab Update Demo</h4>
            </div>
        </div>
        
        <div class="row">
            <div class="col-md-12">
                @{
                    <ul class="nav nav-tabs" role="tablist">
                        @foreach (var tab in Model.Tabs)
                        {
                            var liActiveCss = tab.IsActive ? "active" : "";
                            <li class="@liActiveCss" role="presentation" data-bind="click: function() { UpdateTabContent('@tab.Name'); }">
                                <a data-toggle="tab" role="tab" data-src="" href="#@tab.Name">@tab.Name</a>
                            </li>
                        }
                    </ul>
    
                    <div class="tab-content">
                        @foreach (var tab in Model.Tabs)
                        {
                            var tabPaneActiveCss = tab.IsActive ? "active" : "";
                            <div id="@tab.Name" role="tabpanel" class="tab-pane @tabPaneActiveCss">
                                @Html.Partial(String.Format("_Partial{0}", @tab.Name))
                            </div>
                        }
                    </div>
                }
            </div>
        </div>
    </div>
    
    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script src="~/Scripts/knockout-3.4.0.js"></script>
    <script src="~/Scripts/Tab/TabUpdaterViewModel.js"></script>
    <script src="~/Scripts/Tab/tab-ui.js"></script>

    6. Add new js file for tabs updater view model.

       Creating a view model class to update the tabs.

    // TabsUpdaterViewModel.js file
    
    var TabsUpdaterViewModel = function() {
    
        var self = this;
    
        self.UpdateTabContent = function (tabName) {
    
            var getUrl = "/Tab/GetTabContent?tabName=" + tabName;
            return $.ajax({
                cache: false,
                url: getUrl,
                type: 'GET'
            }).done(function (tabContent) {
                $('#' + tabName).html(tabContent);
            });
        };
        
    };

    7. Add the new js file for the web app or to the view.

    // tab-ui.js file
    
    $(function () {
        // create the new instance of view model.
        var tabsUpdaterViewModel = new TabsUpdaterViewModel();
        // init and apply the knockout bindings to the view / ui.
        ko.applyBindings(tabsUpdaterViewModel);
    })

    This creates a new instance of the view model and init and apply the knckout binding the ui elements in the view.

    The 'data-bind' attribute in the view is used for binding the ui elements.

    8. Incude / add the js scrips files required to the view.

    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script src="~/Scripts/knockout-3.4.0.js"></script>
    <script src="~/Scripts/Tab/TabUpdaterViewModel.js"></script>
    <script src="~/Scripts/Tab/tab-ui.js"></script>

    Ideally we should create new script bundle and add the whole bundle to the view.

    But, i have intentionally added files one by one to understand the flow easily. 

    9. Run the app. and test.

    This can be done in various way.  Therefore i would recommend you to go through the standard tutorial in the asp.net official web site and KnockoutJs official web site.

    http://www.asp.net/mvc

    http://knockoutjs.com/

    http://learn.knockoutjs.com/

    http://knockoutjs.com/documentation/introduction.html

    http://knockoutjs.com/documentation/click-binding.html

    Hope this will help you.

    Thanks & Regards,

    Wenushka

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, September 24, 2016 1:28 PM

All replies

  • User2117486576 posted

    I am not at a location where I can test this but as I recall the anchor tag in the tab needs an href value equal to the id of the panel it opens.

    Check this out.

     @{
                <ul class="nav nav-tabs" role="tablist">
                    @foreach (var tab in Model.Tabs)
                    {  //assuming the Name can be a valid html id
                        <li role="presentation">
                            <a href=@("#" + tab.Name) data-toggle="tab" role="tab" data-src="">@tab.Name</a>
                        </li>
                    }
                </ul>
            }
        </div>
        <div class="tab-content">
            <!--the id value must match the tab.Name in the Model-->
            <div id="Tab1" role="tabpanel" class="tab-pane active">
                @Html.Partial("Tab1")
            </div>
    
            <div id="Tab2" role="tabpanel" class="tab-pane">
                @Html.Partial("Tab2")
            </div>
        </div>

    I also fixed some syntax errors where you call the Html.Partial() helper.

    Tuesday, September 20, 2016 6:38 PM
  • User1308732545 posted

    Hi Richard, 

    Thanks for your reply ,

    However it would be really helpful if you can let me know as I have asked in the post how can I write  onclick event  and show the tabs in knockout js .

    Wednesday, September 21, 2016 9:14 AM
  • User1881638666 posted

    Hi,

    I have added very simple sample here. 

    This can be done in various way. Hence, i have just sketched a sample for you to go ahead.

    1. Create new mvc5 web project.

    2. Add the KnokocutJs to the project.

    3. Add model classes required.

    namespace TestWebApp.Models
    {
        public class Tab
        {
            public string Name;
            public bool IsActive { get; set; }
        }
    
        public class AnotherModel
       {
           public IEnumerable<Tab> Tabs { get; set; }
            
           // some other properties.
       }
    }
    

    One model for represents tab info while other one is to wrap the data for index view.

    4. Create mvc controller.

    using System;
    using System.Collections.Generic;
    using System.Web.Mvc;
    using TestWebApp.Models;
    
    namespace TestWebApp.Controllers
    {
        public class TabController : Controller
        {
            // GET: Tab
            public ActionResult Index()
            {
                var tabs = new List<Tab>
                {
                    new Tab { Name = "Tab1", IsActive = true },
                    new Tab {Name = "Tab2" },
                    new Tab {Name = "Tab3" }
                };
    
                var model = new AnotherModel
                {
                    Tabs = tabs
                };
    
                return View(model);
            }
    
            public ActionResult GetTabContent(string tabName)
            {
                var partialViewName = 
                    String.Format("_Partial{0}", tabName);
    
                return PartialView(partialViewName);
            }
        }
    }

    This simply have index view to display tabs. And another action method to send the partial view of the given tab when requested.

    The second one is used to get the updated tab content.

    5. Create index view.

    @model TestWebApp.Models.AnotherModel
    
    @{
        ViewBag.Title = "Index";
    }
    
    <h2>Index</h2>
    
    <div class="container">
        <div class="row">
            <div class="col-md-12">
                <h4>Tab Update Demo</h4>
            </div>
        </div>
        
        <div class="row">
            <div class="col-md-12">
                @{
                    <ul class="nav nav-tabs" role="tablist">
                        @foreach (var tab in Model.Tabs)
                        {
                            var liActiveCss = tab.IsActive ? "active" : "";
                            <li class="@liActiveCss" role="presentation" data-bind="click: function() { UpdateTabContent('@tab.Name'); }">
                                <a data-toggle="tab" role="tab" data-src="" href="#@tab.Name">@tab.Name</a>
                            </li>
                        }
                    </ul>
    
                    <div class="tab-content">
                        @foreach (var tab in Model.Tabs)
                        {
                            var tabPaneActiveCss = tab.IsActive ? "active" : "";
                            <div id="@tab.Name" role="tabpanel" class="tab-pane @tabPaneActiveCss">
                                @Html.Partial(String.Format("_Partial{0}", @tab.Name))
                            </div>
                        }
                    </div>
                }
            </div>
        </div>
    </div>
    
    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script src="~/Scripts/knockout-3.4.0.js"></script>
    <script src="~/Scripts/Tab/TabUpdaterViewModel.js"></script>
    <script src="~/Scripts/Tab/tab-ui.js"></script>

    6. Add new js file for tabs updater view model.

       Creating a view model class to update the tabs.

    // TabsUpdaterViewModel.js file
    
    var TabsUpdaterViewModel = function() {
    
        var self = this;
    
        self.UpdateTabContent = function (tabName) {
    
            var getUrl = "/Tab/GetTabContent?tabName=" + tabName;
            return $.ajax({
                cache: false,
                url: getUrl,
                type: 'GET'
            }).done(function (tabContent) {
                $('#' + tabName).html(tabContent);
            });
        };
        
    };

    7. Add the new js file for the web app or to the view.

    // tab-ui.js file
    
    $(function () {
        // create the new instance of view model.
        var tabsUpdaterViewModel = new TabsUpdaterViewModel();
        // init and apply the knockout bindings to the view / ui.
        ko.applyBindings(tabsUpdaterViewModel);
    })

    This creates a new instance of the view model and init and apply the knckout binding the ui elements in the view.

    The 'data-bind' attribute in the view is used for binding the ui elements.

    8. Incude / add the js scrips files required to the view.

    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script src="~/Scripts/knockout-3.4.0.js"></script>
    <script src="~/Scripts/Tab/TabUpdaterViewModel.js"></script>
    <script src="~/Scripts/Tab/tab-ui.js"></script>

    Ideally we should create new script bundle and add the whole bundle to the view.

    But, i have intentionally added files one by one to understand the flow easily. 

    9. Run the app. and test.

    This can be done in various way.  Therefore i would recommend you to go through the standard tutorial in the asp.net official web site and KnockoutJs official web site.

    http://www.asp.net/mvc

    http://knockoutjs.com/

    http://learn.knockoutjs.com/

    http://knockoutjs.com/documentation/introduction.html

    http://knockoutjs.com/documentation/click-binding.html

    Hope this will help you.

    Thanks & Regards,

    Wenushka

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, September 24, 2016 1:28 PM