1

I am building a set of filters in Knockout and want to store the current filter settings on an object. When any is changed, I need to filter my data.

The subscription to self.filter is never triggered, even though the Filter object changes. Can this be observed?

var Filter = function() {
    this.gender = ko.observable("");
    this.role = ko.observable("");
};
viewModel = function() {
  var self = this;
  self.filter = ko.observable(new Filter());
  self.filter.subscribe(function(obj) {
    console.log("The filter has been modified! (this line never runs)", obj);
  });
  
  self.output = function() { console.log("Gender", self.filter().gender(), "Role", self.filter().role());}
};

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


<select data-bind="value: filter().gender">
  <option value="">Male or Female</option>
  <option value="M">Male</option>
  <option value="F">Female</option>
</select>
<select data-bind="value: filter().role">
  <option value="">Any</option>
  <option value="Student">Student</option>
  <option value="Guest">Guest</option>
</select>

<p>
<button data-bind="click: output">
Output Filter values (to prove the object is updated)
</button>
</p>

1 Answer 1

1

The filter does not change, which is why the subscription function doesn't get hit. The gender and role observables of the filter do change, however.

self.filter().gender.subscribe() will get called when the gender dropdown changes. The only way self.filter.subscribe() will get called is if you change the value of the filter itself, for example self.filter(new Filter()).

There is not much point to making filter observable if all it is going to have is observable properties (unless you are going to create new filters like in the example above instead of just changing its properties).

Sign up to request clarification or add additional context in comments.

4 Comments

Be careful about creating lots of subscriptions though (they hang around and will use memory - a SPA can be impacted heavily over time) - in theory you'd need to subscribe when filter does change - at that point you should probably also dispose the subscriptions from the previous filter value.
@JamesThorpe Oh! I was looking for a memory leak earlier, will check the other subscriptions.
@PeterB If your page lives for any non-trivial length of time, it's pretty important to ensure that the return value from every subscribe is stored somewhere and a corresponding call to dispose is used at the right time.
@Paul Abbott Thanks, that makes more sense. What is a better way to architect this code - should I keep observables on Filter (necessary to bind to the HTML I believe), or move everything potentially to the viewModel? As there will be another 10+ filters I'm looking for a clean way to address them all and apply all which are set to the data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.