0
votes

I have 3 seperate div's. The first div is bound to the main view model- QuoteSimpleSearchVM

The second div QdetailsDiv is bound to the main view model- QuoteSimpleSearchVM

The third div LineItemresult is bound to the observableArray ProductDetailsArrObj which is within the object SimpleSearchResults.

The main view model- QuoteSimpleSearchVM has an observable array- simpleSearchResultsArray. On selecting one of the array element of simpleSearchResultsArray, the method BindDataToQuotesDetailVM and BindProductsDetails is called. The method BindProductsDetails- fills the array - ProductDetailsArrObj.

Suppose i select the first simpleSearchResultArray element- then simpleSearchResultArray()[0].ProductDetailsArrObj has to be bound to the div- LineItemresult

So the entire structure looks like:

QuoteSimpleSearchVM --> simpleSearchResultsArray()[0] --> ProductDetailsArrObj.

How do I bind simpleSearchResultsArray()[0]'s ProductDetailsArrObj to view? I have used $root & $parent in other scenarios. Not able to fix this issue for the current scenario.

I am getting an error when binding the observable array ProductDetailsArrObj to view. Here is the view code:

<div id="searchResultQuotes" data-bind="visible: $root.showResultTable">
    <div id="resultTable">
        <table id="my-table">
            <thead id="resultTableHeader">
                <tr data-bind="foreach: gridOptions.columns">
                    <th data-bind="visible: checked, text: header">
                    </th>
                </tr>
            </thead>
            <tbody id="resultTableBody" data-bind="foreach: simpleSearchResultsArray">
                <tr>
                    <td>
                        <span data-bind="text: $index()+1"></span>
                    </td>
                    <td>
                        <span data-bind="text: jobName"></span>
                    </td>
                    <td>
                        <span data-bind="text:qName"></span>
                    </td>
                    <td>
                        <a  style="margin-left: auto; margin-right: auto; border: none; background: transparent;box-shadow: none;" data-role="button" data-icon="table_view" data-iconpos="notext" style="text-decoration: none; top: 1%" data-bind="click:function(){ $root.ShowQuotesDetails(qName);}"></a>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</div>


<div id="QdetailsDiv" >
    <div>
        <div>
            <div>
                <span>Job Name</span></div>
            <div>
                <input type="text" id="txtQDJobName" data-bind="value:jobName" /></div>
        </div>
        <div>
            <div>
                <span>Scenarios</span></div>
            <div>
                <input type="text" id="txtScenarioDescription" data-bind="value:scenarios" /></div>
        </div>
    </div>
</div>

<div id="LineItemresult">
    <div class="result">
        <table>
            <thead>
                <tr>
                    <th style="text-align: center">
                        <b>column 1</b>
                    </th>
                    <th style="text-align: center">
                        <b>column 2</b>
                    </th>
                    <th style="text-align: center">
                        <b>column 3</b>
                    </th>
                </tr>
            </thead>
            <tbody id="LineItemTemplateBody" data-bind="foreach: ProductDetailsArrObj">
                <tr>
                    <td>
                        <span data-bind="text:Line"></span>
                    </td>
                    <td>
                        <span data-bind="text:HighLevel"></span>
                    </td>
                    <td>
                        <span data-bind="text:Designation"></span>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

view model code:

ProductDetails = function () {
    var self = this;
    self.Line = ko.observable();
    self.HighLevel = ko.observable();
    self.Designation = ko.observable();  
};

QuoteDetails = function () {
    var self = this;
    self.jobName = ko.observable();
    self.scenarios = ko.observable();
};

