2011-12-27 26 views
22

Tengo un modelo de vista con una propiedad Title. Me gustaría establecer el título de la página usando esa propiedad. Esto es lo que ya intentado, pero no funcionó:¿Hay alguna forma de establecer el título de la página mediante enlace de datos utilizando Knockout.js?

<html> 
    <head> 
    <title data-bind="text: Title"></title> 
</head> 
<body> 
    <span data-bind="text: Title"/> <!-- this displays the title properly --> 
</body> 

El título del navegador está en blanco/predeterminado en lugar del valor de mi propiedad Title.

+0

yo no quiero seguir editando mi respuesta - cualquier posibilidad de poner esto en sus obras de etiquetas HTML? '' –

+0

Además, ¿puede vincular la propiedad Title en su ViewModel a algo más mundano, como un tramo, y que se muestre bien? –

+0

Actualicé mi código un poco. Sí, puedo vincular datos del 'Título' en otros lugares con éxito. Es solo el título de la página que no funciona. –

Respuesta

19

tratar de darle a su elemento html un id

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

y aplicando el modelo de vista de que

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

EDITAR

Esto funciona para mí; Acabo de ejecutar esta página y el título decía "Hola". Revisa tu código para detectar errores tipográficos.

<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> 

Captura de pantalla:

enter image description here

+0

Acabo de intentarlo, pero sin cambios. –

+0

@Byron - lo siento - Tengo una última idea, entonces creo que el depósito estará seco :) --- ver la edición –

+0

@ByronSommardahl ¿Qué hay de pasar el elemento HTML, en lugar de sólo el documento? Algo como 'document.getElementsByTagName (" html ")'. –

3

Se puede crear un custom binding handler que establece document.title en la actualización, a continuación, añadir la unión al elemento body.

+0

¿Alguna posibilidad de que haya visto este trabajo o pueda publicar un ejemplo? –

+0

Eche un vistazo al último ejemplo en la página que he vinculado anteriormente, el hasFocus uno. Sería muy parecido, excepto que no necesitaría el 'init', y' update' establecería 'document.title' en' ko.utils.unwrapObservable (value) 'en lugar de usarlo en el' if 'bloque. – Douglas

0

Según @ sugerencia de Douglas, mi solución fue añadir un oculto div alguna parte del cuerpo unido a un valor calculado:

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

Luego, en el cálculo de valor, me puse la document.title:

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

Esto funciona perfectamente para mí

2

En mis ojos, esta situación plantea para una suscripción observable.

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

Ver Modelo

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:

como una enmienda a mi respuesta anterior, me gustaría poner adelante lo siguiente. ¿Funcionará mi sugerencia anterior? Sí, funciona muy bien. Sin embargo, la manipulación DOM dentro del modelo de vista en sí no sigue "exactamente" el paradigma MVVM. El mejor "enfoque" real sería crear un enlace personalizado, que establece el título del documento en la actualización de un observable particular.

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

Ver Modelo

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(); 
}; 

Y, por último nuestra unión a "escuchar" para los cambios a lo observable (nótese el uso de sólo la acción de actualización)

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; 
    } 
}; 

En primer encargo brillantes vistazo a esta solución puede parecer menos escalable, pero tenga en cuenta que podemos crear "pseudo-herencia" con Modelos de Vista Eliminada usando "call()".

+2

¡Funcionó para mí! Esta es una forma particularmente práctica de hacerlo cuando no desea contaminar el encabezado de su página con el marcado KO que solo se usará dinámicamente en algunos casos específicos. –

1

Puede utilizar nocaut suscribirse:

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'); 
Cuestiones relacionadas