Je me demande si je peux accéder au viewModel principal knockout.js à partir d'une méthode en dehors de la portée du viewModel lui-même. Prenez 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?
});
}
Vous pouvez toujours y accéder simplement en stockant votre modèle de vue dans une variable à laquelle vous pouvez accéder, les module et modèles de module révélateur sont agréables, mais vous pouvez simplement le stocker dans un objet qui n'entrera pas en conflit avec d'autres noms ('mon' ici):
my = { viewModel: new EmployeeViewModel() };
ko.applyBindings(my.viewModel);
Vous avez eu la bonne idée, il vous suffit de prendre l'élément comme argument pour votre fonction de clic 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 click, vous pouvez toujours utiliser la liaison de clic Knockout , qui transmet les données du modèle actuel comme premier paramètre et l'événement comme deuxième 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 (la racine $ est votre modèle de vue de base, vous n'en auriez pas besoin si votre fonction clickedOnEmployee était sur vos objets Employee):
<ul data-bind="foreach: employees">
<li>
<span data-bind="text: name"></span>
<button data-bind="click: $root.clickedOnEmployee">show</button>
</li>
</ul>