CoffeeScript, нокаут и наблюдаемый

У меня есть следующий CoffeeScript для создания Javascript для Knockoutjs

class NewsItem
    content: ko.observable("")
    title: ko.observable("")

    constructor: (data,dispForm) ->
        @content data.get_item("content")
        @title data.get_item("title")
        @id = data.get_id()

class NewsItemViewModel
    collection: ko.observableArray()

    loadAll: =>
            listEnumerator = items.getEnumerator()          
            while listEnumerator.moveNext()
                 currentItem = listEnumerator.get_current()
                 @collection.push new NewsItem currentItem, @list.get_defaultDisplayFormUrl()
            return

$ -> 
    viewModel = new NewsItemViewModel
    ko.applyBindings viewModel
    return

Для отображения HTML я использую этот код

<ul id="results" data-bind="template: {name: 'item_template', foreach: collection}">
</ul>
<script id="item_template" type="text/x-jquery-tmpl"> 
<li>
    <h3><a href="/" data-bind="text: title"></a></h3>
    <p>
        <textarea data-bind="value: content"></textarea>
        <input type="button" value="save" data-bind="enable: content().length > 0">
    </p>
</li>   
</script>

Однако в HTML все элементы отображают значения последнего NewsItem, добавленного в коллекцию.

Любые подсказки?

Ответ 1

Хорошо, это может быть одна из проблем, с которыми сталкивается CoffeeScript:

class NewsItem
    content: ko.observable("")

Здесь вы создаете новый класс со свойством "content", которое является наблюдаемым объектом. Это компилируется в следующий JavaScript:

var NewsItem = (function() {
    function NewsItem() {}
    NewsItem.prototype.content = ko.observable("");
    return NewsItem;
})();

Как вы теперь видите, свойство "контент" прикрепляется к прототипу. Это означает: есть только одно наблюдаемое, созданное, а не одно для каждого экземпляра. Поэтому всякий раз, когда вы выполняете new NewsItem, конструктор обновляет эту единицу, наблюдаемую в прототипе, следовательно, одно и то же значение для всех экземпляров.

Чтобы решить эту проблему, просто создайте наблюдаемое в конструкторе. Таким образом, он привязывается к экземпляру, а не прототипу:

class NewsItem
    constructor: (data,dispForm) ->
        @content = ko.observable data.get_item("content")

Скомпилируется в (соответствующая часть):

this.content = ko.observable(data.get_item("content"));