C.J.
C.J.

Reputation: 6879

How to create a compound property and use it in a jQuery template?

I'd like to be able to create a JS object that has a field that combines existing fields in the object together, but I think I have a context problem for "this" that I'm not sure how to solve.

Here's what I'm trying to do:

function Person(firstName, lastName)
{
    this.FirstName = firstName;
    this.LastName  = lastName;

    this.FullName = function ()
    {
        return this.FirstName + " " + this.LastName;
    }
}

I wish to use FullName is a jquery Template, but haven't had luck.

<script type="text/x-jquery-tmpl" id="tmplImg">
    {{each people}}
        <li>
            ${FullName}
        </li>
    {{/each}}
</script>

I think it can be done somehow because the knockout.js library is able to accomplish it somehow as shown in this tutorial (Step 4).

http://learn.knockoutjs.com/#/?tutorial=templates

Upvotes: 1

Views: 211

Answers (4)

Prusprus
Prusprus

Reputation: 8065

Using your script, I've been able to call FullName and retrieve the full name:

var pers = new Person("first", "last");
alert(pers.FullName());

Is this what you were trying to accomplish?

Upvotes: 0

J. Holmes
J. Holmes

Reputation: 18546

IAbstractDownvoteFactory's answer is a solid answer, and definately deserves an upvote, but I just want to introduce one layer of abstraction beyond his/her answer:

Consider the following helper:

function createBoundMethodsFor(obj) {
    var proto = obj.constructor.prototype
    for(var method in proto)
        if(typeof(proto[method]) === 'function')
            obj[method] = function() { return proto[method].apply(obj, arguments); }
}

Then lets look at constructor for person again:

function Person(firstName, lastName) {
    this.FirstName = firstName;
    this.LastName = lastName;

    createBoundMethodsFor(this)
}

Person.prototype.FullName = function() {
    return this.FirstName + ' ' + this.LastName;
}

This helper loops through all of the functions in the object's prototype, and builds bound closures for each one, and overrides them as instance methods, but they just proxy through to the prototype method. Using a helper like that might make your life a lot easier as the number of methods on an object become non-trivial.

But be aware that bound methods like this lead to interesting results that you might not expect, for example :

var john = new Person("John", "Doe")
var jane = new Person("Jane", "Doe")
var bound = john.FullName

bound() // John Doe
bound.call(jane) // John Doe   (Not Jane like you might expect)

var unbound = john.constructor.prototype.FullName;
unbound() // null
unbound.call(john) // John Doe
unbound.call(jane) // Jane Doe

Fiddle Here

Upvotes: 0

Joe
Joe

Reputation: 82654

Working Demo:

function Person(firstName, lastName) {
    this.FirstName = firstName;
    this.LastName = lastName;
    var self = this;
    this.FullName = function() {
        return self.FirstName + ' ' + self.LastName;
    }
}

Upvotes: 2

Jeremy
Jeremy

Reputation: 792

I'm in no way an expert on jQuery Templates, but this works in my tests:

<script id="myTemplate" type="text/x-jquery-tmpl"> 
    ${$data.getFullName()}
</script>

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

Person.prototype.getFullName = function() {
    return this.firstName + " " + this.lastName;
};

var person = new Person("John", "Doe");

$("#myTemplate").tmpl(person).appendTo("#myOutput");

Upvotes: 0

Related Questions