1

我有以下视图模型:

var ViewModel = function(setData, dummyCard) {
    var self = this;
    ko.mapping.fromJS(setData, {}, self);

    self.cardCount = ko.computed(function() {
        //debugger;
        return self.cards().length;
    });

    self.editing = ko.observable(false);

    self.edit = function () {
        debugger;
        self.editing(true);
    };

};

此 viewModel 用于显示属于 Set 的卡片列表。我试图允许用户通过以下方式编辑这些卡片的面(同时双面):

<!-- ko foreach: cards -->
      <!-- ko foreach: sides -->
         <div data-bind="visible: !$root.editing()" class="span5 side-study-box">
             <p data-bind="text: content">SIDE 1</p>
         </div>
      <!-- /ko -->
<!-- /ko -->

我在这里的示例中添加了编辑功能(参见 Bert Bertington 的 hasFocus 示例):http ://knockoutjs.com/documentation/hasfocus-binding.html

这并不完全有效,因为 Edit 属性附加到 $root (Set) 对象,而不是 $parent (Card) 对象。我认为完成这项工作的方法涉及“创建”方法,如下所示:向使用 Knockout JS 映射插件创建的视图模型添加属性

将这些属性带到一方的父级需要什么语法?

编辑:到目前为止,我有:

var ViewModel = function(setData, dummyCard) {
    var self = this;

    var cardModel = function(data) {
        debugger;
        ko.mapping.fromJS(data, {}, this);

        this.editing = ko.observable(false);

        this.editing = function() {
            debugger;
            this.editing(true);
        };
    };

    var mapping = {
        'cards': {
            create: function(options) {
                return new cardModel(options.data);
            }
        }
    };

self.cardCount = ko.computed(function() {
        //debugger;
        return self.cards().length;
    });

不过,它并不能完全与 js 的其余部分一起使用 - 现在“cards()”是未定义的。现在深入研究它,但如果有人有任何提示,我会全神贯注!

4

1 回答 1

0

尽管您已经在此模型中定义了“cardModel”并调用了 KO 映射,但在应用 KO 绑定时,函数体(即模型定义)默认不会被执行。此外,您的代码将“cards”映射到“cardModel”,因此,“cards”数组在根模型视图中不可用。这些都是您看到未定义卡的原因。

我还注意到“编辑”属性的问题。似乎您有一个可观察的和一个具有相同名称“编辑”的函数,这将导致无休止的递归。

根据您给出的描述,我假设您正在尝试映射一个包含卡片元素的 JSON 数组,并定义了一种完成您想要完成的操作的方法。该代码在这个小提琴中可用。

为了方便读者,下面提到了小提琴中的代码

JavaScript

var cardsJSON = {
    "cards" : [{
        "cardName" : "Card1",
        "sides" : ["Side1", "Side2"]
    }, {
        "cardName" : "Card2",
        "sides" : ["Side1", "Side2"]
    }, {
        "cardName" : "Card3",
        "sides" : ["Side1", "Side2"]
    }]
};

function ViewModel() {
    var self = this;

    var testFcn = function() {
        alert("In Function");
    };

    self.cards = ko.observableArray([]);
    self.cardCount = ko.computed(function() {
        return self.cards().length;
    });
};

function Card() {
    var self = this;
    self.editing = ko.observable(false);

    self.edit = function() {
        self.editing(true);
    };

    self.doneEdit = function() {
        self.editing(false);
    };
};

function createCard(data) {
    var card = new Card();
    ko.mapping.fromJS(data, {}, card);

    return card;
};

var viewModel = new ViewModel();
function init() {
    var mapping = {
        "cards" : {
            create : function(options) {
                return createCard(options.data);
            }
        }
    };

    ko.mapping.fromJS(cardsJSON, mapping, viewModel);
};

init();
ko.applyBindings(viewModel);

HTML

<table border="1">
    <thead>
        <tr>
            <th>Card</th>
            <th colspan="2">Sides</th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        <!-- ko foreach: cards -->
        <tr>
            <td data-bind="text: cardName"></td>
            <!-- ko foreach: sides -->
            <td>
                <span  data-bind="text: $data, visible: !$parent.editing(), click: $parent.edit"></span>
                <input data-bind="value: $data, visible:$parent.editing"></input>
            </td>
            <!-- /ko -->
            <td><input value="Done" type="button" data-bind="click: doneEdit"></input></td>
        </tr>
        <!-- /ko -->
    </tbody>
</table>

代码可能比它应该的要复杂一些,但目的是为了更好地解释。

如您所见,有一个单独的视图模型来表示卡片,它包含自己的属性,例如“编辑”、“编辑”等。当我们通过映射插件映射 JSON 时,我们会覆盖卡片的创建方式。我们基本上要做的是创建一个 Card 视图模型并应用映射,以便它包含预定义的属性以及 JSON 中的属性。

这必须明确地完成(根据我的理解)。完成映射后,根视图模型包含一个可观察的卡片数组,每个卡片实例都包含自己的“编辑”函数和“编辑”属性,您可以在数据绑定中使用它们。

希望这可以帮助。

于 2013-03-26T04:36:48.780 回答