Otrzymanie „Nie można odczytać właściwości 'nodeType' o wartości null” podczas wywoływania ko.applyBindings

99

Mam ten kod wybicia:

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

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

Przykład jest taki sam, jak ten znaleziony na stronie Knockout, ale kiedy go uruchomię, zwraca ten komunikat o błędzie Chrome Fire:

Uncaught TypeError: Nie można odczytać właściwości „nodeType” o wartości null

Ten jest powiązany z plikiem knockout i tym wierszem mojego skryptu:

ko.applyBindings(new TaskListViewModel());

A ten błąd wskazuje na tę linię (1766) przy nokautach:

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

Co ja robię źle?

Gerep
źródło
Ta literówka spowodowałaby, że SyntaxError. Czy naprawienie literówki rozwiązuje problem?
James Allardice,
Tak ... Zaktualizowałem pytanie, ponieważ pojawił się inny błąd.
Gerep,

Odpowiedzi:

176

Ten problem występował, ponieważ próbowałem powiązać HTMLelement przed jego utworzeniem.

Mój skrypt został załadowany na górze HTML(w nagłówku), ale musiał zostać załadowany na dole mojego HTMLkodu (tuż przed zamykającym tagiem body).

Dziękuję za uwagę James Allardice .

Możliwe obejście polega na użyciu defer="defer"

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

Użyj tego, jeśli skrypt nie ma generować treści dokumentu. Poinformuje to przeglądarkę, że może czekać na załadowanie zawartości przed załadowaniem skryptu.

Dalsza lektura .

Mam nadzieję, że to pomoże.

Gerep
źródło
4
Aby podkreślić: <script ...>tag musi znajdować się na dole strony, tuż przed zamykającym </body>tagiem.
aliteralmind
1
wspaniale, dzięki! Po prostu przeniosłem scenariusz na koniec ciała i zadziałał idealnie. wiele podziękowań
Eleanor Zimmermann
33

Możesz rozważyć użycie do tego celu obsługi gotowej do obsługi jquery

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

Osiągasz wtedy dwie rzeczy:

  1. Unikaj zanieczyszczania globalnej przestrzeni nazw
  2. Wiązanie typu knockout następuje PO utworzeniu DOM. Możesz umieścić swój javascript wszędzie tam, gdzie jest odpowiedni dla organizacji.

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

James Kessler
źródło
1
Alert spoilera dla tych, którzy nie korzystali z RTM: $(handler)jest odpowiednikiem$(document).ready(handler)
Brock Hensley
21

jeśli masz jQuery, umieść zastosuj bindowanie w środku onload, aby nokaut szukał DOM, gdy DOM jest gotowy.

$(document).ready(function(){
    ko.applyBindings(new TaskListViewModel());
});
Jhankar Mahbub
źródło
przybity, przy okazji czy mogę dołączyć inne wiązania do bloku dokumentu?
Allan Jikamu
1
Dzięki za informacje!!
karthik
5

Masz prosty błąd w pisowni:

self.addTask = fuction() {

Powinien być:

self.addTask = function() { //Notice the added 'n' in 'function'
James Allardice
źródło