简体   繁体   中英

KOGrid Cell Template $parent is not defined

A beginner level javascript question...

I need to define a cell template for my KOGrid that is dependent on values in my VM. I want text to be displayed green if an associated field is True else display in red.

I have the following cell templates:

var accountEditTemplate = `<div><input type=\"text\" data-bind=\"visible: $parent.selected(), value: $parent.entity[$data.field]" />
                                <span data-bind=\"visible: !$parent.selected(),
                                    text: $parent.entity[$data.field],
                                    css: $parent.entity.accountIsValid() === 'True' ? \'passed-validation\' : \'failed-validation\'">
                                </span>
                            </div>`;

    var costCentreEditTemplate = `<div><input type=\"text\" data-bind=\"visible: $parent.selected(), value: $parent.entity[$data.field]" />
                                <span data-bind=\"visible: !$parent.selected(),
                                    text: $parent.entity[$data.field],
                                    css: $parent.entity.costCentreIsValid() === 'True' ? \'passed-validation\' : \'failed-validation\'">
                                </span>
                            </div>`;

These get used in my columnDefs as follows

self.columnDefs = [
        { width: 100, field: 'supplierNo', displayName: 'Supplier No', cellTemplate: supplierEditTemplate },
        { width: 150, field: 'invoiceNo', displayName: 'Invoice No' },
        { width: 150, field: 'costCentre', displayName: 'Cost Centre (Dim1)', cellTemplate: costCentreEditTemplate },
        { width: 200, field: 'glAccount', displayName: 'GL Account (Account)', cellTemplate: accountEditTemplate },
        { width: 100, field: 'amount', displayName: 'Amount' },
        { width: 300, field: 'invoiceDesc', displayName: 'Invoice Description' },
        { width: 150, field: 'accountIsValid', displayName: 'Valid Account' },
        { width: 150, field: 'costCentreIsValid', displayName: 'Valid Cost Centre' },
        { width: 150, field: 'supplierIsValid', displayName: 'Valid Supplier' },
    ];

This works fine but I want to reduce the code duplication by having a helper function that will return the cell template. Something like:

    function GetCellTemplate(fieldName, isValid)
{
    var template = `<div><input type=\"text\" data-bind=\"visible: $parent.selected(), value: $parent.entity[fieldName]" />
                                    <span data-bind=\"visible: !$parent.selected(),
                                        text: $parent.entity[fieldName],
                                        css: isValid === 'True' ? \'passed-validation\' : \'failed-validation\'">
                                    </span>
                                </div>`;

    switch(expression) {
        case 'account':
            return template
            break;
        default:

    }
}

This could be called by:

var accountEditTemplate = GetCellTemplate('account', $parent.entity.accountIsValid());

My problem is when I try this I get ReferenceError:$parent is not defined

What's the best way to solve this copy & paste code growth - I will the same kind of functionality for many fields?

Code updated as per Jason's suggestion - not yet working

function GetCellTemplate(fieldName, validationFieldName) {
    var template = `<div><input type=\"text\" data-bind=\"visible: $parent.selected(), value: $parent.entity[{fieldName}]\" />
                    <span data-bind=\"visible: !$parent.selected(),
                        text: $parent.entity[{fieldName}],
                        css: $parent.entity.{validationFieldName} === 'True' ? \'passed-validation\' : \'failed-validation\'\">
                    </span>
                </div>`;
    }

var editBatchVm = function () {
    var self = this;
    var $loadingIndicator = $('#loading-indicator');

    // Properties
    self.recs = ko.observableArray([]);
    self.selected = ko.observableArray();

    var accountEditTemplate = GetCellTemplate('account', 'accountIsValid');
    var costCentreEditTemplate = GetCellTemplate('costCentre', 'costCentreIsValid');
    var supplierEditTemplate = GetCellTemplate('supplier', 'supplierIsValid');

    self.columnDefs = [
        { width: 100, field: 'supplierNo', displayName: 'Supplier No', cellTemplate: supplierEditTemplate },
        { width: 150, field: 'invoiceNo', displayName: 'Invoice No' },
        { width: 150, field: 'costCentre', displayName: 'Cost Centre (Dim1)', cellTemplate: costCentreEditTemplate },
        { width: 200, field: 'glAccount', displayName: 'GL Account (Account)', cellTemplate: accountEditTemplate },
        { width: 100, field: 'amount', displayName: 'Amount' },
        { width: 300, field: 'invoiceDesc', displayName: 'Invoice Description' },
        { width: 150, field: 'accountIsValid', displayName: 'Valid Account' },
        { width: 150, field: 'costCentreIsValid', displayName: 'Valid Cost Centre' },
        { width: 150, field: 'supplierIsValid', displayName: 'Valid Supplier' },
    ];

Unless I'm mistaken you're just building a string that will later get executed as a template so there's no need to pass in the actual validation object during template construction, you just need the string that represents the validation object. The template itself can reference the $parent context later when it's executed.

var accountEditTemplate = GetCellTemplate('account', 'accountIsValid');

...

function GetCellTemplate(fieldName, validationFieldName) {
    var template = "<div><input type=\"text\" data-bind=\"visible: $parent.selected(), value: $parent.entity[" + fieldName + "]\" />" +
                   "    <span data-bind=\"visible: !$parent.selected()," +
                   "        text: $parent.entity[" + fieldName + "]," +
                   "        css: $parent.entity." + validationFieldName + " === 'True' ? \'passed-validation\' : \'failed-validation\'\">" +
                   "    </span>" +
                   "</div>";
    ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM