mejobloggs
mejobloggs

Reputation: 8156

Computed variable with properties in KnockoutJS?

Can a computed variable have properties?

For example, I have user input of room dimensions, and I want them to be put through some scaling logic that something else on the screen needs to read from.

When either Width, Height, or Depth is updated, I need to update ALL of ScaledRoom W/H/D, as there's going to be a fair bit of logic that changes all three values depending on situations.

var MyViewModel = function () {
    var self = this;

    //Room Dimensions
    self.RoomWidth = ko.observable();
    self.RoomHeight = ko.observable();
    self.RoomDepth = ko.observable();


    //basic psuedocode of what I want to achieve... Haven't put in the previously mentioned logic in order to keep it simple
    self.ScaledRoom = ko.computed(function () {
        this.Width = self.RoomWidth * 10;
        this.Height = self.RoomHeight * 15;
        this.Depth = self.RoomDepth * 11;
        return this;
    });

};

In the html, i'd like to be able to databind to ScaledRoom.Width() for example

What's the best way to do this?

Upvotes: 0

Views: 218

Answers (1)

Wayne Ellery
Wayne Ellery

Reputation: 7958

Create a separate model for ScaledRoom:

var ScaledRoom  = function () {
    var self = this;

    self.Width = ko.observable(0);
    self.Height = ko.observable(0);
    self.Depth = ko.observable(0);
}

Then you can have a computed observable which changes the values on the object. The if statement first checks if there is an object. If there is no object then it's created.

var ViewModel = function () {
    var self = this;

    self.RoomWidth = ko.observable(0);
    self.RoomHeight = ko.observable(0);
    self.RoomDepth = ko.observable(0);

    self.ScaledRoom = ko.computed(function () {
        var scaledRoom;
        if (!self.ScaledRoom) {
            scaledRoom = new ScaledRoom();
        }
        else {
            scaledRoom = self.ScaledRoom();
        }

        scaledRoom.Width(self.RoomWidth() * 10);
        scaledRoom.Height(self.RoomHeight() * 15);
        scaledRoom.Depth(self.RoomDepth() * 11);

        return scaledRoom;
    });
};

View:

<div>
    Room Width: <input type="text" data-bind="value: RoomWidth"/>
</div>
<div>
    Room Height: <input type="text" data-bind="value: RoomHeight"/>
</div>
<div>
    Room Depth: <input type="text" data-bind="value: RoomDepth"/>
</div>
<div data-bind="with: ScaledRoom">
    <div data-bind="text: Width"></div>
    <div data-bind="text: Height"></div>
    <div data-bind="text: Depth"></div>
</div>

Demo: http://jsfiddle.net/bmk3eo4m/

Upvotes: 1

Related Questions