32 votes

knockout.js accéder à viewModel dans une fonction javascript en dehors de la portée de viewModel

Je me demande si je peux accéder au viewModel principal de knockout.js à partir d'une méthode située en dehors de la portée du viewModel lui-même. Prenons cet exemple :

function Employee(data) {
  var self = this;
  ko.mapping.fromJS(data, {}, this);
}

function EmployeeViewModel() {
  var self = this;
  this.employees = ko.observableArray([]);

  this.loadEmployees = function() {
    var mappedEmployees= $.map(JSON.parse(data.value), function(item) { return new Employee(item) });
    self.employees (mappedEmployees);
  }
}

// here's the part I'm curious about
$(document).ready(function() {
  ko.applyBindings(new EmployeeViewModel());  

  $("#myLink").click(function() {
     // is there some way to get back into the ko context here?
     // like with ko.dataFor or ko.contextFor?
  });
}

51voto

Jason Goemaat Points 7211

Vous pouvez toujours y accéder en stockant votre modèle de vue dans une variable à laquelle vous pouvez accéder, la variable module et modèles de modules révélateurs sont sympathiques, mais vous pouvez simplement les stocker dans un objet qui n'entrera pas en conflit avec d'autres noms ('my' ici) :

my = { viewModel: new EmployeeViewModel() };
ko.applyBindings(my.viewModel);

Vous avez eu la bonne idée, il suffit de prendre l'élément comme argument de votre fonction click et de passer la propriété cible à ko.dataFor ou ko.contextFor ( jsfiddle ):

$(document).ready(function() {
    my.vm = new EmployeeViewModel();
    ko.applyBindings(my.vm);
    $('button').on('click', function(e) {
        alert('you clicked on employee ' + ko.contextFor(e.target).$data.name() +
             ' also known as ' + ko.dataFor(e.target).name());
    });
});​

Au lieu d'utiliser jQuery pour lier l'événement de clic, vous pouvez toujours utiliser la liaison par clic de Knockout qui transmet les données actuelles du modèle comme premier paramètre et l'événement comme second paramètre ( jsfiddle ):

function EmployeeViewModel() {
  var self = this;

  // skipped some of your code

  this.clickedOnEmployee = function(model, event) {
    // assuming your Employee has a name observable
    alert('You clicked on employee ' + model.name());
  };
}

Dans votre html (le $Root est votre modèle de vue de base, vous n'en auriez pas besoin si votre fonction clickedOnEmployee était sur vos objets employés) :

<ul data-bind="foreach: employees">
    <li>
        <span data-bind="text: name"></span>
        <button data-bind="click: $root.clickedOnEmployee">show</button>
    </li>
</ul>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X