function SimpleSearchResults() {
    var self = this;
    self.index = ko.observable();
    self.jobName = ko.observable();
    self.qName = ko.observable();
    self.view = ko.observable();

    self.quoteDetailsObj = new QuoteDetails();
    self.ProductDetailsArrObj = ko.observableArray([]);

    self.BindProductsDetails = function () {
        var tempArray = [];
        console.log(self.ProductDetailsArrObj());
        var data=[{itemNumber:'1',highLevelItem:'HL1',designation:'1'}, {itemNumber:'2',highLevelItem:'HL2',designation:'2'}, {itemNumber:'3',highLevelItem:'HL3',designation:'3'}];

        for (var k = 0; k < data.length; k = k + 1) {
            var tempProdDetails = new ProductDetails();
            tempProdDetails.Line(data[k].itemNumber);
            tempProdDetails.HighLevel(data[k].highLevelItem);
            tempProdDetails.Designation(data[k].designation);
            tempArray.push(tempProdDetails);
        }
        console.log(tempArray.length);
       self.ProductDetailsArrObj(tempArray);
        ko.applyBindings(self.ProductDetailsArrObj, document.getElementById("LineItemresult"));
    };

    self.BindDataToQuotesDetailVM = function () {
        self.quoteDetailsObj.jobName("job name 1");
        self.quoteDetailsObj.scenarios("scenario 1");
        ko.applyBindings(self.quoteDetailsObj, document.getElementById("QdetailsDiv"));
       self.BindProductsDetails();
    };
};

function QuoteSimpleSearchVM() {
    var self = this;
    self.showResultTable = ko.observable(false);
    self.showQuoteDetails= ko.observable(false);

    self.simpleSearchResultsArray = ko.observableArray([]); 

     self.gridOptions = {
        columns: [{
            header: 'Index',
            dataMember: 'index',
            checked: ko.observable(true)
        }, {
            header: 'Job Name',
            dataMember: 'jobName',
            checked: ko.observable(true)
        }, {
            header: 'Quote Name',
            dataMember: 'qName',
            checked: ko.observable(true)
        }, {
            header: 'Quote Number',
            dataMember: 'quoteNumber',
            checked: ko.observable(true)
        }]
     };

    self.Search = function () { 
        var temparray = [];
        self.showResultTable("true");
        var data=[{jobName: 'job 1', documentName: 'quote name 1'}, {jobName: 'job 2', documentName: 'quote name 2'}, {jobName: 'job 3', documentName: 'quote name 3'}];

        for (var k = 0; k < data.length; k = k + 1) {
            var temp = new SimpleSearchResults();
            temp.index = k + 1;
            temp.jobName = data[k].jobName;
            temp.qName = data[k].documentName;
            temparray.push(temp);
        }
        self.simpleSearchResultsArray(temparray);
        if (data.length > 0) {
            self.showResultTable(true);
        }
        ko.applyBindings(QuoteSimpleSearchVMObj, document.getElementById("QdetailsDiv"));
    };

    self.ShowQuotesDetails= function(quoteName){ 
        self.showResultTable("false");
        self.showQuoteDetails("true");
        ko.utils.arrayForEach(self.simpleSearchResultsArray(), function (SimpleSearchResultsObj) {
                if (SimpleSearchResultsObj.qName == quoteName) { 
                    SimpleSearchResultsObj.BindDataToQuotesDetailVM();
                }
            })   
    };
};

var QuoteSimpleSearchVMObj;
$(document).ready(function () {
    QuoteSimpleSearchVMObj = new QuoteSimpleSearchVM();
    ko.applyBindings(QuoteSimpleSearchVMObj, document.getElementById("searchResultQuotes"));

     QuoteSimpleSearchVMObj.Search();
});

QuoteSimpleSearchVM- is the main view model.

On click of the + sign in view, job name, scenario and the columns are bound with the view model data, method BindDataToQuotesDetailVM, BindProductsDetails are called to bind the data. I get a reference error: Unable to parse bindings. Message: ReferenceError: ProductDetailsArrObj is not defined; Bindings value: foreach: ProductDetailsArrObj

Can anyone help me solve this? jsfiddle link for the same: http://jsfiddle.net/ynV35/45/

1

1 Answers

1
votes

Binding the viewModel to HTML makes it $root in knockout context and it variables and methods becomes $data. You can no longer call it by name. The solution in this case where viewModel part that is binded to div is an array is to use foreach: $data instead of foreach: ProductDetailsArrObj.

OLD answer before updates

This is the most common error in knockout. Simple mistype, name or structure change leads to message that binding cannot be parsed. You must learn to resolve this on your own or you won't go far with knockoutjs. KO is nice enough to give you a name of variable you should search in your HTML.

Your ProductDetailsArrObj is inside another object SimpleSearchResults so it should be used with full path in namespace or inside foreach loop as SimpleSearchResults is an array of items. You say that HTML binds separate views but your JS says something different.

This is called in knockout as context. You can read more about it in KO documentation: http://knockoutjs.com/documentation/binding-context.html