Obtendo “Não é possível ler a propriedade 'nodeType' de null” ao chamar ko.applyBindings


99

Eu tenho este código nocaute:

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>

O exemplo é o mesmo encontrado no site Knockout, mas quando eu o executo, ele retorna esta mensagem no Chrome Fire Bug:

TypeError não capturado: não é possível ler a propriedade 'nodeType' de nulo

Este está relacionado ao arquivo knockout e a esta linha do meu script:

ko.applyBindings(new TaskListViewModel());

E este erro está apontando para esta linha (1766) no nocaute:

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

O que estou fazendo de errado?


Esse erro de digitação causaria esse SyntaxError. Corrigir o erro de digitação corrige o problema?
James Allardice

Sim ... Eu atualizei a pergunta porque outro erro ocorreu.
Gerep

Respostas:


176

Este problema estava acontecendo porque eu estava tentando vincular um HTMLelemento antes de ser criado.

Meu script foi carregado na parte superior HTML(no cabeçalho), mas precisava ser carregado na parte inferior do meu HTMLcódigo (antes da tag de fechamento do corpo).

Obrigado pela sua atenção James Allardice .

Uma possível solução é usar defer="defer"

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

Use isso se o script não for gerar nenhum conteúdo de documento. Isso dirá ao navegador que ele pode esperar o conteúdo ser carregado antes de carregar o script.

Leitura adicional .

Espero que ajude.


4
Para enfatizar: a <script ...>tag precisa estar na parte inferior da página, logo antes da </body>tag de fechamento .
aliteralmind de

1
maravilhoso obrigado! Acabei de mover meu script para o final do corpo e funcionou perfeitamente. muitas gratidões
Eleanor Zimmermann

33

Você pode querer considerar o uso do manipulador pronto jquery para isso

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

Então você consegue duas coisas:

  1. Evite poluir o namespace global
  2. A ligação Knockout ocorre APÓS a criação do DOM. Você pode colocar seu javascript onde quer que seja adequado para a organização.

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


1
Alerta de spoiler para quem não fez RTM: $(handler)é equivalente a$(document).ready(handler)
Brock Hensley

21

se você tiver jQuery, coloque apply binding dentro de onloadmodo que o knockout procure pelo DOM quando o DOM estiver pronto.

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

acertou em cheio, btw posso incluir outras ligações no bloco de documentos?
Allan Jikamu

1
Obrigado pela sua informação!!
karthik

5

Você cometeu um erro de grafia simples:

self.addTask = fuction() {

Deveria estar:

self.addTask = function() { //Notice the added 'n' in 'function'
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.