Is there a way to set the page title by data-binding using Knockout.js?

前端 未结 5 1060
春和景丽
春和景丽 2020-12-11 00:05

I have a viewModel with a Title property. I\'d like to set the page title using that property. Here\'s what I tried already, which didn\'t work:



        
相关标签:
5条回答
  • 2020-12-11 00:37

    You could create a custom binding handler which sets document.title on update, then add the binding to the body element.

    0 讨论(0)
  • 2020-12-11 00:41

    In my eyes, this situations begs for an observable subscription.

    ...
    <title>{FALL BACK TEXT}</title>
    ...
    

    View Model

    ViewModel = function() {
        var self = this;
        self.PageTitle = ko.observable(null);
        self.PageTitle.subscribe(function(newValue){ document.title = self.PageTitle() });
    
        //change PageTitle to see your handy work in action
        self.PageTitle("Hello World!");
    
    };
    

    EDIT: As an amendment to my previous answer, I'd like to put forth the following. Will my previous suggestion work? Yes, it works very nicely. However, DOM manipulation within the view model itself does not "exactly" follow the MVVM paradigm. The actual "best" approach would be to create a custom binding, which sets the document title on update of a particular observable.

    ...
    <title data-bind="htmlDocumentTitle: PageTitle()">{FALLBACK TEXT}</title>
    ...
    

    View Model

    ViewModel = function() {
        var self = this;
        self.PageTitle = ko.observable(null);
    
        self.init = function(){
            self.PageTitle("My page title from an obersvable");
        };
    
        //init the viewmodel
        self.init();
    };
    

    And finally our shiny custom binding to "listen" for changes to the observable (note the use of ONLY the update action)

    ko.bindingHandlers.htmlDocumentTitle = {
        update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
            var fallbackTitle = "My document title";
            var title = ko.unwrap(valueAccessor());
    
            if(!title || title == null && title == "")
                title = fallbackTitle;
    
            document.title = title;
        }
    };
    

    At first glance this solution may appear less scalable, but do keep in mind that we can create "pseudo-inheritance" with Knockout View Models using "call()".

    0 讨论(0)
  • 2020-12-11 00:42

    As per @Douglas's suggestion, my solution was to add a hidden div somewhere in the body bound to a computed value:

    <div data-bind="text: currentPageTitle()"></div>
    

    Then, in the value computation, I set the document.title:

    self.currentPageTitle = ko.computed(function() {
        document.title = self.Title();
        return self.Title();
    }, this);
    

    This works perfectly for me

    0 讨论(0)
  • 2020-12-11 00:53

    Try giving your html element an id

    <html id="htmlTop" xmlns="http://www.w3.org/1999/xhtml">
    

    and applying your viewModel to it

    ko.applyBindings(viewModel, document.getElementById("htmlTop"));
    

    EDIT

    This works for me; I just ran this page and the title said "Hello". Double check your code for typos.

    <html id="htmlTop">
    
        <head>
          <title data-bind="text: title"></title>
    
          <script type='text/javascript' src='jquery.min.js'></script>
          <script type='text/javascript' src='knockout-1.2.1.js'></script>
    
          <script type="text/javascript">
    
              $(function () {
                  var viewModel = { title: "Hello" };
                  ko.applyBindings(viewModel, document.getElementById("htmlTop"));
              });
    
          </script>
    
        </head>
    
        <body>
        </body>
    </html>
    

    Screenshot:

    enter image description here

    0 讨论(0)
  • 2020-12-11 00:56

    You can use knockout subscribe:

    function viewModel() {
      var self = this;
    
      self.title = ko.observable(null);
      self.title.subscribe(function(newTitle) {
          document.title = newTitle;
      })  
    }
    
    var vm = new viewModel();
    ko.applyBindings(vm);
    
    vm.title('Hello page');
    
    0 讨论(0)
提交回复
热议问题