目标
我希望创建一个索赔表。此声明表必须支持以下内容:
要求#5在这里处理了 Retrieve boolean value from selected array object
问题
当前代码的编辑和更新过程中断,我知道将数据绑定到相应的选择列表时遇到问题,但我看不到它。
期望的结果
的Javascript
var myViewModel = window["myViewModel"] = {};
(function () {
myViewModel = function () {
var self = this;
self.claimLines = ko.observableArray(ko.utils.arrayMap(claimLines, function (claimLine) {
return new ClaimLine(new ClaimLine("","","","","",""));
}));
// Changed newClaimLine to observable with empty ClaimLine
self.newClaimLine = ko.observable(new ClaimLine("","","","","",""));
self.editClaimLine = function (claimLineItem) {
var editable = new ClaimLine(claimLineItem.serviceStartDate(), claimLineItem.serviceEndDate(), claimLineItem.planType(), claimLineItem.expenseType(), claimLineItem.amount(), claimLineItem.provider());
claimLineBeingEdited = claimLineItem;
self.newClaimLine(editable);
var test = 'test';
};
// The only thing the update method does is emptying the editor form
self.updateClaimLine = function (claimLineBeingUpdated) {
var test = 'test';
claimLineBeingEdited.serviceStartDate(claimLineBeingUpdated.serviceStartDate());
claimLineBeingEdited.serviceEndDate(claimLineBeingUpdated.serviceEndDate());
claimLineBeingEdited.planType(claimLineBeingUpdated.planType());
claimLineBeingEdited.expenseType(claimLineBeingUpdated.expenseType());
claimLineBeingEdited.amount(claimLineBeingUpdated.amount());
claimLineBeingEdited.provider(claimLineBeingUpdated.provider());
self.newClaimLine(new ClaimLine("","","","","",""));
isClaimFor = false;
isExpenseType = false;
};
// This method can only be used for adding new items, not updating existing items
self.addClaimLine = function (claimLineBeingAdded) {
self.claimLines.push(new ClaimLine(claimLineBeingAdded.serviceStartDate(), claimLineBeingAdded.serviceEndDate(), claimLineBeingAdded.planType(), claimLineBeingAdded.expenseType(), claimLineBeingAdded.amount(), claimLineBeingAdded.provider()));
self.newClaimLine(new ClaimLine("","","","","",""));
};
//remove an existing claim line
self.removeClaimLine = function (claimLine) {
self.claimLines.remove(claimLine);
}
//aggregate claim amounts
self.grandTotal = ko.computed(function() {
var total = 0;
$.each(self.claimLines(), function() {
total += parseFloat(this.amount())
});
return "$" + total.toFixed(2);
});
};
function ClaimLine(serviceStartDate, serviceEndDate, planType, expenseType, amount, provider) {
var line = this;
line.serviceStartDate = ko.observable(ko.utils.unwrapObservable(serviceStartDate));
line.serviceEndDate = ko.observable(ko.utils.unwrapObservable(serviceEndDate));
line.planType = ko.observable(ko.utils.unwrapObservable(selectedPlanTypeId));
line.expenseType = ko.observable(ko.utils.unwrapObservable(selectedExpenseTypeId));
line.amount = ko.observable(ko.utils.unwrapObservable(amount));
line.provider = ko.observable(ko.utils.unwrapObservable(provider));
line.expenseTypeName = ko.computed(function() {
return ko.utils.arrayFirst(self.expenseTypes, function (expenseTypeSomething) {
return expenseTypeSomething.id == line.expenseType();
});
});
line.planTypeName = ko.computed(function() {
return ko.utils.arrayFirst(self.planTypes, function (planTypeSomething) {
return planTypeSomething.id == line.planType();
});
});
}
var claimLines = [
];
self.planTypes = [
{ id: 1, name: 'The EBC HRA - Deductible', hasClaimFor: true, hasExpenseType: false },
{ id: 2, name: 'FSA - Health Care FSA', hasClaimFor: false, hasExpenseType: true },
{ id: 3, name: 'FSA - Dependent Care FSA', hasClaimFor: false, hasExpenseType: true }
];
self.claimForWhom = [
{ id: 1, name: "Self"},
{ id: 2, name: "Boston Allen (Dependent)"},
{ id: 3, name: "Bishop Allen (Dependent)"},
{ id: 4, name: "Billy Allen Jr (Dependent)"},
{ id: 5, name: "Billy Allen Sr (Dependent)"},
{ id: 6, name: "Name not listed"}
];
self.expenseTypes = [
{ id: 1, name: "Chiropractic"},
{ id: 2, name: "Dental"},
{ id: 3, name: "Massage Therapy"},
{ id: 4, name: "Medical"},
{ id: 5, name: "Medical Mileage"},
{ id: 6, name: "Office Visit"},
{ id: 7, name: "Optical"},
{ id: 8, name: "Orthodontic"},
{ id: 9, name: "OTC"},
{ id: 10, name: "Prescription"},
{ id: 11, name: "Supplement/Vitamin"},
{ id: 12, name: "Therapy"}
];
self.providers = [
"Dean",
"Mercy Health",
"UW Health",
"Aurora"
];
self.selectedPlanTypeId = ko.observable();
self.selectedExpenseTypeId = ko.observable();
self.selectedClaimForWhomId = ko.observable();
self.selectedPlanType = ko.computed(function () {
var selectedPlanTypeId = self.selectedPlanTypeId();
return ko.utils.arrayFirst(self.planTypes, function (planType) {
return planType.id == selectedPlanTypeId;
});
});
self.selectedExpenseType = ko.computed(function () {
var selectedExpenseTypeId = self.selectedExpenseTypeId();
return ko.utils.arrayFirst(self.expenseTypes, function (expenseType) {
return expenseType.id == selectedExpenseTypeId;
});
});
self.isClaimFor = ko.computed(function(){
var selectedPlanType = self.selectedPlanType();
return selectedPlanType && !!selectedPlanType.hasClaimFor;
});
self.isExpenseType = ko.computed(function(){
var selectedPlanType = self.selectedPlanType();
return selectedPlanType && !!selectedPlanType.hasExpenseType;
});
})();
$(document).ready(function(){
myViewModel = new myViewModel();
ko.applyBindings(myViewModel);
$('.datepicker').datepicker();
});
HTML
<h3 class="body">Enter Claim Lines</h3>
<form class="form-horizontal col-xs-12 col-sm-12 col-md-12 col-lg-12" role="form" data-bind="with: newClaimLine">
<div class="form-group">
<label for="serviceStartDate" class="col-sm-4 control-label">Service Start Date</label>
<div class="col-sm-4">
<input id="serviceStartDate" type="date" class="form-control datepicker" data-bind="value: serviceStartDate" placeholder="mm/dd/yyyy" />
</div>
</div>
<div class="form-group">
<label for="serviceEndDate" class="col-sm-4 control-label">Service End Date</label>
<div class="col-sm-4">
<input id="serviceEndDate" type="date" class="form-control datepicker" data-bind="value: serviceEndDate" placeholder="mm/dd/yyyy" />
</div>
</div>
<div class="form-group">
<label for="planType" class="col-sm-4 control-label">Plan Type</label>
<div class="col-sm-4">
<select id="planType" class="form-control" data-bind="options: planTypes, optionsText: 'name', optionsCaption: 'Choose Plan Type', optionsValue: 'id', value: selectedPlanTypeId">
</select>
</div>
</div>
<div data-bind="if: isClaimFor">
<div class="form-group">
<label for="claimForWhom" class="col-sm-4 control-label">Claim For</label>
<div class="col-sm-4">
<select id="claimForWhom" class="form-control" data-bind="options: claimForWhom, optionsText : 'name', optionsCaption: 'Select Dependent', optionsValue: 'id', value: selectedClaimForWhomId"></select>
</div>
</div>
</div>
<div data-bind="if: isExpenseType">
<div class="form-group">
<label for="expenseType" class="col-sm-4 control-label">Expense Type</label>
<div class="col-sm-4">
<select id="expenseType" class="form-control" data-bind="options: expenseTypes, optionsText : 'name', optionsCaption: 'Select Expense Type', optionsValue: 'id', value: selectedExpenseTypeId"></select>
</div>
</div>
</div>
<div class="form-group">
<label for="amount" class="col-sm-4 control-label">Amount</label>
<div class="col-sm-4">
<input id="amount" type="date" class="form-control" data-bind="value: amount" placeholder="Enter Amount" />
</div>
</div>
<div class="form-group">
<label for="provider" class="col-sm-4 control-label">Provider</label>
<div class="col-sm-4">
<select id="provider" class="form-control" data-bind="options: providers, optionsCaption: 'Choose Provider Type', value: provider">
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-6 col-sm-offset-4">
<button class="btn btn-default" data-bind="click: $root.addClaimLine"><i class="fa fa-plus fa-lg fa-fw"></i> Add Claim Line</button>
<button class="btn btn-default" data-bind="click: $root.updateClaimLine"><i class="fa fa-refresh fa-lg fa-fw"></i> Update Claim Line</button>
</div>
</div>
</form>
<!-- Desktop saved claim lines -->
<table class="hidden-xs table table-responsive table-condensed" data-bind="visible: claimLines().length > 0">
<thead>
<tr>
<th colspan="2">Saved Claim Lines
<span class="pull-right">Claim Total = <span data-bind="text: grandTotal()"></span></span>
</th>
</tr>
</thead>
<tbody data-bind="foreach: claimLines">
<tr>
<td>
<p><strong><span data-bind="text: planTypeName().name"></span> - <span data-bind="text: expenseTypeName().name"></span><br /></strong><strong data-bind="text: $root.grandTotal()"></strong> claim incurred between <strong data-bind="text: serviceStartDate"></strong> and <strong data-bind="text: serviceEndDate"></strong>.</p>
</td>
<td class="text-right">
<button data-bind="click: $root.editClaimLine" class="btn btn-link">
<i class="fa fa-edit fa-2x"></i>
</button>
<button data-bind="click: $root.removeClaimLine" class="btn btn-link">
<i class="fa fa-times fa-2x"></i>
</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<th class="text-right" colspan="2">
<span>Claim Total = <span data-bind="text: grandTotal()"></span></span>
</th>
</tr>
</tfoot>
</table>
答案 0 :(得分:1)
这里有一些问题。
您的选择数组声明为self.planTypes = ...
。 self是myViewModel构造函数中的变量。你 应该得到一个例外,但这一点已经将 self 变量声明为等于窗口。
您选择的... observables也都在窗口范围内,并未包含在myViewModel中。
当您添加新的声明行时,我会根据您选择的内容获取javascript错误,例如,如果expenseType为null。
<强>解决方案强>
我创建了一个顶级命名空间调用模型,并将所有内容附加到其中。 我为编辑声明行创建了一个显式类。这允许您添加各种帮助功能和可观察对象,而不会污染声明行本身。 我已经更改了所有选项绑定以删除Id参数。我发现使用该对象更容易,而不是不断查找数组成员。
我已经实现了添加和更新功能。
我还删除了datapicker jQuery调用,因为在使用此插件时需要做更多的工作来更新observable。没有帮助(即自定义绑定),DatePicker插件和Knockout不能并行工作。
我还在声明行的按钮中添加了字母E和R(编辑和删除),因为我没有获得任何UI(在你的小提琴中缺少CSS?)
<强> HTML 强>
<section class="row top10">
<div class="col-xs-12 col-sm-12 col-md-8 col-lg-8 col-md-offset-2 col-lg-offset-2">
<form class="form-horizontal col-xs-12 col-sm-12 col-md-12 col-lg-12" role="form" data-bind="with: newClaimLine">
<div class="form-group">
<label for="serviceStartDate" class="col-sm-4 control-label">Service Start Date</label>
<div class="col-sm-4">
<input id="serviceStartDate" type="date" class="form-control datepicker" data-bind="value: serviceStartDate" placeholder="mm/dd/yyyy" />
</div>
</div>
<div class="form-group">
<label for="serviceEndDate" class="col-sm-4 control-label">Service End Date</label>
<div class="col-sm-4">
<input id="serviceEndDate" type="date" class="form-control datepicker" data-bind="value: serviceEndDate" placeholder="mm/dd/yyyy" />
</div>
</div>
<div class="form-group">
<label for="planType" class="col-sm-4 control-label">Plan Type</label>
<div class="col-sm-4">
<select id="planType" class="form-control" data-bind="options: Models.planTypes, optionsText: 'name', optionsCaption: 'Choose Plan Type', value: planType"></select>
</div>
</div>
<div data-bind="if: isClaimFor">
<div class="form-group">
<label for="claimForWhom" class="col-sm-4 control-label">Claim For</label>
<div class="col-sm-4">
<select id="claimForWhom" class="form-control" data-bind="options: Models.claimForWhom, optionsText : 'name', optionsCaption: 'Select Dependent', value: claimFor"></select>
</div>
</div>
</div>
<div data-bind="if: isExpenseType">
<div class="form-group">
<label for="expenseType" class="col-sm-4 control-label">Expense Type</label>
<div class="col-sm-4">
<select id="expenseType" class="form-control" data-bind="options: Models.expenseTypes, optionsText : 'name', optionsCaption: 'Select Expense Type', value: expenseType"></select>
</div>
</div>
</div>
<div class="form-group">
<label for="amount" class="col-sm-4 control-label">Amount</label>
<div class="col-sm-4">
<input id="amount" type="number" class="form-control" data-bind="value: amount" placeholder="Enter Amount" />
</div>
</div>
<div class="form-group">
<label for="provider" class="col-sm-4 control-label">Provider</label>
<div class="col-sm-4">
<select id="provider" class="form-control" data-bind="options: Models.providers, optionsCaption: 'Choose Provider Type', value: provider"></select>
</div>
</div>
<div class="form-group">
<div class="col-sm-6 col-sm-offset-4">
<button class="btn btn-default" data-bind="click: $root.addClaimLine, enable: !claimId()"><i class="fa fa-plus fa-lg fa-fw"></i> Add Claim Line</button>
<button class="btn btn-default" data-bind="click: $root.updateClaimLine, enable: claimId"><i class="fa fa-refresh fa-lg fa-fw"></i> Update Claim Line</button>
</div>
</div>
</form>
<!-- Desktop saved claim lines -->
<table class="hidden-xs table table-responsive table-condensed" data-bind="visible: claimLines().length > 0">
<thead>
<tr>
<th colspan="2">Saved Claim Lines <span class="pull-right">Claim Total = <span data-bind="text: grandTotal()"></span></span>
</th>
</tr>
</thead>
<tbody data-bind="foreach: claimLines">
<tr>
<td>
<p><strong><span data-bind="text: planTypeName().name"></span> - <span data-bind="text: expenseTypeName().name"></span><br /></strong><strong data-bind="text: $root.grandTotal()"></strong> claim incurred between <strong data-bind="text: serviceStartDate"></strong> and <strong data-bind="text: serviceEndDate"></strong>.</p>
</td>
<td class="text-right">
<button data-bind="click: $root.editClaimLine" class="btn btn-link"> <i class="fa fa-edit fa-2x">E</i>
</button>
<button data-bind="click: $root.removeClaimLine" class="btn btn-link"> <i class="fa fa-times fa-2x">R</i>
</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<th class="text-right" colspan="2"> <span>Claim Total = <span data-bind="text: grandTotal()"></span></span>
</th>
</tr>
</tfoot>
</table>
<!-- Mobile saved claim lines -->
<div class="hidden-sm hidden-md hidden-lg" data-bind="visible: claimLines().length > 0">
<h3 class="body">Saved Claim Lines</h3>
<div data-bind="foreach: claimLines">
<div>
<p>Your <strong data-bind="text: planTypeName().name"></strong> incurred a <strong data-bind="text: expenseTypeName().name"></strong> claim for <strong data-bind="text: $root.grandTotal()"></strong> between <strong data-bind="text: serviceStartDate"></strong> - <strong data-bind="text: serviceEndDate"></strong>.</p>
<p>
<button data-bind="click: $root.editClaimLine" class="btn btn-default"> <i class="fa fa-edit fa-lg"></i> Edit Claim Line</button>
<button data-bind="click: $root.removeClaimLine" class="btn btn-default"> <i class="fa fa-times fa-lg"></i> Delete Claim Line</button>
</p>
</div>
</div>
</div>
<h3 class="body">Attach Supporting Documentation</h3>
<button class="btn btn-default btn-lg" role="button"> <i class="fa fa-cloud-upload fa-3x fa-fw pull-left"></i>
<span class="pull-left text-left">Upload<br />Documentation</span>
</button>
<hr />
<div class="pull-right">
<button class="btn btn-link btn-lg">Cancel</button>
<button class="btn btn-default btn-lg" role="button"> <i class="fa fa-check fa-fw"></i>Verify Claim</button>
</div>
</div>
</section>
<强>的Javascript 强>
var Models = window["Models"] = {};
(function () {
Models.ViewModel = function () {
var self = this;
var newClaimId = 0;
self.claimLines = ko.observableArray(ko.utils.arrayMap(claimLines, function (claimLine) {
return new Models.ClaimLine("","","","","","", "");
}));
// Changed newClaimLine to observable with empty ClaimLine
self.newClaimLine = new Models.EditClaimLine();
self.editClaimLine = function(claimLineItem) {
self.newClaimLine.edit(claimLineItem);
};
/*
self.editClaimLine = function (claimLineItem) {
var editable = new ClaimLine(claimLineItem.serviceStartDate(), claimLineItem.serviceEndDate(), claimLineItem.planType(), claimLineItem.expenseType(), claimLineItem.amount(), claimLineItem.provider());
claimLineBeingEdited = claimLineItem;
self.newClaimLine(editable);
var test = 'test';
};
*/
// The only thing the update method does is emptying the editor form
self.updateClaimLine = function (claimLineBeingUpdated) {
var foundClaim = ko.utils.arrayFirst( self.claimLines(), function(item) { return item.claimId() == claimLineBeingUpdated.claimId(); } );
var test = 'test';
foundClaim.serviceStartDate(claimLineBeingUpdated.serviceStartDate());
foundClaim.serviceEndDate(claimLineBeingUpdated.serviceEndDate());
foundClaim.planType(claimLineBeingUpdated.planType());
foundClaim.expenseType(claimLineBeingUpdated.expenseType());
foundClaim.amount(claimLineBeingUpdated.amount());
foundClaim.provider(claimLineBeingUpdated.provider());
foundClaim.claimFor(claimLineBeingUpdated.claimFor());
self.newClaimLine.reset(); //(new ClaimLine("","","","","",""));
};
// This method can only be used for adding new items, not updating existing items
self.addClaimLine = function (claimLineBeingAdded) {
var newClaim = new Models.ClaimLine(claimLineBeingAdded.serviceStartDate, claimLineBeingAdded.serviceEndDate, claimLineBeingAdded.planType, claimLineBeingAdded.expenseType, claimLineBeingAdded.amount, claimLineBeingAdded.provider, claimLineBeingAdded.claimFor);
newClaim.claimId(++newClaimId);
self.claimLines.push(newClaim);
self.newClaimLine.reset(); //(new ClaimLine("","","","","",""));
};
//remove an existing claim line
self.removeClaimLine = function (claimLine) {
self.claimLines.remove(claimLine);
}
//aggregate claim amounts
self.grandTotal = ko.computed(function() {
var total = 0;
$.each(self.claimLines(), function() {
total += parseFloat(this.amount())
});
return "$" + total.toFixed(2);
});
};
Models.EditClaimLine = function() {
var self = this;
self.claimId = ko.observable();
self.serviceStartDate = ko.observable();
self.serviceEndDate = ko.observable();
self.planType = ko.observable();
self.claimFor = ko.observable();
self.expenseType = ko.observable();
self.amount = ko.observable();
self.provider = ko.observable();
self.isClaimFor = ko.computed(function(){
var selectedPlanType = self.planType();
return selectedPlanType && !!selectedPlanType.hasClaimFor;
});
self.isExpenseType = ko.computed(function(){
var selectedPlanType = self.planType();
return selectedPlanType && !!selectedPlanType.hasExpenseType;
});
self.reset = function(){
self.claimId(undefined);
self.serviceStartDate(undefined);
self.serviceEndDate(undefined);
self.planType(undefined);
self.claimFor(undefined);
self.expenseType(undefined);
self.amount(undefined);
self.provider(undefined);
};
self.edit = function(claim) {
self.claimId(claim.claimId());
self.serviceStartDate(claim.serviceStartDate());
self.serviceEndDate(claim.serviceEndDate());
self.planType(claim.planType());
self.claimFor(claim.claimFor());
self.expenseType(claim.expenseType());
self.amount(claim.amount());
self.provider(claim.provider());
};
self.reset();
}
Models.ClaimLine = function(serviceStartDate, serviceEndDate, planType, expenseType, amount, provider, claimFor) {
var line = this;
var getName = function(value){
return (ko.unwrap(value) || { name: '' }).name;
};
line.claimId = ko.observable();
line.serviceStartDate = ko.observable(ko.unwrap(serviceStartDate));
line.serviceEndDate = ko.observable(ko.unwrap(serviceEndDate));
line.planType = ko.observable(ko.unwrap(planType));
line.expenseType = ko.observable(ko.unwrap(expenseType));
line.amount = ko.observable(ko.unwrap(amount));
line.provider = ko.observable(ko.unwrap(provider));
line.claimFor = ko.observable(ko.unwrap(claimFor));
line.expenseTypeName = ko.computed(function() {
return getName(line.expenseType);
});
line.planTypeName = ko.computed(function() {
return getName(line.planType);
});
}
var claimLines = [
];
Models.planTypes = [
{ id: 1, name: 'The EBC HRA - Deductible', hasClaimFor: true, hasExpenseType: false },
{ id: 2, name: 'FSA - Health Care FSA', hasClaimFor: false, hasExpenseType: true },
{ id: 3, name: 'FSA - Dependent Care FSA', hasClaimFor: false, hasExpenseType: true }
];
Models.claimForWhom = [
{ id: 1, name: "Self"},
{ id: 2, name: "Boston Allen (Dependent)"},
{ id: 3, name: "Bishop Allen (Dependent)"},
{ id: 4, name: "Billy Allen Jr (Dependent)"},
{ id: 5, name: "Billy Allen Sr (Dependent)"},
{ id: 6, name: "Name not listed"}
];
Models.expenseTypes = [
{ id: 1, name: "Chiropractic"},
{ id: 2, name: "Dental"},
{ id: 3, name: "Massage Therapy"},
{ id: 4, name: "Medical"},
{ id: 5, name: "Medical Mileage"},
{ id: 6, name: "Office Visit"},
{ id: 7, name: "Optical"},
{ id: 8, name: "Orthodontic"},
{ id: 9, name: "OTC"},
{ id: 10, name: "Prescription"},
{ id: 11, name: "Supplement/Vitamin"},
{ id: 12, name: "Therapy"}
];
Models.providers = [
"Dean",
"Mercy Health",
"UW Health",
"Aurora"
];
})();
$(document).ready(function(){
var myViewModel = new Models.ViewModel();
ko.applyBindings(myViewModel);
//$('.datepicker').datepicker();
});