2

我试图解决的情况是如何将 json 数据的子数组映射到我的视图模型。业务逻辑是,对于给定的职位,有一组项目,每个项目都有一组经验。如果我使用敲除映射器函数,我可以循环并填充我的经验集合,但是我的 viewModel 具有计算函数、订阅事件等,我不确定如何将传入的内部数组连接到该 viewModel。

模型(缩写格式)

// for creating project objects
my.Project = function (selectedProject) {
    var self = this;
    self.project = ko.observable();
    self.company = ko.observable();
    self.experiences = ko.observableArray([]);
    self.hourlyRate = ko.observable();
    self.hours = ko.observable();
    self.hoursPerWeek = ko.observable();
    self.hoursTypeId = ko.observable();
    self.id = ko.observable();
    self.maxDate = ko.observable();
    self.minDate = ko.observable();
    self.minDescriptionLength = ko.observable();
    self.memberId = ko.observable();
    self.name = ko.observable(); 
    self.startDate = ko.observable();
    // non-persistable properties
    self.chartVals = ko.observableArray([]);
    self.isSelected = ko.computed(function () {
        if (typeof selectedProject === 'undefined') {
            return false;
        } else {
            return selectedProject === self;
        }
    });
    self.newExperience = ko.observable(new my.Experience());
    self.selectProject = function (p) {
        console.log(p.name());
        $("#selectedProjectName").text(p.name());
    };
    self.enableDetails = function () {
        my.vm.proficencyTip = ko.observable();
        console.log("enableDetails pow");
        return true;
    },
    self.disableDetails = function () {
        console.log('disableDetails mouse-off');
        return false;
    };
    self.isSelectedProficiency = ko.observable(false);
    self.selectedProficiency = function (p) {
        console.log('Proficiency value is ' + p.name);
    };
    self.updateProject = function () {
        my.postProjectData(self);
    };
    self.hoursTypeId.subscribe(function () {
        var endDate = new Date();
        var startDate = new Date();
        if (self.endDate() != "") {
            endDate = $.datepicker.parseDate("mm/dd/yy", self.endDate()); 
        }
        if (self.startDate() != undefined) {
            startDate = $.datepicker.parseDate("mm/dd/yy", self.startDate());
        }
        var days = (endDate - startDate) / 1000 / 60 / 60 / 24;
        var weeks = days / 7;
        if (self.hoursTypeId() == 2) {
            if (self.hoursPerWeek() > 0) {
                self.totalHours((weeks * self.hoursPerWeek()).toFixed(0));
            } else {

            }
        }
        if (self.hoursTypeId() == 1) {
            if (self.totalHours() > 0) {
                self.hoursPerWeek((self.totalHours() / weeks).toFixed(0));
            }
        }
    });
};
// for creating Position Models
my.Experience = function (selectedExperience) {
    var self = this;
    self.id = ko.observable();
    self.projectId = ko.observable();
    self.positionId = ko.observable();
    self.memberId = ko.observable();
    self.frequencyId = ko.observable();
    self.skillName = ko.observable();
    self.skillId = ko.observable();
    self.proficiencyId = ko.observable();
    self.frequencyId = ko.observable();
    self.proficiency = ko.observable();
    self.frequency = ko.observable();
    self.description = ko.observable();
    self.skill = {
        name:ko.observable()
    };
    self.proficiency.subscribe(function () {
        self.proficiencyId = self.proficiency();
        console.log('proficiency subscribed: ' + self.proficiency());
        my.setCounterHint(self.frequency(), self.proficiency(), self.description());

        var tip = "Don't just list those skills your strongest in. It's just as important to add new skills you are aquiring!";
        var result = $.grep(my.ajaxData.member.Proficiencies, function (e) { return e.Id == self.proficiency(); });
        if (result.length == 0) {
            // not found
        } else if (result.length == 1) {
            // access the foo property using result[0].foo
            tip = result[0].Name + ':\nAutonomy: ' + result[0].Autonomy + '\nContext: ' + result[0].nContext + '\nKnowledge: ' + result[0].Knowledge + '\nWorkmanship: ' + result[0].Workmanship;
        } else {
            // multiple items found
        }
        $(".proficiencyTip").attr('title', tip).attr('alt', tip);
        $(".proficiencyQuestionMark").fadeIn('slow');
    });

    self.frequency.subscribe(function () {
        self.frequencyId = self.frequency();
        console.log('frequency subscribed: ' + self.frequency());
        self.frequencyId = self.frequency();
        $("#newExperienceFrequency").val(self.frequencyId);
        my.setCounterHint(self.frequency(), self.proficiency(), self.description());
        var tip;

        $(".frequencyTip").attr('title', tip).attr('alt', tip);
        $(".frequencyQuestionMark").fadeIn('slow');
    });

    self.minDesc = ko.observable(my.getMinDescriptionLen(self.frequency(), self.proficiency()));

    self.mouseoverDescription = function () {
        $(".tip").hide(); 
        $(".descriptionQuestionMark").fadeIn('slow');
    },
    self.mouseoffDescription = function () { 
        $(".descriptionQuestionMark").delay(3000).fadeOut("slow");
    };

    });
};


