2017-10-26 1 views
1

Ich habe ein ko.observable in meinem Viewmodel, das an einen Eingang angehängt ist. Wenn der Benutzer den Wert dieser Eingabe (pro Zeichen) ändert, führe ich einen AJAX-Aufruf aus, der Vorschläge vom Backend herunterlädt.Wie ignoriere ich Änderungen, die nicht vom Benutzer vorgenommen wurden?

Wenn der Benutzer einen der Vorschläge auswählt, möchte ich die Eingabe mit dem gewählten Wert füllen, aber ohne den AJAX-Anruf zu senden. Aber das Setzen des beobachtbaren Wertes löst immer noch eine Ereignis- und Aufruffunktion aus, die an die textInput Bindung gebunden ist.

Wie kann ich den beobachtbaren Wert setzen, ohne textInput auszulösen?

Beispielcode:

var name = ko.observable(); 
name.subscribe(nameChanged); 

var nameChanged = function() { 
    someService.post(name(), success, failure); 
} 

var someAction = function() { 

    name("Test"); // I don't want to trigger AJAX call here 
} 
<input type="text" data-bind="textInput: name" /> 

Antwort

1

eine weitere Option ist eine berechnete beobachtbaren als Vermittler zu verwenden. Die Ajax-Funktion kann im Write-Ereignis des Berechneten so auslösen, dass direkte Schreibvorgänge auf den Observablen sie umgehen.

function viewModel(){ 
 
    var self = this; 
 
    
 
    self.realName = ko.observable('test'); 
 
    
 
    self.Name = ko.computed({ 
 
     read: function(){ 
 
      return self.realName(); 
 
     }, 
 
     write: function(value){ 
 
      self.realName(value); 
 
      nameChanged(value); 
 
     } 
 
    }); 
 
    
 
    function nameChanged(newName) { 
 
     console.log("name changed:", newName); 
 
    } 
 
    
 
    self.modifyName = function(){ 
 
     self.realName(self.realName() + 'z'); 
 
    } 
 
} 
 

 
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 
 

 

 
<input type="text" data-bind="textInput: Name" /> 
 
<br /> 
 
<button data-bind="click: modifyName">Modify</button>

+0

Ich endete mit zwei Observablen: name und displayName. Ich habe auch Änderungen abonniert, und wenn man sich ändert * und * ein anderer ist anders, aktualisiert der erste den zweiten. Aber jetzt weiß ich, woher die Änderung kam: Wenn displayName den Namen aktualisiert - vom Benutzer, und wenn der Name den Namen aktualisiert, aus dem Code. Ihre Lösung ist jedoch eleganter. – Spook

0

gesetzt Vielleicht eine bestimmte CSS-Klasse auf dem Feld nach der Auswahl getroffen wird und ein gewisse Logik um den Ajax-Aufruf gesetzt zu überprüfen, ob das Feld mit der CSS-Klasse hat.

0

Anstatt das Änderungsereignis der Observable zu abonnieren, können Sie stattdessen Ihren Ajax-Aufruf mit dem Änderungsereignis des ui-Elements verknüpfen. Sie erhalten würden von name.subscribe(nameChanged); befreien und fügen Sie ein event Bindung:

data-bind="textInput: name, event: { changed: nameChanged }" 
+1

Dies ist nicht so einfach. Ich muss diesen AJAX-Aufruf nach jeder Wertänderung auslösen, z. nach jedem Tastendruck (einschließlich Einfügen, Maus-Text ziehen etc.), weil ich Vorschläge für die automatische Vervollständigung für diese Eingabe anfordert. Während 'changed' nur aufgerufen wird, wenn die Eingabe den Fokus verliert ... – Spook

0

Eine „altmodische“ Art und Weise, die funktioniert, ist aber nicht wirklich elegant ist, um vorübergehend das Abonnement verfügen und es dann wieder anbringen:

var myName = ko.observable(); 
 
var nameSub = myName.subscribe(nameChanged); 
 

 
function nameChanged(newName) { 
 
    console.log("name changed:", newName); 
 
} 
 

 
function changeWithoutLog() { 
 
    nameSub.dispose(); 
 
    myName("Test"); 
 
    nameSub = myName.subscribe(nameChanged); 
 
} 
 

 

 
ko.applyBindings({ name: myName });
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 
 

 

 
<input type="text" data-bind="textInput: name" /> 
 
<button data-bind="click: changeWithoutLog">change without post</button>

Verwandte Themen