3

我正在尝试使用<pre>标签调试 ko(版本:2.2.1):

 <pre data-bind="text:ko.toJSON($root,null,2)"></pre>

但我得到了这个:

Uncaught Error: Unable to parse bindings.
Message: TypeError: Object object has no method 'getType';
Bindings value: text:ko.toJSON($root,null,2) 

更新:

似乎 $root 对象实际上是 windows 对象,为什么会发生,我如何确保它仍然在我的 ViewModel 范围内?

场景是这样的:

我有一个视图,其中还包含一个弹出模板。当用户单击一个按钮时,弹出窗口会显示,这就是我收到此错误的时候($root 失去了 ViewModel 范围并成为窗口对象)。

看法:

        <a  href="#" class="caspButton" data-bind="visible: editMode(), click:setEditMode">Done</a> 
        <!-- ko if: entities().length > 0 -->
        //THIS OPENS THE PROBLEMATIC POPUP
        <a href="#caspPopupAddEntities" class="caspButton caspPlus" data-bind="visible: editMode(), click:bindPopup.bind($root)"></a>
        <!-- /ko -->

        <!-- ko if: parentChildArr().length > 0 -->
        <a href="sp/book/addChildEntity" class="caspButton caspPlus"  data-bind="visible: editMode(),cafeHrefParam: {entity: 'entity',st:'st',parentEntityType: parentTypeName,parentPropName:parentPropName }" title="Add Entity" data-cafeDialog="popup"></a>
        <!-- /ko -->

        <header>
            <h2 class="caspFancy" data-bind="text: $root.title"></h2>
        </header>

        <div class="caspData">
            <!-- ko if: entities().length > 0 -->
            <ul data-bind="foreach: entities">
                <li data-bind="css: {caspEditable: $root.editMode(),caspListSeperator: !$root.editMode()}"> 
                    <a class="caspDelete caspPosition" href="#removeEntities" title="Delete" data-bind="visible: $root.editMode(),click: $root.bindPopup"
                    data-delete="true"></a>

                    <div class="caspInnerData">
                        <a class="caspBookLink" data-bind="attr: {href: 'sp/book/book' }, cafeHrefParam: { chapter: 'chapter', page: 'page', id: $data.id }, text: name,css: {caspBullet: !$root.editMode()}"></a>

                        <!-- ko if: shortDescription -->
                        <p data-bind="text: shortDescription"></p>
                        <!-- /ko -->
                    </div>
                    <!-- end .caspInnerData -->
                </li>
            </ul>
            <!-- /ko -->

            <!-- ko if: parentChildArr -->
            <ul data-bind="foreach: parentChildArr">
                <!-- ko if: children().length > 0 -->
                <li data-bind="css: {caspEditable: $root.editMode()}"> 

                    <div class="caspInnerData"> 
                    <div class="caspParent"> 
                        <span data-bind="text: $root.parentTypeName"></span> :
                         <a data-bind="attr: {href: 'sp/book/book' }, cafeHrefParam: { chapter: $root.parentTypeNamePlural, page: 'page', id: $data.id }, text: parent" class="caspBookLink"></a> 
                     </div>                   

                        <ul data-bind="foreach:children">
                            <li>
                                <a class="caspDelete" href="#removeEntities" title="Delete" data-bind="visible: $root.editMode(),click: $root.bindPopup"
                                data-delete="true"></a>

                                <a data-bind="attr: {href: 'sp/book/book' }, cafeHrefParam: { chapter: 'chapter', page: 'page', id: $data.id }, text: name" class="caspBookLink caspBullet"></a>                             
                            </li>
                        </ul>

                    </div>
                    <!-- end .caspInnerData -->
                </li>
                <!-- /ko -->
            </ul>
            <!-- /ko -->                

        </div>
        <!-- end .caspData -->

//HERE IS THE PROBLEM - '$root' becomes the windows object when i open this popup
 <div id="caspPopupAddEntities" data-role="popup" class="popup">
            <div class="caspBtnWrapper"> 

                <a href="#" data-role="button" class="caspButton cafeRight" data-bind="click:$root.saveEntity.bind($root)">Done</a>
                <a href="#" data-role="button" class="caspButton cafeLeft" data-bind="click:$root.cancel">Cancel</a>
            </div>
            <!-- end .caspBtnWrapper -->
            <header>
             <h1 class="caspFancy">Add New</h1>

         </header>
         <div class="caspDataWrapper" data-bind="with:$root.addItem()">
            <fieldset data-role="fieldcontain">
                <label for="title">Title</label>
                <input type="text" name="title" id="title" data-bind="value:name"
                />
            </fieldset>
            <fieldset data-role="fieldcontain">
                <label for="shortDescription">Overview</label>
                <textarea class="caspTextarea" type="text" name="shortDescription"
                id="shortDescription" data-bind="value:shortDescription" />
            </fieldset>
            <fieldset data-role="fieldcontain">
                <label for="mission">Mission</label>
                <textarea class="caspTextarea" type="text" name="mission"
                id="mission" data-bind="value:description" />
            </fieldset>
            <fieldset data-role="fieldcontain">
                <label for="period">Period</label>
                <input type="text" placeholder="  Set date and Time" name="period"
                id="period" data-bind="value:periodName" />
            </fieldset>
            <fieldset data-role="fieldcontain">
                <label for="ownedBy">Owned By</label>
                <input placeholder= "Select" type="text" name="ownedBy" id="ownedBy" data-bind="value:ownedBy,cafeAutoComplete: {source: 'users'}">
            </fieldset>
            <fieldset data-role="fieldcontain">
                <label for="assignedTo">Assigned to</label>
                 <input placeholder= "Select" type="text" name="assignedTo" id="assignedTo" data-bind="value:assignedTo,cafeAutoComplete: {source: 'users'}">
            </fieldset>
        </div>
        <!-- end .caspDataWrapper -->
    </div>
    <!-- end #caspPopupAddEntities -->



