Je construis une interface utilisateur d'autorisations, j'ai une liste d'autorisations avec une liste de sélection à côté de chaque autorisation. Les permissions sont représentées par un tableau d'objets observables qui sont liés à une liste de sélection:
<div data-bind="foreach: permissions">
<div class="permission_row">
<span data-bind="text: name"></span>
<select data-bind="value: level, event:{ change: $parent.permissionChanged}">
<option value="0"></option>
<option value="1">R</option>
<option value="2">RW</option>
</select>
</div>
</div>
Maintenant, le problème est le suivant: l'événement de modification est déclenché lorsque l'interface utilisateur se remplit pour la première fois. J'appelle ma fonction ajax, j'obtiens la liste des autorisations, puis l'événement est déclenché pour chacun des éléments d'autorisation. Ce n'est vraiment pas le comportement que je souhaite. Je souhaite qu'il soit déclenché uniquement lorsqu'un utilisateur sélectionne vraiment une nouvelle valeur pour l'autorisation dans la liste de sélection , comment puis-je faire cela?
la source
select
élément. Cependant, même lorsque la valeur initiale de la sélection correspond à l'une des options, cela déclenche toujours l'change
événement. Lorsque j'ai implémenté ce simpleif
bloc dans le gestionnaire, tout fonctionnait comme prévu. Essayez d'abord cette méthode. Merci, @Sarath!Ce n'est qu'une supposition, mais je pense que cela se produit parce que
level
c'est un nombre. Dans ce cas, lavalue
liaison déclenchera unchange
événement à mettre à jourlevel
avec la valeur de chaîne. Vous pouvez donc résoudre ce problème en vous assurant qu'illevel
s'agit d'une chaîne pour commencer.De plus, la manière la plus "Knockout" de faire ceci est de ne pas utiliser de gestionnaires d'événements, mais d'utiliser des observables et des abonnements. Créez
level
un observable, puis ajoutez-y un abonnement, qui sera exécuté à chaquelevel
modification.la source
Voici une solution qui peut aider avec ce comportement étrange. Je n'ai pas pu trouver de meilleure solution que de placer un bouton pour déclencher manuellement l'événement de modification.
EDIT: Peut-être qu'une liaison personnalisée comme celle-ci pourrait aider:
ko.bindingHandlers.changeSelectValue = { init: function(element,valueAccessor){ $(element).change(function(){ var value = $(element).val(); if($(element).is(":focus")){ //Do whatever you want with the new value } }); } };
Et dans votre attribut de liaison de données, ajoutez:
la source
J'utilise cette liaison personnalisée (basée sur ce violon de RP Niemeyer, voir sa réponse à cette question), qui s'assure que la valeur numérique est correctement convertie de chaîne en nombre (comme suggéré par la solution de Michael Best):
Javascript:
ko.bindingHandlers.valueAsNumber = { init: function (element, valueAccessor, allBindingsAccessor) { var observable = valueAccessor(), interceptor = ko.computed({ read: function () { var val = ko.utils.unwrapObservable(observable); return (observable() ? observable().toString() : observable()); }, write: function (newValue) { observable(newValue ? parseInt(newValue, 10) : newValue); }, owner: this }); ko.applyBindingsToNode(element, { value: interceptor }); } };
Exemple HTML:
<select data-bind="valueAsNumber: level, event:{ change: $parent.permissionChanged }"> <option value="0"></option> <option value="1">R</option> <option value="2">RW</option> </select>
la source
Si vous utilisez une valeur observable au lieu d'une valeur primitive, la sélection ne déclenchera pas d'événements de modification lors de la liaison initiale. Vous pouvez continuer à vous lier à l'événement de modification, plutôt que de vous abonner directement à l'observable.
la source
Rapide et sale, utilisant un simple drapeau:
var bindingsApplied = false; var ViewModel = function() { // ... this.permissionChanged = function() { // ignore, if flag not set if (!flag) return; // ... }; }; ko.applyBindings(new ViewModel()); bindingsApplied = true; // done with the initial population, set flag to true
Si cela ne fonctionne pas, essayez d'encapsuler la dernière ligne dans un setTimeout () - les événements sont asynchrones, donc peut-être que le dernier est toujours en attente lorsque applyBindings () est déjà retourné.
la source
J'ai eu un problème similaire et je viens de modifier le gestionnaire d'événements pour vérifier le type de la variable. Le type n'est défini qu'une fois que l'utilisateur a sélectionné une valeur, pas lors du premier chargement de la page.
self.permissionChanged = function (l) { if (typeof l != 'undefined') { ... } }
Cela semble fonctionner pour moi.
la source
utilisez ceci:
this.permissionChanged = function (obj, event) { if (event.type != "load") { } }
la source
Essaye celui-là:
self.GetHierarchyNodeList = function (data, index, event) { debugger; if (event.type != "change") { return; } } event.type == "change" event.type == "load"
la source
Si vous utilisez Knockout, utilisez la fonctionnalité clé de Knockout de fonctionnalité observable.
Utilisez la
ko.computed()
méthode et faites et déclenchez un appel ajax dans cette fonction.la source