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

的孙子有孩子和孙子一样,所以就像我正在寻找一个answser这个问题,我在寻找什么模式是在挖掘映射处理“一路下来的乌龟”。

一如既往,感谢您一起看看,分享您的经验并提供您的理由充分的意见。

回答

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); 
+0

瑞安,不能感谢你足够抽空你星期天来分享你的经验和智慧。你是Knockout.js的守护神,也是失去开发者的发现者!阵列技术和你精辟的解释就像一个魅力。 –