Search code examples
javascriptknockout.jsknockout-2.0knockout-3.0knockout-templating

Passing parameter from Knockout template to modal


In this code example I'm looking for a way to pass parameters from data in Knockout's template into Knockout's data-bind that should ultimately appear in modal window.

The result should be a modal window that displays a participant's name based on which participant is to be deleted.

Right now I have to enter the names manually, what should be done to have them automatically binded?

var viewModel = function() {
  this.showModal = function() {
    console.log("Showing modal");
    $('#modal').modal('show');
  }
  this.buyer = {
    name: 'Franklin',
    credits: 250
  };
  this.seller = {
    name: 'Mario',
    credits: 5800
  };
};
ko.applyBindings(new viewModel);
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" rel="stylesheet" />
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<div data-bind="template: { name: 'person-template', data: buyer }"></div>
<div data-bind="template: { name: 'person-template', data: seller }"></div>

<script type="text/html" id="person-template">
  <h3 data-bind="text: name"></h3>
  <p>Credits: <span data-bind="text: credits"></span>
  </p>
  <button data-bind="click: $root.showModal" class="btn">Delete</button>
</script>

<div id="modal" class="modal fade" tabindex="-1" role="dialog">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span>
        </button>
        <h4 class="modal-title">Delete item</h4>
      </div>
      <div class="modal-body">
        <p>Really delete Franklin?</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
        <button type="button" class="btn btn-primary">Delete</button>
      </div>
    </div>
    <!-- /.modal-content -->
  </div>
  <!-- /.modal-dialog -->
</div>
<!-- /.modal -->


Solution

  • First, you need to make the name something KO manages:

    <p>Really delete <span data-bind="text: deleting"></span>?</p>
    

    Give yourself an observable for that in your view model:

    this.deleting = ko.observable(null);
    

    Then update showModal to update an observable:

    this.showModal = function(deleting) {
      this.deleting(deleting.name);
      console.log("Showing modal");
      $('#modal').modal('show');
    };
    

    Then, since you're using $root.showModal, this will be incorrect, but we can addres that with bind:

    <button data-bind="click: $root.showModal.bind($root)" class="btn">Delete</button>
    

    Live Example:

    var viewModel = function() {
      this.showModal = function(deleting) {
        this.deleting(deleting.name);
        console.log("Showing modal");
        $('#modal').modal('show');
      };
      this.deleting = ko.observable(null);
      this.buyer = {
        name: 'Franklin',
        credits: 250
      };
      this.seller = {
        name: 'Mario',
        credits: 5800
      };
    };
    ko.applyBindings(new viewModel);
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" rel="stylesheet" />
    <link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    <div data-bind="template: { name: 'person-template', data: buyer }"></div>
    <div data-bind="template: { name: 'person-template', data: seller }"></div>
    
    <script type="text/html" id="person-template">
      <h3 data-bind="text: name"></h3>
      <p>Credits: <span data-bind="text: credits"></span>
      </p>
      <button data-bind="click: $root.showModal.bind($root)" class="btn">Delete</button>
    </script>
    
    <div id="modal" class="modal fade" tabindex="-1" role="dialog">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span>
            </button>
            <h4 class="modal-title">Delete item</h4>
          </div>
          <div class="modal-body">
            <p>Really delete <span data-bind="text: deleting"></span>?</p>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
            <button type="button" class="btn btn-primary">Delete</button>
          </div>
        </div>
        <!-- /.modal-content -->
      </div>
      <!-- /.modal-dialog -->
    </div>
    <!-- /.modal -->