Question

When called via afterRender, $(element).offset().top == 0, however, calling offset().top on the element after applyBindings results in the (expected) value 80.

Why is the first one not 80? Is there anyway to find the expected value (80) in afterRender?

Template

<div data-bind="foreach: {data: entries, afterRender: render}">
    <div data-bind="text: name, attr: { 'id': name }"> </div>
</div>

Javascript

var ViewModel = function() {
    this.entries = [
        { name: "one" },
        { name: "two"},
        { name: "three"},
        { name: "four"},
        { name: "five"}
    ];
    this.render = function(element, data) {
        if (data.name == "five")
            alert($(element).offset().top);
    }
 };

ko.applyBindings(new ViewModel());
alert($("#five").offset().top);

Example

jsFiddle

Was it helpful?

Solution

It looks like the element you're referring to in

$(element).offset().top

is not actually a DOM object, it's a Knockout object. It contains some other data besides the HTML. The following yields the correct result, because it's referring to the DOM object:

this.render = function(element, data) {
    if (data.name == "five") {
        console.log( $('#five').offset().top );
    }
}

I haven't used knockout before, so there may be a better way of accessing it, but I found that the object you're trying to access is actually in the element, it's just one level deep in the object, so that the following also works:

this.render = function(element, data) {
    if (data.name == "five") {
        console.log( $( element[1] ).offset().top );
    }
}

(Note that I'm using console.log for cleaner debugging. I prefer to not have all those alerts popping up.)

Here's the updated fiddle

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