WhatsInAName
WhatsInAName

Reputation: 724

knockout js - access variable inside object

I am trying to create a computed variable (RateDisplay) based on what the user enters(MinRate, MaxRate if VRAChecked is true, else FlatRate) that is defined as an observable. I have an object (product) as part of the viewmodel like the following:

var viewModel = new function () {

var self = this;
self.Id = ko.observable();

self.product = {
  Id: ko.observable(),
  Name: ko.observable(),
  VRAChecked: ko.observable(false),
  MinRate: ko.observable(),
  MaxRate: ko.observable(),
  FlatRate: ko.observable(),
  RateDisplay: ko.computed(function() {
    if (self.product.VRAChecked())
      {
        return self.product.MinRate() + "-" + self.product.MaxRate();
      }
      else
      {
        return self.product.FlatRate();
      }
  }, this),

  PercentageGoal: ko.observable()
};

  };//viewmodel ends

The problem is, I get this js error: "self.product is undefined" at the line

  if (self.product.VRAChecked())

I understand that, that is probably because the object is still being created.

So, how do I create the computed variable (RateDisplay)? I need it to be an element of that object (product).

Upvotes: 0

Views: 1951

Answers (1)

Buzinas
Buzinas

Reputation: 11733

The problem is that you're creating the computed before the other product properties are even created, and then, they are not defined yet.

Try to create it only after the product declaration, and it will work like a charm.

Take a look at the example below:

var viewModel = function() {
  var self = this;
  self.Id = ko.observable();
  self.product = {
    Id: ko.observable(),
    Name: ko.observable(),
    VRAChecked: ko.observable(false),
    MinRate: ko.observable(),
    MaxRate: ko.observable(),
    FlatRate: ko.observable(),
    PercentageGoal: ko.observable()
  };
  
  self.product.RateDisplay = ko.computed(function() {
      if (self.product.VRAChecked()) {
        return self.product.MinRate() + "-" + this.product.MaxRate();
      } else {
        return self.product.FlatRate();
      }
    }, self)
}

ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<div>
  <label>Min Rate <input type="textbox" data-bind="value: product.MinRate"></label>
  <label>Max Rate <input type="textbox" data-bind="value: product.MaxRate"></label>
</div>
<div>
  <label>Flat Rate <input type="textbox" data-bind="value: product.FlatRate"></label>
</div>
<div>
  <label><input type="checkbox" data-bind="checked: product.VRAChecked"> VRA Checked</label>
</div>
<div>Display: <span data-bind="text: product.RateDisplay"></span></div>

Upvotes: 1

Related Questions