【问题标题】:Adding a property to a child object in a viewModel generated by knockout mapping plugin将属性添加到由敲除映射插件生成的 viewModel 中的子对象
【发布时间】:2013-03-26 12:36:48
【问题描述】:

我有以下视图模型:

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

};

此视图模型用于显示属于某个集合的卡片列表。我正在尝试允许用户通过以下方式编辑这些卡片的面(同时双面):

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

这并不完全有效,因为编辑属性附加到 $root (Set) 对象,而不是 $parent (Card) 对象。我认为使这项工作的方法涉及“创建”方法,如下所示:Adding properties to the view model created by using the Knockout JS mapping plugin

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

编辑:到目前为止我有:

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()”是未定义的。现在深入研究,但如果有人有任何提示,我会全力以赴!

【问题讨论】:

    标签: knockout.js


    【解决方案1】:

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

    我还注意到“编辑”属性存在问题。看来你有一个可观察的和一个同名的函数“编辑”,这将导致一个无休止的递归。

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

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

    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 中的属性。

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

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-14
      • 2014-02-19
      • 2014-01-21
      • 1970-01-01
      • 2011-11-21
      • 1970-01-01
      • 2022-12-05
      • 1970-01-01
      相关资源
      最近更新 更多