Brian Ogden
Brian Ogden

Reputation: 19232

Computed Observable change does not update title attribute in UI (using knockout-bootstrap.js)

Is there anyway to trigger an update of the title attribute of my element in this JS Fiddle:

http://jsfiddle.net/YPXYJ/9/

Note that the tooltip in the data-bind attribute of the element is part of the knockout-bootstrap.js library

<label data-bind="text: copyOtherPartyHelpText()"></label>
<br />
<br />
 <i class="icon-question-sign" data-bind="tooltip: { title: copyOtherPartyHelpText(), placement: 'top', trigger: 'hover' }"></i>
<br />
<br />
<a style="cursor: pointer;" data-bind="click:changeHelpText">Click HERE To Change Label Text</a>

function MyViewModel() {
    this._copyOtherPartyHelpText = ko.observable();
    this.readOnlyView = ko.observable(true);


    this.copyOtherPartyHelpText = ko.computed({
        read: function () {
            var value = this._copyOtherPartyHelpText();

            if (value) {
                return value;
            }

            if (this.readOnlyView()) {
                value = 'Currently Disabled';
            } else {
                value = 'Match/agree to this term.';
            }
            //this makes things even worse, it is an initialization workaround
            //_copyOtherPartyHelpText(value);

            return value;
        },
        write: function (value) {
            this._copyOtherPartyHelpText(value);
        },
        owner: this
    });

    this.changeHelpText = function(){
        this.copyOtherPartyHelpText('help text updated but not tooltip');
    }
}


ko.applyBindings(new MyViewModel());

Upvotes: 0

Views: 1429

Answers (2)

UweB
UweB

Reputation: 4110

The console/browser error log will tell you:

Uncaught ReferenceError: copyOtherPartyHelpText is not defined

You'd have to reference your function calls with this. or the inner function will go looking for window.copyOtherPartyHelpText instead.

I'd recommend using a local variable named self (as they often do in the knockoutjs documentation and tutorials) in your view model, so you can always reference its properties safely and easily from inside, as demonstrated in your modified JSFiddle: http://jsfiddle.net/YPXYJ/3/

function MyViewModel() {
    var self = this;

    // More code here...

    this.changeHelpText = function(){
        alert('changeHelpText called');
        self.copyOtherPartyHelpText('help text and UI updated');
    }
}

EDIT2:

Inside the tooltip binding for the title, you don't call the value accessor but instead reference to the observable function like so:

old:

<i class="icon-question-sign" data-bind="tooltip: { title: copyOtherPartyHelpText(), placement: 'top', trigger: 'hover' }"></i>

new:

<i class="icon-question-sign" data-bind="tooltip: { title: copyOtherPartyHelpText, placement: 'top', trigger: 'hover' }"></i>

See: http://jsfiddle.net/YPXYJ/11/

Upvotes: 3

Xion Dark
Xion Dark

Reputation: 3434

You needed the "this." when reffering to 'this._copyOtherPartyHelpText()' and 'this.copyOtherPartyHelpText()'

here you go http://jsfiddle.net/FtMdZ/2/

ko.observable();
    this.readOnlyView = ko.observable(true);


    this.copyOtherPartyHelpText = ko.computed({
        read: function () {
            var value = this._copyOtherPartyHelpText();

            if (value) {
                return value;
            }

            if (this.readOnlyView()) {
                value = 'Currently Disabled';
            } else {
                value = 'Match/agree to this term.';
            }
            //this makes things even worse, it is an initialization workaround
            //_copyOtherPartyHelpText(value);

            return value;
        },
        write: function (value) {
            this._copyOtherPartyHelpText(value);
        },
        owner: this
    });

    this.changeHelpText = function(){
        alert('changeHelpText called');
        this.copyOtherPartyHelpText('help text and UI updated');
    }
}


ko.applyBindings(new MyViewModel());

Upvotes: 2

Related Questions