I have a drop down box and a radio button that are part of a detail row. There can be multiple detail rows, so there can be multiple instances of this radio button and drop down list. I have an observablearray that is a master list of loans of types 'dl' and 'sb'. The 'dl' and 'sb' are the values on the radio buttons. When a user selects a radio button, i want to populate the drop down box with a list of the loans that have the loan type selected ('dl' or 'sb') from the radio button. So, for example, if a user selects the radio button that has the value of 'sb,' then I want to populate the drop down list on the selected detail row with only those loans that are 'sb' loan types (in the observable, a field called DocStandBy is tied to the loan type, and LoanNum in the same observable is the loan number to be displayed in the drop down box).
I have not been able to figure out how to return a filtered subset of an observablearray to a drop down box based on a click event on a radio button. Below is code that obviously does not work, but does illistrate what I am trying to do. How can I alter the below code to get this to work?
VIEW-
<tbody data-bind="foreach: LoanDetails()">
<tr style="border: none">
<td colspan="2">
<input type="radio" data-bind="checked: DocStandby, attr: { 'name': SeedID(), 'value': 'DL' }, click: $parent.SaveDocStand($data)" />
Documentary
<input type="radio" data-bind="checked: DocStandby, attr: { 'name': SeedID(), 'value': 'SB' }, click: $parent.SaveDocStand($data)" />
Stand By
</td>
</tr>
<tr style="border: none">
<td style="font-weight: bold">AB Loans:</td>
<td>
<select id="ddlLoans" data-bind=" optionsCaption: 'Choose...',
options: $parent.ABLoans($parent.dlOrSB() == $data.DocStandby()), optionsText: 'LoanNum',
optionsValue: 'LoanNum'">
</select>
</td>
</tr>
</tbody>
VIEWMODEL EDITED-
define(['services/logger', 'durandal/system', 'plugins/router', 'services/CertificateDataService', 'controls/Lucas', 'services/ErrorLoggingDataService', 'services/LCDataService'],
function (logger, system, router, CertificateDataService, Lucas, ErrorLoggingDataService, LCDataService) {
var clients = ko.observableArray([]);
var ABLoans = ko.observableArray([]);
var clientID = ko.observable();
var LoanDetails = ko.observableArray([]);
var dlOrSB = ko.observable();
var vm = {
activate: activate,
clients: clients,
LoanDetails: LoanDetails,
ABLoans: ABLoans,
dlOrSB: dlOrSB,
clientID: clientID,
AddLC: function () {
nextnum(nextnum() + 1);
LoanDetails.push(buildRow(nextnum(), vm.LCLoans, 'DD'));
},
SaveDocStand: function (row) {
if (row.DocStandby() != null && row.DocStandby() != '') {
//POPLUATES ABLoans observablearray, or THE MASTER LIST OF LOANS
GetLoansByClient(row.DocStandby(), clientID(), 'AB');
}
ko.utils.arrayForEach(LoanDetails(), function (item) {
if (item.SeedID() == row.SeedID()) {
item.FilteredLoans = ko.computed(function () {
var val = row.DocStandby();
return LCLoans().filter(function (item) {
return val && item.LoanSubType === val;
});
})
}
});
dlOrSB = row.DocStandby();
}
};
Each element of your LoanDetails array needs to have a separate computed that returns a filtered array of your ABLoans based on the selected DocStandby.
You will notice that each element of LoadDetails has its own ko.computed ( FilteredLoans ) that just returns a filter based on the value of the DocStandby observable. It uses a common source of loans ( ABLoans ) so if that array was ever to be updated then all line item computed will also re-filter.
Here is a basic example that shows you the mechanics invoked, you will need to adapt to your exact object model, specifically how you create your LoadDetail array items.
HTML
<table>
<tbody data-bind="foreach: LoanDetails">
<tr colspan="2">
<td><input type="radio" data-bind="checked: DocStandby, attr: { 'name': SeedID(), 'value': 'DL' }" />Documentary
<input type="radio" data-bind="checked: DocStandby, attr: { 'name': SeedID(), 'value': 'SB' }" />Stand By</td>
</tr>
<tr>
<td>AB Loan:</td>
<td><select data-bind="options: FilteredLoans, value: LoanNum, optionsValue: 'LoanNum', optionsText: 'LoanNum', optionsCaption: 'Choose...'"></select></td>
</tr>
</tbody>
</table>
JAVASCRIPT
var vm = {
LoanDetails: ko.observableArray([]),
ABLoans: ko.observableArray([])
};
var buildRow = function( seed, ABLoans) {
var obj = {
SeedID: ko.observable(seed),
DocStandby: ko.observable(),
LoanNum: ko.observable()
};
// Add to object after obj is created so we can use that instance
// using "this" to read the items DocStandby value
obj.FilteredLoans = ko.computed( function() {
var val = this.DocStandby();
return ABLoans().filter( function( item ) {
return val && item.Type === val;
} );
}, obj);
return obj;
};
vm.ABLoans( [
{ LoanNum: '1-DL', Type: 'DL' },
{ LoanNum: '2-DL', Type: 'DL' },
{ LoanNum: '1-SB', Type: 'SB' },
{ LoanNum: '2-SB', Type: 'SB' },
] );
vm.LoanDetails.push( buildRow(1, vm.ABLoans));
vm.LoanDetails.push( buildRow(2, vm.ABLoans));
ko.applyBindings(vm);
See this jsFiddle for the above code working