2016-05-17 9 views
1

Ich habe folgende Typoskript einen KnockoutJS Bindungs ​​Handler für ein klickbaren Element in meiner Ansicht zu definieren:Wie kann ich warten, bis ein Ajax-Aufruf abgeschlossen wird, ohne 'async: false' zu verwenden und ohne Callbacks zu verwenden?

module MyModule { 
    export interface ICopyButtonParams { 
     dataUrl: string; 
    } 

    ko.bindingHandlers.copyButton = { 
     init: (element: HTMLElement, valueAccessor:() => ICopyButtonParams) => { 
      var options: any = ko.utils.unwrapObservable(valueAccessor()); 
      if (!options.dataUrl) { 
       return; 
      } 

      new Clipboard(element, { 
       text:() => { 
        var clipboardData: string; 

        $.ajax({ 
         url: options.dataUrl, 
         type: "GET", 
         contentType: "application/json", 
         cache: false, 
         async: false, 
         success: (result: SubmitResult) => { 
          clipboardData = result.Data; 
         } 
        }); 

        return clipboardData; 
       } 
      }); 
     } 
    }; 
} 

diese Bindung Handler Was tut, ist es das klickbaren Element in ein Clipboard.JS aktivierte Element dreht, die eine Zeichenfolge in der Zwischenablage speichert wenn geklickt wird. In meinem Fall möchte ich die dynamische Textfunktion von Clipboard.JS verwenden, wobei Sie eine Funktion in den Zwischenablage-Konstruktor übergeben, der den Text zurückgibt, den Sie in der Zwischenablage speichern möchten. In dieser Funktion möchte ich eine API aufrufen, die den zu speichernden Text zurückgibt.

Aufgrund der Beschaffenheit dieser Architektur kann ich keinen Standard-Ajax-Aufruf mit einem Erfolgsrückruf verwenden, da dies bedeuten würde, dass der Text der Zwischenablage nicht rechtzeitig aufgelöst würde.

Als Notlösung, werden Sie in meinem Code feststellen, dass ich meinen Ajax-Aufruf asynchron (schlecht, ich weiß) gemacht habe. Da die "async" -Flagge ab JQuery 1.8 veraltet ist, versuche ich an einen alternativen Ansatz zu denken.

Irgendwelche Ideen?

+1

Warum nicht zuerst ein asynchrones Ajax-Aufruf und dann in den Erfolg Rückruf Sie können ein Cliboard-Objekt erstellen? – mirage

+0

Der springende Punkt ist, dass ich die Daten nicht abrufen möchte, um sie in die Zwischenablage zu kopieren, wenn sie nicht benötigt wird (d. H. Jemand klickt auf die Schaltfläche "In Zwischenablage kopieren"). Es kann potenziell mehr als 100 Dinge auf der Seite geben, die in die Zwischenablage kopiert werden können und jeweils viele Zeichen Text enthalten. Wenn ich jede Zwischenablage-Schaltfläche mit den Daten, die sie speichern soll, vorinitialisiere, kann ich genauso gut den Zwischenablage-Text mit dem Rest des Ansichtsmodells abrufen und den Ajax-Aufruf ganz wegnehmen. Es sollte darauf hingewiesen werden, dass das, was in die Zwischenablage kopiert wird, niemals auf der Seite angezeigt wird. – aleonj

+0

Vielleicht verstehe ich Sie nicht richtig, aber Sie sollten nur Daten-bind = "copyButton: {}" auf die Elemente setzen, die Sie auf diese Weise verhalten möchten, oder? – mirage

Antwort

1

Ich denke, dass eine bessere Approuch sein wird, Click-Ereignis von selbst zu behandeln.

Dann auf Ihrem Ajax Callback ein Textfeld erstellen, Wert einstellen, wählen und document.execCommand('copy') als Clipboard.JS aufrufen. Etwas ähnliches wie diese (sorry für Javascript stattdessen auf Typoskript)

ko.bindingHandlers.copyButton = { 
    init: function(element, valueAccessor) { 
    var url = ko.utils.unwrapObservable(valueAccessor()); 

    $(element).click(function() { 
     $.ajax({ 
     url: url, 
     type: "GET", 
     contentType: "application/json", 
     cache: false, 
     async: false, 
     success: function(result) { 
      var ta = document.createElement('textarea'); 
      document.body.appendChild(ta); 
      ta.value = result; 
      ta.select(); 
      var r = document.createRange(); 
      r.selectNode(ta); 
      document.getSelection().addRange(r); 
      document.execCommand('copy'); 
      document.body.removeChild(ta); 
     } 
     }); 
    }); 
    } 
}; 

Ich habe ein ähnliches Arbeitsbeispiel here (ohne Ajax-Request)

+0

Ja, am Ende kam ich selbst zu diesem Ansatz. Das Design von Clipboard.JS ist zu präskriptiv. Es war schön, dass es alle "hacky" Sachen wie das Erstellen von Textareas umhüllte, aber es ist den Aufwand nicht wert. Danke für deine Antwort! – aleonj