Universal Apps mit TypeScript und AngularJS

Vergangene Woche habe ich gemeinsam mit Manfred Steyer (Professor an der FH Campus 02) und Andreas Schabus (Microsoft Österreich) einen Info-Abend zum Thema Cross-Device-Entwicklung an der FH Campus 02 in Graz veranstaltet. Unter anderem habe ich dort gezeigt, wie man eine Universal App für Windows 8 und Windows Phone 8 mit TypeScript und AngularJS erstellen kann. In diesem Beitrag fasse ich die wichtigsten Punkte zusammen, die dabei zu beachten sind. Das fertige Visual Studio Projekt kann am Ende des Artikels heruntergeladen werden.

Todo MVC

Als Basis verwende ich dafür das Beispiel von todomvc.com. Es handelt sich dabei um eine einfache HTML5 Webanwendung, mit der sich eine Todo-Liste verwalten lässt. Die Einträge werden dabei im lokalen Speicher des Browsers abgelegt, wodurch die Anwendung auch ohne Internetverbindung genutzt werden kann.

Im ersten Schritt erstellen wir ein neues Projekt für eine HTML Anwendung mit TypeScript in Visual Studio und fügen den Quellcode des TodoMVC Projekts hinzu. Damit beim kompilieren aus allen TypeScript Dateien eine einzelne JavaScript Datei erzeugt wird, muss bei den Projekteinstellungen ein Ausgabepfad konfiguriert werden. Das hat den Vorteil, dass nicht alle JavaScript Dateien einzeln referenziert werden müssen, und es ist auch nur ein einziger HTTP Request notwendig.

TypeScript Einstellungen

TypeScript Einstellungen des HTML Projekts


Hat man die Einstellungen so wie am Screenshot ersichtlich vorgenommen, kann das Projekt nun aus Visual Studio heraus gestartet und getestet werden.

Universal App Projekt erstellen und konfigurieren

Im nächsten Schritt fügen wir ein neues Projekt für eine Universal App mit JavaScript hinzu. Damit TypeScript Dateien unterstützt und kompiliert werden, müssen ein paar kleine Änderungen an den Projektdateien vorgenommen werden. Dazu „entladen“ wir das Projekt und bearbeiten dann direkt die Projektdatei.

Projektdatei bearbeiten

Die Projektdatei muss direkt im XML Editor bearbeitet werden.


Gleich in der ersten Zeile innerhalb des Projekt-Elements muss folgende Zeile eingefügt werden:

  <Import Project="$(MSBuildExtensionsPath32)MicrosoftVisualStudiov$(VisualStudioVersion)TypeScriptMicrosoft.TypeScript.Default.props" Condition="Exists('$(MSBuildExtensionsPath32)MicrosoftVisualStudiov$(VisualStudioVersion)TypeScriptMicrosoft.TypeScript.Default.props')" />

Und ganz am Ende sind folgende zwei Zeilen hinzuzufügen:

  <Import Project="$(MSBuildExtensionsPath32)MicrosoftVisualStudiov$(VisualStudioVersion)TypeScriptMicrosoft.TypeScript.targets" Condition="Exists('$(MSBuildExtensionsPath32)MicrosoftVisualStudiov$(VisualStudioVersion)TypeScriptMicrosoft.TypeScript.targets')" />
  <Import Project="$(MSBuildExtensionsPath32)MicrosoftVisualStudiov$(VisualStudioVersion)TypeScriptMicrosoft.TypeScript.jsproj.targets" Condition="Exists('$(MSBuildExtensionsPath32)MicrosoftVisualStudiov$(VisualStudioVersion)TypeScriptMicrosoft.TypeScript.jsproj.targets')" />

Diese Anpassungen müssen für alle drei Projekte vorgenommen werden. Anschließend können die Projekte wieder geladen werden.

Für das Windows 8 und Windows Phone 8 Projekt muss auch wieder konfiguriert werden, dass alle TypeScript Dateien in eine einzelne JavaScript Datei kompiliert werden. Für das Shared-Projekt ist das nicht notwendig, da dieses Projekt nicht kompiliert wird, sondern nur als Container für gemeinsam genutzte Dateien dient.

Nachdem wir alle Einstellungen vorgenommen haben, kopieren wir alle Skript und CSS Dateien in das Shared-Projekt und übernehmen den Inhalt der HTML Datei in die HTML Dateien der App Projekte.

Windows Runtime und dynamische Inhalte

Damit haben wir alle Einstellungen vorgenommen und können das Projekt ausführen. Leider bekommen wir gleich nach dem Start folgende Fehlermeldung:

JavaScript runtime error: Unable to add dynamic content. A script attempted to inject dynamic content, or elements previously modified dynamically, that might be unsafe. For example, using the innerHTML property to add script or malformed HTML will generate this exception. Use the toStaticHTML method to filter dynamic content, or explicitly create elements and attributes with a method such as createElement. For more information, see http://go.microsoft.com/fwlink/?LinkID=247104.

Dabei handelt es sich um eine Einschränkung der Windows Runtime, die aus Sicherheitsgründen das Hinzufügen von dynamischen Inhalt unterbindet. In diesem Fall sehen wir, dass der Fehler innerhalb der angular.js Datei auftritt. Und zwar werden in der letzten Zeile weitere Styles in den Header der Seite eingefügt. Da wir uns sicher sind, dass es sich hier um keinen schädlichen Code handelt, können wir den Filter der Windows Runtime für diese Zeile deaktivieren. Das Ergebnis sieht dann wie folgt aus:

MSApp.execUnsafeLocalFunction(function () {
    !angular.$$csp() && angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";[ng\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\:form{display:block;}</style>');
});

In diesem Fall kann der Code auch einfach so umgeschrieben werden, dass man ganz ohne dynamische Inhalte auskommt.

var style = document.createElement('style');
style.type = 'text/css';
style.innerText = '@charset "UTF-8";[ng\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\:form{display:block;}';
!angular.$$csp() && angular.element(document).find('head').prepend(style);

Je nach dem welche Features man von AngularJS verwendet, muss in dieser Datei an weiteren Stellen eine Ausnahme hinzugefügt werden. Eventuell wird es in Zukunft auch eine Version von AngularJS geben, die von Haus aus kompatibel mit der Windows Runtime ist. JQuery z.B. kann seit der Version 2.0 ohne Probleme eingesetzt werden.

Fazit

Mit recht wenig Aufwand lässt sich aus einer Webanwendung, die mit TypeScript und AngularJS erstellt wurde, eine App für Windows 8 und Windows Phone 8 erzeugen. Da es derzeit noch kein Template für Universal Apps mit TypeScript Unterstützung gibt, müssen die Projektdateien selbst angepasst werden. Durch die Sicherheitsmechanismen der Windows Runtime muss in Libraries, wie z.B. AngularJS, vereinzelt die Ausführung bestimmter Codeteile explizit erlaubt werden.

Das fertige Visual Studio Projekt kann hier heruntergeladen werden: TodoMvc.zip

Speichere in deinen Favoriten diesen permalink.

Schreibe einen Kommentar