淘汰映射添加问题

时间:2012-12-07 14:16:11

标签: knockout.js

我有一个方法,我试图将一个子项添加到我的父项,但是当调用该方法时,调用父项的上下文是未定义的。

代码(为清晰起见缩写)小提琴http://jsfiddle.net/poundingCode/THghy/

// Initialized the namespace
var my = {};
    my.models = {};

    // View model declaration
    my.vm = (function (model) {
        var memberVm = {
            id: ko.observable(model.Id),
            company: ko.observable(model.Company),
            fName: ko.observable(model.FName),
            lName: ko.observable(model.LName),
            name: ko.observable(model.Name),
            positions: ko.observableArray([]),
            totalPositions: ko.observable(),
            totalProjects: ko.observable()
        };

        // children
        memberVm.loadPositions = function (positions) {
            memberVm.totalPositions = 0;
            memberVm.totalProjects = 0;
            $.each(positions, function (i, p) {
                memberVm.positions.push( new my.models.Position()
                .company(p.Company)
                .companyId(p.CompanyId)
                 .description(p.Description)
                .id(p.Id)
                .memberId(p.MemberId)
                .name(p.Name)
                .title(p.Title)
                .projects(p.Projects) 
                );
                memberVm.totalPositions++;
                memberVm.totalProjects += p.Projects.length;
            });// end for each
        }; //end load positions

        memberVm.loadPositions(model.Positions);

        memberVm.fullName = ko.computed(function () {
            return this.fName() + ' ' + this.lName();
        }, memberVm);


        // Computed observable function.
        // We append it to the ViewModel here.

        // return object
        var vm = {
            id: memberVm.id,
            company: memberVm.company,
            fName: memberVm.fName,
            fullName: memberVm.fullName,
            lName: memberVm.lName,
            name: memberVm.name,
            positions: memberVm.positions,
            totalPositions: memberVm.totalPositions,
            totalProjects: memberVm.totalProjects,    

        };
        return vm;
    });

    /////////////////////////////////////
    // Add a position - or at least try to! this is where I get into trouble.

    my.vm.addPosition = (function () {
        var pos = new my.models.Position();
        pos.memberId = my.vm.id;
        my.vm.positions.push(pos);
    });
    /////////////////////////////////////
    // TypeError: my.vm.positions is undefined my.vm.positions.push(pos);
    my.models.Member = (function () {
            id = ko.observable();
            company = ko.observable(); 
            fName = ko.observable();
            lName = ko.observable();
            name = ko.observable();
            positions = ko.observableArray([]);

    });
    my.models.Position = (function () {
        this.company = ko.observable();          
        this.id = ko.observable();           
        this.memberId = ko.observable();
        this.name = ko.observable();
        this.title = ko.observable();
        // place holders
        this.totalProjects = ko.observableArray();
        this.totalCredits = ko.observableArray();
    });


 var viewModel = my.vm(data);
        ko.applyBindings(viewModel);
my.setUI();

HTML

  

      <script type="text/html" id="positionItemTemplate">
          <div class="summary" data-bind="attr : {onClick: 'my.showDetails(' + id() + ')', href: '#detail_'+ id()}">
                                    <a data-bind="attr : { href: '#detail_'+ id()}">
                                    <h2><label data-bind="text: company().Name"></label>: <label data-bind="text: title"></label></h2> </a>
                                    <h3><label data-bind="text: title" ></label> <label data-bind="text: startDate" ></label> - <label data-bind="value: endDate" ></label></h3>

                                </div>
                                <div data-bind="attr : {id: 'detail_' + id() }" class="details" style="right: 580px;">
                                  <div class="positionOverview">
                                   <h2><label data-bind="text: company().Name"></label>: <label data-bind="text: title"></label></h2> </a>
                                     <a data-bind="attr : {href: '#detail_'+ id()}">   <div class="editor-label"><label>Position</label></div></a>
                                        <div class="editor-field">
                                            <input type="text" data-bind="value: company().Name" class="textbox-long">
                                        </div>
                                        <div class="editor-label">
                                            <label>Title</label>
                                        </div>
                                      <div class="editor-field">
                                          <input type="text" data-bind="value: title" class="textbox-long">
                                      </div>
                                        <div class="editor-label">
                                            <label>Summary</label>
                                        </div>
                                        <div class="editor-field">
                                           <textarea data-bind="value: summary"  rows="4" cols="60"></textarea>
                                        </div>
                                        <div class="editor-label"><label>Compensation</label></div>
                                        <div class="editor-field">
                                            <select data-bind="options: $parent.compensations, value: compensationId, optionsText: 'Name', optionsValue: 'Id', optionsCaption: 'Select'"></select>
                                        </div>
                                        <div class="editor-label"><label for="HoursPerWeek" class="hourly">Hours/Week</label></div>
                                        <div class="editor-field">
                                            <input type="text" data-bind="value: hoursPerWeek" class="number-short">
                                        </div>
                                      <div class="div-table">
                                          <div class="div-table-row">
                                              <div class="div-table-col"><label for="StartDate">Start Date</label></div>
                                              <div class="div-table-col"><label for="EndDate">End Date</label></div>
                                              <div class="div-table-col"></div>
                                          </div>
                                          <div class="div-table-row">
                                              <div class="div-table-col"><input type="text" data-bind="value: startDate" class="date"></div>
                                              <div class="div-table-col"><input type="text" data-bind="value: endDate" class="date"></div>

                                          </div>
                                          <div class="div-table-row salary">
                                              <div class="div-table-col"><label for="SalaryStart">$/Hr Start</label></div>
                                              <div class="div-table-col"><label for="SalaryStart">$/Hr End</label></div>
                                          </div>
                                          <div class="div-table-row salary">
                                              <div class="div-table-col"><input type="text" data-bind="value: salaryStart" class="date"></div>
                                              <div class="div-table-col"><input type="text" data-bind="value: salaryEnd" class="date"></div>
                                          </div>
                                      </div>
                                      <input id="btnAddProject" type="button" value="Add Project" data-bind="attr : {onClick: 'addProject(new project())'}">
                                        <input type="button" data-bind="attr : {onClick: 'my.showDetails(' + id() + ')'}" value="Update"/>
                                    </div>                                                                   
                                </div>
      </script>
</head>
    <body>
        <div id="main">
            <div class="marquee center">
                <aside class="aside">
                    <div class="display">
                     <label data-bind="text: 'Total Positions: ' + totalPositions" ></label><input value="Add Position" type="button" data-bind="attr : {onClick: 'my.vm.addPosition()'}"/><br />

                    </div>
                    <div class="adPanel">
                        <h4><div id="message"></div></h4>
                    </div>
                </aside>
            </div>
            <section id="primary" class="primary">
                <article id="article1">
                    <section >
                        <div id="positions">
                            <div class="position" data-bind="template: { name: 'positionItemTemplate', foreach: positions, as: 'position' }">
                            </div>
                        </div>
                    </section>
                </article>
<!--            <footer class="footer">
                <p>Copyright © 2008 All Rights</p>
            </footer>-->
        </section>

        </div>
    </body>
</html>

1 个答案:

答案 0 :(得分:2)

主要问题是您的my.vm是一个构造函数,可用于创建my.vm的实例。但是,addPosition功能已直接添加到my.vm并尝试推送到my.vm.positions

理想情况下,您要做的是在vm的实例上使该函数可用并推送到该实例的positions数组。

因此,您可以将addPosition放入vm声明中,并让它对您要返回的vm变量进行操作。此时,当您添加新位置时,绑定会遇到问题,因为company为空且某些绑定引用company().Name