</div>
<!-- end content -->
</div>
<!-- end page -->

视图模型:

  /**
 * The module for the common Entities ViewModel
 */
define(['ko', 'komap', 'kopost', 'ca', 'sp/utils', 'sp/db'], function (ko, komap, kopost, ca, util, db) {

    /**
     * The Entities ViewModel.  This VM just exposes a collection of entities in a single property.
     * The model to retrieve is obtained from the last portion of the URL path.
     */

    function EntitiesViewModel(ctx, data) {
        this.init(ctx,data);

    }

    // EntitiesViewModel.prototype = new ca.ViewModel({});

    // EntitiesViewModel.prototype.constructor = EntitiesViewModel;

    ko.utils.extend(EntitiesViewModel.prototype,(function(){



        init = function(ctx,data){
            var self = this;
            strategyId = ctx.param.st;
            entitySet = db.getEntitySetFromElementType(ctx.param.entity);
                parentEntitySet = _getParentEntitySet(entitySet);                      
                childPropName = util.getChildEntityPropertyName(parentEntitySet);

            self.editMode = ko.observable(false);
            self.entities = ko.observableArray([]);
            self.parentChildArr = ko.observableArray([]);   
            self.users = ko.observableArray([]);

            self.parentPropName = util.getParentEntityPropertyName(entitySet);
            self.parentTypeName = util.getParentTypeName(entitySet);    
            self.parentTypeNamePlural = util.getPluralName(self.parentTypeName);

            self.title = ko.computed(function () {
                // temporary method to get the plural name.
                return util.getPluralName(entitySet.collectionName);
            });

            self.addItem = ko.observable(entitySet.addNew());
            self.addItem().name = ko.observable("");
            self.addItem().shortDescription = ko.observable("");
            self.addItem().mission = ko.observable("");
            self.addItem().period = ko.observable("");
            self.addItem().ownedBy = ko.observable("");
            self.addItem().assignedTo = ko.observable("");

            _loadData(self);
        },



        bindPopup = function (o, e) {
            openPopup(o, e);
            selectedEntity = o;
            var popupId = $(e.target).attr('href');
            ko.applyBindings(self, $('#overlay').find(popupId).get(0));
            db.User.toArray( this.users );
        },



        startEdit = function (o, e) {
            self.editMode(true);
            e.stopPropagation();
        },

        cancel = function (o, e) {  
            closePopup(o, e);
            this.addItem (entitySet.addNew());
        },




        saveEntity = function (o, e) {
            var self = this;
            var parent = parentEntitySet.addNew({ id: strategyId });
            parentEntitySet.attachOrGet(parent);

            var entity = {
                name: self.addItem().name,
                shortDescription: self.addItem().shortDescription,
                description: self.addItem().description
            }

            entity[self.parentPropName] = parent;

            var newEntity = entitySet.addNew(entity);
            entitySet.attachOrGet(newEntity);
            entitySet.add(newEntity);

            db.saveChanges().done(function (i) {
                closePopup(o, e);                               
                _loadData(self);
                self.addItem (entitySet.addNew());
                kopost.publish("ca.sp.entitiesChanged", "Add new Entity");

            }).fail(function (error) {
                self.addItem (entitySet.addNew());
                console.log('Error = ' + error);

            });

            //detach the entities after save to avoid having them saved again
            entitySet.detach(newEntity);
            parentEntitySet.detach(parent);

            e.stopPropagation();
        };


        return {
            init: init,
            setEditMode: setEditMode,
            bindPopup: bindPopup,
            cancelDelete: cancelDelete,
            startEdit: startEdit,
            cancel: cancel,
            deleteEntity: deleteEntity,
            saveEntity: saveEntity
        }

    }()));
    return EntitiesViewModel;
});
4

1 回答 1

0

$data指上下文中的当前项。一个简单的ko.toJSON($data)应该告诉你结果。

于 2013-01-28T18:08:24.617 回答