The function where I'm loading the data.
loadProjectsForPosition = function (position) {
    // if we have no projects, add one 
    if (position.projects.length == 0) {
            position.projects.push(new my.Project()
                        .company(position.company())
                        .companyName(position.companyName())
                        .endDate(position.endDate())
                        .experiences([])
                        .hourlyRate(position.hourlyRate())
                        .hours(position.hours())
                        .maxDate(position.maxDate())
                        .minDate(position.minDate())
                        .memberId(position.memberId())
                        .description("Summarize the project and its objectives here.")
                        .name('New')
                        .positionId(position.positionId())
                        .startDate(position.startDate())
                        .totalHours(position.totalHours())
                );

        $.each(my.ajaxData.member.Projects, function (i, p) { 
            if (p.PositionId == position.id()) {
                position.projects.push(new my.Project(position.projects[0])
                        .chartVals(p.ChartVals)
                        .company(p.Company)
                        .companyName(p.CompanyName)
                        .creditMinutes(p.CreditMinutes)
                        .description(p.Description)
                        .endDate(p.EndDate)
                        **.experiences(p.Experiences)** 
                        .hourlyRate(p.HourlyRate)
                        .hours(p.Hours)
                        .hoursPerWeek(p.HoursPerWeek)
                        .hoursTypeId(p.HoursTypeId)
                        .id(p.Id)
                        .maxDate(p.MaxDate)
                        .minDate(p.MinDate)
                        .minDescriptionLength(p.MinDescriptionLength)
                        .memberId(p.MemberId)
                        .name(p.Name)
                        .positionId(p.PositionId)
                        .startDate(p.StartDate)
                        .totalCompensation(p.TotalCompensation)
                        .totalHours(p.TotalHours)
                        .weightedHours(p.WeightedHours)
                        .isSelectedProficiency(false)
                );
                position.selectedPosition = true;
            }
        });
    };
}

孙子也有孩子和孙子,所以尽管我正在寻找这个问题的答案,但我正在寻找用于处理“海龟一路向下”的淘汰赛映射中的模式。

与往常一样,感谢您查看、分享您的经验并提供您有充分理由的意见。

4

1 回答 1

4

如果您打算使用映射插件,那么您可能需要查看映射选项以及如何自定义对象的创建方式。文档在这里: http: //knockoutjs.com/documentation/plugins-mapping.html#customizing_object_construction_using_create

虽然,如果您已经为各种对象提供了不错的构造函数,那么您可能根本不需要映射插件。

例如,当您通过父构造函数传递数据时,您可以执行以下操作:

var mappedExperiences = ko.utils.arrayMap(selectedProject.experiences || [], function(item) {
    return new my.Experience(item);
});

self.experiences(mappedExperiences);
于 2012-12-30T18:27:44.947 回答