Question

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



        }
 };
Was it helpful?

Solution

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top