Zoltán Tamási
Zoltán Tamási

Reputation: 12809

A template for a query viewmodel

I have let's say a viewmodel for querying products, similar to this.

function ProductQueryModel() {
  this.publishedSince = ko.observable();
  this.nameContains = ko.observable();
  ...
  this.SubmitQuery = function() { 
    // what shall I do? ...
  }
}

Now I create a template for this viewmodel, so that I can reuse is in the application.

<template id="productquerymodel-template">
  <form>
    ...
    <input type="text" data-bind="textInput: nameContains"/>
    ...
    <button type="submit" data-bind="click: SubmitQuery">Submit</button>
  </form>
</template>

I intentionally didn't use the submit binding, because in most cases I want frm submission only on button click to prevent accidental submission for example.

Here I have a problem with submitting the form. The method which is bound to the submit button's click event doesn't make sense inside the query model, because the query model itself has no idea what to do when querying. It should be outside of the query viewmodel, because the method implementation depends on what exactly is using the query model.

But on the other hand, containing the submit button inside the template makes sense, because it's part of the form.

A way would be to define the click binding inside the template like $parent.SubmitQuery.bind($parent), but then I would restrict the consumer of the template to always define a SubmitQuery function on the parent of the query model, which is not a nice solution I think.

Does anybody know about an existing practice for such scnearios, or any other ideas which might help in these situations?

Upvotes: 0

Views: 70

Answers (1)

Dennis W
Dennis W

Reputation: 961

Here is how I would accomplish that.

Template file:

<script type="text/html" id="productquerymodel-template">
  <form>
    <input type="text" data-bind="textInput: nameContains"/>
    <button type="submit" data-bind="click: SubmitQuery">Submit</button>
  </form>
</script>

<script>
  function ProductQueryModel() {
    var self = this;
    self.publishedSince = ko.observable();
    self.nameContains = ko.observable();
    self.SubmitQuery = function () {
      // Do nothing by default
    };
  }
</script>

HTML page:

<div data-bind="template: { 
  name: 'productquerymodel-template',
  data: ProductQuery 
}"></div>

<script>
  // This would be your main view model for the page
  function MainViewModel() {
    var self = this;
    self.ProductQuery = new ProductQueryModel()
  }

  // Initialize an instance of the view model
  var vm = new MainViewModel();

  // Insert your page specific SubmitQuery function here
  vm.ProductQuery.SubmitQuery = function () {
    alert('Page specific stuff');
  };

  ko.applyBindings(vm);
</script>

Fiddle link: https://jsfiddle.net/dw1284/fopwgf4a/

Upvotes: 1

Related Questions