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?


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.


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/


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

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'
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.