Obtention de «Impossible de lire la propriété 'nodeType' de null» lors de l'appel de ko.applyBindings

99

J'ai ce code knock-out:

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

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

L'exemple est le même que celui trouvé sur le site Web de Knockout, mais lorsque je l'exécute, il renvoie ce message sur Chrome Fire Bug:

Uncaught TypeError: impossible de lire la propriété 'nodeType' de null

Celui-ci est lié au fichier knockout et à cette ligne de mon script:

ko.applyBindings(new TaskListViewModel());

Et cette erreur pointe vers cette ligne (1766) sur KO:

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

Qu'est-ce que je fais mal?

Gerep
la source
Cette faute de frappe provoquerait cette SyntaxError. La correction de la faute de frappe résout-elle le problème?
James Allardice
Oui ... J'ai mis à jour la question car une autre erreur est survenue.
Gerep

Réponses:

176

Ce problème se produisait parce que j'essayais de lier un HTMLélément avant sa création.

Mon script était chargé au-dessus de HTML(dans la tête) mais il devait être chargé en bas de mon HTMLcode (juste avant la balise body de fermeture).

Merci pour votre attention James Allardice .

Une solution de contournement possible consiste à utiliser defer="defer"

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

Utilisez cette option si le script ne génère aucun contenu de document. Cela indiquera au navigateur qu'il peut attendre que le contenu soit chargé avant de charger le script.

Lectures complémentaires .

J'espère que ça aide.

Gerep
la source
4
Pour souligner: la <script ...>balise doit être au bas de la page, juste avant la </body>balise de fermeture .
aliteralmind le
1
merveilleux, merci! Je viens de déplacer mon script à la fin du corps et cela a parfaitement fonctionné. many gratitudes
Eleanor Zimmermann
33

Vous voudrez peut-être envisager d'utiliser le gestionnaire prêt jquery pour cela

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

Ensuite, vous réalisez deux choses:

  1. Évitez de polluer l'espace de noms global
  2. La liaison Knockout se produit APRÈS la création du DOM. Vous pouvez placer votre javascript partout où il convient à l'organisation.

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

James Kessler
la source
1
Alerte spoiler pour ceux qui n'ont pas RTM: $(handler)équivaut à$(document).ready(handler)
Brock Hensley
21

si vous avez jQuery, mettez apply binding à l'intérieur de onloadsorte que knockout recherche le DOM lorsque le DOM est prêt.

$(document).ready(function(){
    ko.applyBindings(new TaskListViewModel());
});
Jhankar Mahbub
la source
cloué, btw puis-je inclure d'autres liaisons sur le bloc de document?
Allan Jikamu
1
Merci pour votre information!!
karthik
5

Vous avez une faute d'orthographe simple:

self.addTask = fuction() {

Devrait être:

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