0

I am having problems creating a custom field within KnockOutJS ViewModel.

HTML

<table class="table table-striped">
    <thead><tr>
        <th>name</th><th>abb</th><th>combo</th>
    </tr></thead>
    <tbody data-bind="foreach: clients"><tr>
        <td data-bind="text: Name"></td>
        <td data-bind="text: Abbreviation"></td>
        <td data-bind="text: NameAbbreviation"></td>
    </tr></tbody>
</table>

JS CODE

function ClientModel() {
    var self = this;
// Bind all data to UI < -- working
    self.clients = ko.observableArray(data);
// Not working        
    self.NameAbbreviation = ko.computed(function () {
        return self.Name + " " + self.Abbreviation;
    })
};
ko.applyBindings(new ClientModel());

JOSN DATA (working)

{"ID":14,"GUID":"c999b888-9566-2e50-a23c-07913d389f99","Name":"Aaron46","Abbreviation":"Corporate Customer","Website":"www.ts2mkg3d0oomo.com","Email":"[email protected]","Active":true,"ModifyDate":"1959-02-14T15:47:53.43","CreatedDate":"1987-09-26T00:37:13.52","CreatedDateString":"9/26/1987","ModifyDateString":"2/14/1959","Status":0,"Message":null},{"ID":443,"GUID":"12c60aa5-03f1-509c-5d49-9caf696c44ce","Name":"Abigail","Abbreviation":"Technical","Website":"www.wsfj97qccj1.com","Email":"[email protected]","Active":true,"ModifyDate":"2007-02-01T06:01:11.3","CreatedDate":"1963-05-11T01:23:21.11","CreatedDateString":"5/11/1963","ModifyDateString":"2/1/2007","Status":0,"Message":null},{"ID":136,"GUID":"63c65e85-0f9b-1f7c-328a-ca253a4881d1","Name":"Adrienne","Abbreviation":"Accounting","Website":"www.ixug6k4eqkjmnr.com","Email":"[email protected]","Active":false,"ModifyDate":"2000-12-14T08:11:31.83","CreatedDate":"1980-05-03T03:25:02.34","CreatedDateString":"5/3/1980","ModifyDateString":"12/14/2000","Status":0,"Message":null}

I am able to bind all the data with no issues, when I do not create a custom view field!

When I try to create NameAbbreviation custom field, I get an error

Error: Unable to parse bindings.
Message: ReferenceError: NameAbbreviation is not defined;
Bindings value: text: NameAbbreviation

I understand the error, as KO cannot find NameAbbreviation in the view.

How do I get this custom view NameAbbreviation to be used/seen by KO?

2
  • Are Name and Abbreviation ko.observables? If so, might try: return self.Name() + " " + self.Abbreviation(); Commented Jan 23, 2013 at 3:20
  • That did not work: Object #<ClientModel> has no method 'Name' .. Commented Jan 23, 2013 at 3:22

2 Answers 2

3

When you are in the foreach loop, the scope is the array item that you are looping on. Your view model has NameAbbreviation defined at the root level rather than on each item.

There are several approaches that you could take here.

The simplest is to just create a simple function on your view model that returns the formatted string and bind against it using $root or $parent.

function ClientModel() {
    this.clients = ko.observableArray(data);
    this.NameAbbreviation = function (item) {
        return item.Name + " " + item.Abbreviation;
    };
};

Then, in your UI bind like:

<tbody data-bind="foreach: clients">
    <tr>
        <td data-bind="text: Name"></td>
        <td data-bind="text: Abbreviation"></td>
        <td data-bind="text: $root.NameAbbreviation($data)"></td>
    </tr>
</tbody>

Otherwise, you could consider creating a "item" constructor function that adds the NameAbbreviation and then sending each raw data item through the constructor.

Another option would be to use the mapping plugin.

Sign up to request clarification or add additional context in comments.

4 Comments

self.FullName = ko.computed(function (item) { return item.Name + " " + item.Abbreviation; }) <-- ADDED the ko.computed However, I am getting ** Cannot read property 'Name' of undefined**
If this lives on the main view model and is returning the value for each item, then you would not want this to be a ko.computed. It can just be a normal function.
Ok .. now I am getting a literal string: "function (item) { return item.Abbreviation() + " " + item.Active(); }" returned
I had an error in the answer. Updated. Need to pass the data, as KO only passes data for handlers (click/event).
0
// use () with item.Name and item.Abbreviation as below

this.NameAbbreviation = function (item) {
        return item.Name() + " " + item.Abbreviation();
    };

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.