2014-07-17 9 views
12

Ich kann nicht herausfinden, wie man eine Knockout-Klickbindung erstellt, die den WertAccessor nur ausführt, wenn ein JavaScript-Bestätigungsdialog wahr zurückgibt.Knockout Klickbindung mit Javascript bestätigen

Es ist wohl so etwas wie folgt aussehen:

<a data-bind="confirmClick: { message: 'Are you sure?', click: someMethod }">Confirmable link</a> 

Intern wird die confirmClick Bindung würde wie etwas tun:

if (confirm(message)) { 
    click(); 
} 

Ich weiß, ich könnte mit bekommen, um dieses den confirm(...) Code, indem sie tun in meinem viewModel, aber das scheint nicht der geeignete Ort, um diese Art von Code zu setzen. Ich könnte wahrscheinlich auch so weit gehen, diese Art von Dialog mit jQueryUI oder Bootstrap zu bestätigen, aber ich möchte etwas, das ich einfach in ein Projekt einfügen kann.

Ich habe das internets ohne Glück abgekocht .. ich auf dem Quellcode für Knockout des Click-Ereignis (https://github.com/knockout/knockout/blob/master/src/binding/defaultBindings/event.js) selbst gesucht, aber es sieht nicht freundlich ...

überhaupt Hilfe würde sehr geschätzt werden!

Antwort

18

Sie benötigen eine individuelle confirmClickbinding handler zu schaffen, die Ihre Nachricht und Ihre Click-Handler nimmt und wickeln um die Bestätigungslogik:

ko.bindingHandlers.confirmClick = { 
    init: function(element, valueAccessor, allBindings, viewModel) { 
     var value = valueAccessor(); 
     var message = ko.unwrap(value.message); 
     var click = value.click; 
     ko.applyBindingsToNode(element, { click: function() { 
      if (confirm(message)) 
       return click.apply(this, Array.prototype.slice.apply(arguments)); 
     }}, viewModel); 
    } 
} 

Und Sie können Sie es, wie Sie beschrieben haben:

<a data-bind="confirmClick: { message: 'Are you sure?', click: someMethod }"> 
    Confirmable link</a> 

Demo JSFiddle.

Hinweis: Sie benötigen nur die click.apply Magie, wenn Sie die ursprünglichen click Ereignishandlerargumente zu Ihrem eigenen Click-Ereignishandler beibehalten und übergeben möchten.

+0

Nur um die Dinge zum Abschluss bringen .... was sollte die anonyme SiehöreneinKlicken: function() { ....} 'return wenn confirm false zurückgibt? –

+0

es wird 'undefined' zurückgeben, damit KO Ihren Handler nicht anruft, auch die Browser Aktion (Klick auf den Link) wird nicht ausgeführt. Aber Sie können dies nach Ihren Bedürfnissen ändern. – nemesv

+0

Bereits getestet, bevor die andere Antwort kam und es funktioniert unglaublich gut. Ich bin froh, dass ich die Zeit damit verbracht habe zu untersuchen, wie ich das alleine machen kann, aber ich kam diesem Niveau der Erleuchtung nicht nahe. Vielen Dank! –

0

Ich glaube, das ist, wo Knockout den Klick-Bindungs ​​Handler definiert -

ko.bindingHandlers[eventName] = { 
    'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) { 
     var newValueAccessor = function() { 
      var result = {}; 
      result[eventName] = valueAccessor(); 
      return result; 
     }; 
     return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindings, viewModel, bindingContext); 
    } 
} 

Wo für eventname bindenem Handler ‚Klick‘. Ich glaube, dass diese irgendwo in Ihrer Ansicht nach Modell setzen oder nach dem Knockout geladen ist, den Trick tun soll -

ko.bindingHandlers.clickConfirm = { 
    'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) { 
     var newValueAccessor = function() { 
      var result = {}; 
      result.click = function() { 
      var result = confirm('You are about to confirm something.'); 
       // If they press OK, 
       console.log('pressed - ', result); 
       if (result === true) { 
        console.log('Calling this - ', valueAccessor()); 
        valueAccessor()(); 
       } 

      } 
      return result; 
     }; 
     return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindings, viewModel, bindingContext); 
    } 
} 

http://jsfiddle.net/XhLKD/

+0

Kudos auf der Arbeitslösung, aber @ nemesvs Antwort kam zuerst herein, funktioniert und scheint mindestens eine etwas einfachere Lösung zu sein.Ich möchte darauf hinweisen, dass es in beiden Lösungen Dinge gibt, die außerhalb meines Verständnisses liegen. Aus technischer Sicht könnte Ihre Antwort also sehr viel besser sein. Letztendlich wählte ich die erste und kürzere Antwort basierend auf meiner Ignoranz. –