Obteniendo "No se puede leer la propiedad 'nodeType' de nulo" al llamar a ko.applyBindings

99

Tengo este código de eliminación:

function Task(data) {
    this.title = ko.observable(data.title);
    this.isDone = ko.observable(data.isDone);
}

function TaskListViewModel() {
    // Data
    var self = this;
    self.tasks = ko.observableArray([]);
    self.newTaskText = ko.observable();
    self.incompleteTasks = ko.computed(function() {
        return ko.utils.arrayFilter(self.tasks(), function(task) { return !task.isDone() });
    });

    // Operations
    self.addTask = function() {
        self.tasks.push(new Task({ title: this.newTaskText() }));
        self.newTaskText("");
    };
    self.removeTask = function(task) { self.tasks.remove(task) };
}

ko.applyBindings(new TaskListViewModel());

Este html:

<head>
    <script type="text/javascript" src="jquery-1.7.1.min.js"></script>
    <script type="text/javascript" src="knockout-2.0.0.js"></script>
    <script type="text/javascript" src="script.js"></script>
</head>
<body>
    <h3>Tasks</h3>

    <form data-bind="submit: addTask">
        Add task: <input data-bind="value: newTaskText" placeholder="What needs to be done?" />
        <button type="submit">Add</button>
    </form>

    <ul data-bind="foreach: tasks, visible: tasks().length > 0">
        <li>
            <input type="checkbox" data-bind="checked: isDone" />
            <input data-bind="value: title, disable: isDone" />
            <a href="#" data-bind="click: $parent.removeTask">Delete</a>
        </li> 
    </ul>

    You have <b data-bind="text: incompleteTasks().length">&nbsp;</b> incomplete task(s)
    <span data-bind="visible: incompleteTasks().length == 0"> - it's beer time!</span>
</body>

El ejemplo es el mismo que el que se encuentra en el sitio web de Knockout, pero cuando lo ejecuto, devuelve este mensaje en Chrome Fire Bug:

Uncaught TypeError: no se puede leer la propiedad 'nodeType' de nulo

Este está relacionado con el archivo knockout y con esta línea de mi script:

ko.applyBindings(new TaskListViewModel());

Y este error apunta a esta línea (1766) en el nocaut:

var isElement = (nodeVerified.nodeType == 1);

¿Qué estoy haciendo mal?

Gerep
fuente
Ese error tipográfico causaría que SyntaxError. ¿Solucionar el error tipográfico soluciona el problema?
James Allardice
Sí ... He actualizado la pregunta porque vino otro error.
Gerep

Respuestas:

176

Este problema estaba sucediendo porque estaba tratando de vincular un HTMLelemento antes de que se creara.

Mi secuencia de comandos se cargó en la parte superior HTML(en la cabecera), pero necesitaba cargarse en la parte inferior de mi HTMLcódigo (justo antes de la etiqueta de cierre del cuerpo).

Gracias por tu atención James Allardice .

Una posible solución alternativa es utilizar defer="defer"

<script src="script.js" type="text/javascript" defer="defer"></script>

Use esto si el script no va a generar ningún contenido de documento. Esto le dirá al navegador que puede esperar a que se cargue el contenido antes de cargar el script.

Leer más .

Espero eso ayude.

Gerep
fuente
4
Para enfatizar: la <script ...>etiqueta debe estar en la parte inferior de la página, justo antes de la </body>etiqueta de cierre .
aliteralmind
1
maravilloso, gracias! Simplemente moví mi guión al final del cuerpo y funcionó perfectamente. muchas gratitudes
Eleanor Zimmermann
33

Es posible que desee considerar el uso del controlador jquery ready para esto

$(function() {
   function TaskListViewModel() {
   ...
   ko.applyBindings(new TaskListViewModel());
});

Entonces logras dos cosas:

  1. Evite contaminar el espacio de nombres global
  2. La unión por nocaut ocurre DESPUÉS de que se crea el DOM. Puede colocar su javascript donde sea adecuado para la organización.

Ver http://api.jquery.com/ready/

James Kessler
fuente
1
Alerta de spoiler para aquellos que no hicieron RTM: $(handler)es equivalente a$(document).ready(handler)
Brock Hensley
21

si tiene jQuery, aplique el enlace dentro onloadpara que el knockout busque el DOM cuando DOM esté listo.

$(document).ready(function(){
    ko.applyBindings(new TaskListViewModel());
});
Jhankar Mahbub
fuente
clavado, por cierto, ¿puedo incluir otras encuadernaciones en el bloque de documentos?
Allan Jikamu
1
¡Gracias por tu información!
karthik
5

Tiene un simple error de ortografía:

self.addTask = fuction() {

Debiera ser:

self.addTask = function() { //Notice the added 'n' in 'function'
James Allardice
fuente