TypeScript bietet Möglichkeiten um JavaScript Code in Klassen und Module strukturieren. Natürlich kann eine SharePoint Hosted App in SharePoint 2013 auch mit TypeScript erstellt werden (siehe Blog)
Ich habe mir mal Gedanken gemacht, wie ich die üblichen CSOM Aufrufe in Klassen verpacken kann um das ganze etwas strukturierter im Code darzustellen. Ein üblicher CSOM Aufruf kann so aussehen:
1 var ctx: SP.ClientContext = SP.ClientContext.get_current();
2 var user: SP.User = ctx.get_web().get_currentUser();
3 ctx.load(user, 'Title');
4 ctx.executeQueryAsync(
5 () => {
6 $('#message').text(user.get_title());
7 },
8 () => { });
Üblicherweise benötigt man den ClientContext, führt einzelne Arbeitsschritte am Context aus und wartet dann auf den Rückruf der executeQueryAsync-Methode. Meistens lasse ich mir im Failure-Callback noch die Fehlermeldung ausgeben.
Meine Idee ist nun, diese wiederkehrenden Schritte in eine Basis-Klasse zu verpacken und die konkreten Aufgaben in abgeleitete Klassen zu schreiben. Ich definiere somit die Klasse “Job”:
1 class job {
2 protected ctx: SP.ClientContext = SP.ClientContext.get_current();
3 public success: (sender : any, args: SP.ClientRequestSucceededEventArgs) => void;
4
5 public errorCallback: (sender: any, args: SP.ClientRequestFailedEventArgs) => any =
6 (sender, args) => {
7 alert(args.get_message());
8 };
9
10 doIt() {
11 this.work();
12 this.ctx.executeQueryAsync(this.success,this.errorCallback);
13 }
14
15 work() {
16 }
17 }
In der Klasse werden die beiden Rückruf-Funktionen als Member der Klasse definiert. Wir finden success und errorCallback. Die errorCallback-Methode wird gleich mal mit einer Alert-Box versehen die die Fehlermeldung ausgibt. Die Success Methode bleibt zunächst leer.
Mein erster Versuch sah vor, diese Methoden in den abgeleiteten Klassen zu überschreiben. Leider funktioniert das nicht, da wie in JavaScript üblich, in der CallBack Methode “this” nicht auf die Klasseninstanz zeigt. (Spaß mit this) Daher der Weg, die Methode als Properties zu definieren und später im Constructor die Methoden zuweisen.
Wenn ich nun das Beispiel von oben mit meinem Job programmieren möchte, so ist eine abgeleitete Klasse “getUserNameJob” zu erstellen. In dieser Klasse muss im Constructor die “Work” und die “Success” Methode definiert werden. Um das Resultat an den Aufrufer zurück zu geben wird ein “jobCallback” definiert der dann vom Aufrufer zu übergeben ist.
1 class getUserNameJob extends job {
2 public jobCallback: (userName: string) => any;
3
4 private user: SP.User;
5
6 constructor() {
7 super();
8
9 this.work = () => {
10 this.user =this.ctx.get_web().get_currentUser();
11 this.ctx.load(this.user, 'Title');
12 };
13
14 this.success = (sender, args) => {
15 var str = this.user.get_title();
16 this.jobCallback(this.user.get_title());
17 }
18 }
19 }
Um diesen Job nun zu verwenden wird eine Instanz gebildet, dem Callback eine Methode zugewiesen und die “doIt()” Methode aufgerufen:
1 var j: getUserNameJob = new getUserNameJob();
2 j.jobCallback = (userName) => {
3 $('#message').text(userName);
4 };
5 j.doIt();
Von diesem Basisgerüst ausgehend können nun diverse spezialisierte JobKlassen gebildet werden. Z.B. das Auslesen von ListItems oder auch der Zugriff auf das HostWeb kann so in handliche Basis-Klassen verpackt werden.
Ein detailliertes Demo hierzu zeige ich auf der SharePoint Konferenz in Erding (10.-11.3.2015) in der Session “TypeScript – typisiertes JavaScript”