{"id":21017,"date":"2016-04-05T14:47:20","date_gmt":"2016-04-05T13:47:20","guid":{"rendered":"https:\/\/www.inovex.de\/\/?p=1579"},"modified":"2026-03-17T08:00:04","modified_gmt":"2026-03-17T07:00:04","slug":"polymer-in-dart-tutorial","status":"publish","type":"post","link":"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/","title":{"rendered":"Polymer in Dart [Tutorial]"},"content":{"rendered":"<p>Javascript ist in vielerlei Hinsicht nicht die optimale Wahl, um komplexe Web-Applikationen zu entwickeln. Da die Sprache nicht von Anfang an sorgf\u00e4ltig entworfen wurde, gibt es \u2013 abgesehen von Problemen wie fehlender Typisierung und Modularisierung \u2013 viele kleine Unsch\u00f6nheiten. Um den Entwickler:innen eine ordentlich aufgebaute, saubere Sprache zu bieten, mit der Web-Applikationen erstellt werden k\u00f6nnen, hat Google Dart entworfen, das die Unzul\u00e4nglichkeiten von Javascript \u00fcberwinden soll.<!--more--><\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\"><\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#Was-ist-Dart\" >Was ist Dart<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#Polymer-in-Dart-%E2%80%93-Aufbau\" >Polymer in Dart \u2013 Aufbau<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#Verwendung-von-Bibliotheken-und-Komponenten\" >Verwendung von Bibliotheken und Komponenten<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#Verwendung-von-anderen-Webcomponents\" >Verwendung von anderen Webcomponents<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#Probleme-bei-Javascript-Dart-vs-Polymer-Dart\" >Probleme bei Javascript-Dart vs. Polymer-Dart<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#Integration-von-reinen-Javascript-Bibliotheken\" >Integration von reinen Javascript-Bibliotheken<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#Der-Build\" >Der Build<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#Veroeffentlichen-von-eigenen-Komponenten\" >Ver\u00f6ffentlichen von eigenen Komponenten<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#Testen-von-Polymer-Apps-mit-Dart\" >Testen von Polymer-Apps mit Dart<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#Fazit\" >Fazit<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#Links-Quellen\" >Links &amp; Quellen<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#Were-hiring\" >We&#8217;re hiring!<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#Weiterlesen\" >Weiterlesen<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"Was-ist-Dart\"><\/span>Was ist Dart<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Auf den ersten Blick erinnert Dart dabei an Java \u2013 mit Klassen ohne Mehrfachvererbung, Interfaces, Generics und Annotations werden viele M\u00f6glichkeiten geboten, um sauberen objekt-orientierten Code zu schreiben. Dart unterst\u00fctzt statische Typisierung, diese ist jedoch optional und kann deaktiviert werden \u2013 auf diese Weise ist es m\u00f6glich, bei der Entwicklung statische Typ-Checks zu nutzen, diese im Produktivbetrieb jedoch zu deaktivieren.<\/p>\n<p>Mit pub steht ein an npm erinnernder Paketmanager zur Verf\u00fcgung, der Dependency Management und Build-Steuerung \u00fcbernimmt. Pakete k\u00f6nnen in der zentralen Registry <code>pub.dartlang.org<\/code> ver\u00f6ffentlicht werden. Die Abh\u00e4ngigkeiten eines Projektes liegen dabei immer in der zentralen Datei <code>pubspec.yaml<\/code>.<\/p>\n<p>Mit Dart ist es m\u00f6glich, sowohl Server-Anwendungen als auch Web-Applikationen zu entwickeln \u2013 f\u00fcr ersteres steht die Dartium-VM bereit, um das Dart-Programm performant auszuf\u00fchren, f\u00fcr letzteres eignet sich das Tool Dart2JS, das den nativen Dart-Code in Javascript umwandelt, das anschlie\u00dfend in jedem gew\u00f6hnlichen Browser ausgef\u00fchrt werden kann. Durch ein spezielles Paket ist es m\u00f6glich, Javascript-Bibliotheken aus dem Dart-Code heraus anzusprechen.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Polymer-in-Dart-%E2%80%93-Aufbau\"><\/span>Polymer in Dart \u2013 Aufbau<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>F\u00fcr die Polymer-Bibliothek wird zus\u00e4tzlich zur Javascript-Version eine Dart-Version gepflegt, die die Erstellung von Web-Components direkt aus Dart m\u00f6glich macht. Dabei wird eine einzelne Komponente immer in 2 oder mehr Dateien aufgeteilt \u2013 die HTML-Datei mit Template und CSS-Definitionen und die Dart-Datei, die die Logik der Komponente kapselt. Aus Sicht von Dart ist eine Polymer-Komponente eine herk\u00f6mmliche Dart-Klasse mit Annotationen, die <a href=\"https:\/\/www.inovex.de\/\/polymer-1-0-das-experiment-ist-vorueber\/\" target=\"_blank\" rel=\"noopener\">Polymer<\/a> erlauben, die Komponente im Browser zu registrieren und zu verwenden:<\/p>\n<pre class=\"lang:js decode:true \">@HtmlImport(my_component.html')\r\n\r\nlibrary my_package.my_component;\r\n\r\nimport 'dart:html';\r\n\r\nimport 'package:polymer\/polymer.dart';\r\n\r\nimport 'package:web_components\/web_components.dart' show HtmlImport;\r\n\r\n@PolymerRegister('my-component')\r\n\r\nclass MyComponent extends PolymerElement {\r\n\r\n    MyComponent.created() : super.created();\r\n\r\n    @Property(observer: 'paramChanged')\r\n\r\n    String param = null;\r\n\r\n    @reflectable\r\n\r\n    void paramChanged(String newParam, String oldParam) {\r\n\r\n        \/\/...\r\n\r\n    }\r\n\r\n}<\/pre>\n<p>Die zugeh\u00f6rige HTML-Datei mit Template und Styles unterscheidet sich dabei im Aufbau nicht von Polymer-Komponenten, die auf herk\u00f6mmliche Weise mit Javascript entwickelt wurden, Databinding und CSS-Selektoren sind identisch:<\/p>\n<pre class=\"lang:xhtml decode:true\">&lt;dom-module id=\"my-component\"&gt;\r\n\r\n&lt;style&gt;\r\n\r\n* {\r\n\r\n    color: red !important;\r\n\r\n  ;}\r\n\r\n&lt;\/style&gt;\r\n\r\n&lt;template&gt;\r\n\r\n    &lt;h1&gt;This is my component&lt;\/h1&gt;\r\n\r\n    &lt;p&gt;{{param}}&lt;\/p&gt;\r\n\r\n&lt;\/template&gt;\r\n\r\n&lt;\/dom-module&gt;<\/pre>\n<p>Um eine solche Komponente in einem Dart-Projekt zu verwenden, muss die Basisdatei <code>pubspec.yaml<\/code> angepasst werden. Dabei m\u00fcssen die korrekten Dependencies geladen und der Webcomponent-Transformer verkn\u00fcpft werden, der die verwendeten <a href=\"https:\/\/www.inovex.de\/\/webcomponents-tutorial\/\" target=\"_blank\" rel=\"noopener\">Webcomponents<\/a> aufl\u00f6st. Transformer werden vor der Auslieferung von Dateien ausgef\u00fchrt und f\u00fchren Modifikationen am Inhalt durch, in diesem Fall die <a href=\"https:\/\/pub.dartlang.org\/packages\/web_components\" target=\"_blank\" rel=\"noopener\">Anwendung von Polyfills f\u00fcr Shadow DOM, Custom Elements und HTML Imports<\/a>.<\/p>\n<pre class=\"lang:yaml decode:true \">dependencies:\r\n\r\npolymer: 1.0.0-rc.6\r\n\r\nweb_components: ^0.12.0\r\n\r\nreflectable: ^0.3.0\r\n\r\npolymer_elements: 1.0.0-rc.3\r\n\r\nevents: 0.1.1+1\r\n\r\ntransformers:\r\n\r\n- web_components:\r\n\r\nentry_points:\r\n\r\n- web\/foo.html\r\n\r\n- reflectable:\r\n\r\nentry_points:\r\n\r\n- web\/foo.dart<\/pre>\n<p>In der Haupt-HTML-Datei, dem sogenannten Entry Point, der der Startpunkt der Web-App und der Abh\u00e4ngigkeits-Aufl\u00f6sung ist, kann die erstellte Komponente verwendet werden:<\/p>\n<pre class=\"lang:xhtml decode:true \">&lt;!DOCTYPE html&gt;\r\n\r\n&lt;html&gt;\r\n\r\n    &lt;head&gt;\r\n\r\n        &lt;script async type=\"application\/dart\" src=\"foo.dart\"&gt;&lt;\/script&gt;\r\n\r\n        &lt;script src=\"packages\/browser\/dart.js\"&gt;&lt;\/script&gt;\r\n\r\n    &lt;\/head&gt;\r\n\r\n    &lt;body&gt;\r\n\r\n        &lt;my-component param=\u201c123\u201c&gt;&lt;\/my-component&gt;\r\n\r\n    &lt;\/body&gt;\r\n\r\n&lt;\/html&gt;\r\n\r\n<\/pre>\n<p>Hier wird die Haupt-Dart-Datei referenziert, die die Startmethode <code>main()<\/code> enth\u00e4lt, die wie in Java-Anwendungen den Programmstartpunkt markiert. Im Falle von Webcomponents muss die Dart-Datei nur die ben\u00f6tigten Komponenten importieren und Dart starten, der Rest wird dann von Polymer und den einzelnen Komponenten selbst \u00fcbernommen:<\/p>\n<pre class=\"lang:js decode:true \">import 'dart:async';\r\n\r\nimport 'package:polymer\/polymer.dart';\r\n\r\nimport 'my_component.dart';\r\n\r\nFuture main() async {\r\n\r\n    await initPolymer();\r\n\r\n}<\/pre>\n<p>Mit <code>pub serve<\/code> wird ein lokaler Entwicklungs-Server gestartet, der die Polymer-Komponenten kompiliert und die Entrypoint-Datei in einem Webserver zur Verf\u00fcgung stellt. In einem Browser kann anschlie\u00dfend das Endprodukt betrachtet werden. <code>pub<\/code> bemerkt, wenn Quelldateien sich \u00e4ndern und kompiliert das Projekt bei Bedarf automatisch neu. Der komplette Beispiel-Code kann auch auf <a href=\"https:\/\/github.com\/flash1293\/polymer_dart_example\" target=\"_blank\" rel=\"noopener\">Github<\/a> eingesehen werden.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Verwendung-von-Bibliotheken-und-Komponenten\"><\/span>Verwendung von Bibliotheken und Komponenten<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Das wichtigste Merkmal von Webcomponents ist ihre F\u00e4higkeit zur Wiederverwendung und Komposition mit anderen Komponenten. Die von Google selbst gepflegten Komponenten-Bibliotheken (iron, paper, google, \u2026) sind in Dart portiert und k\u00f6nnen \u00fcber das pub-Package <code>polymer_components<\/code> geladen werden. Das Einbinden der Komponenten funktioniert wie im herk\u00f6mmlichen Javascript-Dart mit einem Link-Tag (z.B. <span class=\"lang:xhtml decode:true crayon-inline \">&lt;link rel=&#8220;import&#8220; href=&#8220;packages\/polymer_elements\/iron_list.html&#8220;&gt;<\/span>), durch den die Komponente geladen wird und ab sofort in Templates verwendet werden kann. Es ist auch m\u00f6glich, Instanzen von Komponenten imperativ im Dart-Code zu erzeugen, daf\u00fcr kann die Funktion <code><a href=\"https:\/\/api.dartlang.org\/133732\/dart-html\/Element\/Element.tag.html\" target=\"_blank\" rel=\"noopener\">Element.tag<\/a><\/code> aus dem <code>dart:html<\/code>-Package verwendet werden, das die Arbeit mit dem DOM durch ein einheitliches Interface erm\u00f6glicht (\u00e4hnlich wie jQuery in Javascript).<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Verwendung-von-anderen-Webcomponents\"><\/span>Verwendung von anderen Webcomponents<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Es ist auch m\u00f6glich, Webcomponents zu nutzen, die nicht auf Dart portiert wurden \u2013 da Webcomponents nur einen modernen Browser ben\u00f6tigen, um eingebunden zu werden, k\u00f6nnen sie einfach so genutzt werden wie in der herk\u00f6mmlichen Webcomponents-Programmierung: Durch Importieren der HTML-Datei. So kann beispielsweise die Komponente <code>app-router<\/code> genutzt werden, um ohne Aufwand client-seitige Seitennavigation zu implementieren:<\/p>\n<pre class=\"lang:xhtml decode:true \">&lt;!doctype html&gt;\r\n\r\n&lt;html&gt;\r\n\r\n    &lt;head&gt;\r\n\r\n        &lt;title&gt;App Router&lt;\/title&gt;\r\n\r\n            &lt;link rel=\"import\" href=\"\/bower_components\/app-router\/app-router.html\"&gt;\r\n\r\n    &lt;\/head&gt;\r\n\r\n    &lt;body&gt;\r\n\r\n        &lt;app-router&gt;\r\n\r\n            &lt;app-route path=\"\/home\/:param\" element=\"my-component\"&gt;&lt;\/app-route&gt;\r\n\r\n            &lt;app-route path=\"*\" element=\"not-found-component\"&gt;&lt;\/app-route&gt;\r\n\r\n        &lt;\/app-router&gt;\r\n\r\n    &lt;\/body&gt;\r\n\r\n&lt;\/html&gt;<\/pre>\n<p>Im oben stehenden Beispiel wird die <code>app-router<\/code>-Komponente verwendet, um auf der Seite <code>#\/home\/abc<\/code> die von uns in Dart entwickelte Komponente darzustellen \u2013 Parameter, die mit der Platzhalter-Syntax im <code>path<\/code>-Attribut definiert wurden, werden automatisch der Komponente \u00fcbergeben; in diesem Fall w\u00fcrde das Element initialisiert werden. Da die Schnittstelle zwischen den Komponenten nur auf HTML bzw. dem DOM basiert, ist die Tatsache, dass eine Komponente mit Dart entwickelt wurde, nur ein Implementierungsdetail und behindert die Komposition nicht.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Probleme-bei-Javascript-Dart-vs-Polymer-Dart\"><\/span>Probleme bei Javascript-Dart vs. Polymer-Dart<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Probleme entstehen, wenn Komponenten verwendet werden, die Polymer in der Javascript-Version nutzen. Da Polymer eigene Komponenten registriert (z.B. dom-module), kollidieren zwei Instanzen von Polymer, die auf der gleichen Website ausgef\u00fchrt werden. Momentan ist es daher nicht m\u00f6glich, ohne Modifikationen gleichzeitig Komponenten zu nutzen, die mit Dart-Polymer bzw. Javascript-Polymer entwickelt wurden. F\u00fcr das bereits erw\u00e4hnte <code>polymer_elements<\/code> Package, das die Komponenten nicht von Grund auf neu implementiert, sondern nur ein Dart-Interface f\u00fcr die Javascript-Komponenten zur Verf\u00fcgung stellt, wurde das Problem umgangen, indem der HTML-Import von Polymer nachtr\u00e4glich von Javascript-Polymer auf Dart-Polymer ge\u00e4ndert wurde. Diese Strategie kann beispielsweise auch f\u00fcr \u00fcber Bower geladene Webcomponents \u00fcbernommen werden \u2013 ein Post-Install-Script kann alle referenzierten Polymer-Instanzen auf die Dart-Variante um\u00e4ndern und so das Problem von mehreren laufenden Polymer-Instanzen verhindern. Wird das <code>polymer_elements<\/code> Package verwendet, muss die gleiche Vorgehensweise auch f\u00fcr die dort definierten Komponenten angewendet werden \u2013 die Komponente Paper-Button darf nicht zweimal \u2013 einmal aus der Bower-Dependency, einmal aus der Dart-Dependency \u2013 initialisiert werden. Um die Anpassung der Referenzen zu automatisieren, kann das Bower-Paket <code>polymer-highlander<\/code> genutzt werden.<\/p>\n<p>Eine andere M\u00f6glichkeit zur Aufl\u00f6sung des Konflikts stellt das Package <code>custom_element_apigen<\/code> dar, das auch f\u00fcr die Google-Elemente in <code>polymer_elements genutzt<\/code> wurde. Damit kann ein Dart-Wrapper f\u00fcr beliebige Webcomponents geschrieben werden. Der manuelle Aufwand ist allerdings gro\u00df und das Tool schlecht dokumentiert.<\/p>\n<p>Die Nutzung von zwei unterschiedlichen Dependency-Management-Systemen mag zwar umst\u00e4ndlich und unsauber erscheinen, im Moment ist das \u00d6kosystem von Dart jedoch noch nicht gro\u00df genug, um eigene Bibliotheken f\u00fcr alle denkbaren Anwendungsfalle liefern zu k\u00f6nnen und es steht in Frage, ob das jemals der Fall sein wird, da Google seine <a href=\"http:\/\/news.dartlang.org\/2015\/03\/dart-for-entire-web.html\" target=\"_blank\" rel=\"noopener\">Bem\u00fchungen aufgegeben<\/a> hat, jeden Browser mit einer Dart-Runtime auszustatten. Daher muss in vielen F\u00e4llen auf Javascript-Pendants zur\u00fcckgegriffen werden.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Integration-von-reinen-Javascript-Bibliotheken\"><\/span>Integration von reinen Javascript-Bibliotheken<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Javascript hat ein riesiges \u00d6kosystem aus Bibliotheken und Frameworks f\u00fcr die verschiedensten Anwendungsf\u00e4lle. Oft macht es Sinn, aus einer Dart-Polymer Anwendung heraus auf diese Bibliotheken zuzugreifen, da keine Dart-Bibliothek existiert, die \u00e4hnliche Funktionalit\u00e4t bereitstellt. Die Datums-Bibliothek <code>moment.js<\/code> beispielsweise liefert viele praktische Hilfsmethoden, wie z.B. <code>fromNow<\/code> \u2013 die die Zeitspanne zwischen einem Datum und der aktuellen Zeit in lesbarer Form ausgibt. Diese soll im folgenden Beispiel in einer Dart-Polymer-Komponente zug\u00e4nglich gemacht werden. Um die Bibliothek zu integrieren, ist der einfachste Weg, diese per Bower zu laden: <span class=\"lang:sh decode:true crayon-inline \">bower install &#8211;save moment<\/span>. Nun kann die Javascript-Datei im HTML-Part der Komponente mit einem herk\u00f6mmlichen Script-Tag geladen werden: <span class=\"lang:xhtml decode:true crayon-inline \">&lt;script src=&#8220;bower_components\/moment\/moment.js&#8220; type=&#8220;application\/javascript&#8220;&gt;&lt;\/script&gt;<\/span>. Um nun in Dart-Code auf die Bibliothek zuzugreifen, wird das Core-Package <code>dart:js<\/code> ben\u00f6tigt, das es erm\u00f6glicht, mit Dart Javascript-Code anzusprechen. Mithilfe dieses Package ist es m\u00f6glich, einen Dart-Proxy f\u00fcr <code>moment<\/code> zu entwickeln:<\/p>\n<pre class=\"lang:js decode:true \">import 'dart:js';\r\n\r\nclass Moment {\r\n\r\n    JsObject _momentInstance;\r\n\r\n    Moment(date) {\r\n\r\n        _momentInstance = context.callMethod('moment', [date]);\r\n\r\n    }\r\n\r\n    String fromNow() {\r\n\r\n        return _momentInstance.callMethod('fromNow').toString();\r\n\r\n    }\r\n\r\n}<\/pre>\n<p>Im Konstruktor der Dart-Klasse wird eine Javascript-Instanz von <code>moment<\/code> aufgerufen. Daf\u00fcr muss auf die Variable <code>context<\/code> zugegriffen werden, die den globalen Namespace in Javascript darstellt. Die Moment-Bibliothek registriert dort automatisch die globale Variable <code>moment<\/code>, die mit der Methode <code>callMethod<\/code> aus dem <code>dart:js<\/code> Package aufgerufen werden kann. Als Parameter wird der Parameter des Dart-Konstruktors durchgeschleust, der absichtlich nicht typisiert wurde, da die Moment-Bibliothek verschiedene Werte als Parameter akzeptiert. Das resultierende <code>JsObject<\/code> wird als Instanz-Variable gespeichert. Ab jetzt sind die verschiedenen Funktionen der Bibliothek zug\u00e4nglich, wie in diesem Beispiel die <code>fromNow<\/code>-Methode, die auch wieder mit <code>callMethod<\/code> aufgerufen wird. Da de R\u00fcckgabe-Wert von <code>callMethod<\/code> immer vom Typ <code>JsObject<\/code> ist, muss er in diesem Fall noch mit <code>toString()<\/code> in einen normalen Dart-String umgewandelt werden, um die Typsicherheit zu gew\u00e4hrleisten. Die Funktionalit\u00e4t k\u00f6nnte nun in der Komponente als Computed Binding im Template verf\u00fcgbar gemacht werden:<\/p>\n<pre class=\"lang:js decode:true \">my_component.dart\r\n\r\n@reflectable\r\n\r\nString timeAgo(int timestamp) {\r\n\r\n    return (new Moment(timestamp)).fromNow();\r\n\r\n}<\/pre>\n<pre class=\"lang:xhtml decode:true \">my_component.html\r\n\r\nThe beginning of the unix-epoch was &lt;span&gt;{{timeAgo(0)}}&lt;\/span&gt;<\/pre>\n<p><strong>Ausgabe:<\/strong> The beginning of the unix-epoch was 46 years ago<\/p>\n<p>Es ist zu sehen, dass die Verwendung von Javascript-Bibliotheken aus Dart heraus nicht schwierig ist, jedoch immer den Aufwand nach sich zieht, eine Proxy-Klasse zu definieren. Au\u00dferdem f\u00fchlen sich die typenlosen Interfaces der Javascript-Bibliotheken u.U. in typisiertem Dart-Code merkw\u00fcrdig an. Daher sollte auf die Faustregel zur\u00fcckgegriffen werden, die Dart-Welt nur zu verlassen, wenn dies unbedingt n\u00f6tig ist, um den Overhead der <em>Grenz\u00fcberschreitung<\/em> zu vermeiden \u2013 da das Dart-\u00d6kosystem immer weiter w\u00e4chst, wird die Not, Bibliotheken aus Dart einzubinden, mit der Zeit wahrscheinlich immer kleiner werden. Zus\u00e4tzlich ist mit dem <a href=\"https:\/\/pub.dartlang.org\/packages\/js\" target=\"_blank\" rel=\"noopener\">js-Package<\/a> eine weitere M\u00f6glichkeit in aktiver Entwicklung, auf schnelle und einfache Art Interfaces zu bestehenden Javascript-Bibliotheken zu erstellen, die vollkommen deklarativ funktioniert.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Der-Build\"><\/span>Der Build<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Um aus den erstellten Dart-Klassen eine auslieferbare Web-App zu erstellen, sollte das Pub-Tool mit den Transformern <code>web_components<\/code> und <code>reflectables<\/code> verwendet werden \u2013 mit dem Befehl <span class=\"lang:sh decode:true crayon-inline \">pub build &#8211;mode=release<\/span> geht der Transformer vom spezifizierten Entry-Point aus und nimmt alle ben\u00f6tigten Dart-Klassen und Assets wie HTML- oder CSS-Files in den Compile-Vorgang mit auf. Um den ausgegebenen Code m\u00f6glichst klein zu halten, wird <em>Tree shaking<\/em> angewendet. Dabei wird aller Code, der im aktuellen Programm nicht erreicht wird und damit unn\u00f6tig ist, ausgeschlossen. Anschlie\u00dfend wird mit dem Tool Dart2JS das Dart-Programm in Javascript \u00fcbersetzt, das auch im Browser ausf\u00fchrbar ist. Daraus resultieren im build-Ordner einige Javascript- und Asset-Files, die die komplette Web-App beinhalten und von einem Webserver ausgeliefert werden k\u00f6nnen. Vorsicht: Es werden auch Dateien im build-Ordner abgelegt, die im Endprodukt gar nicht ben\u00f6tigt werden; HTML-Templates von verwendeten Webcomponents werden automatisch in der Haupt-HTML-Datei geb\u00fcndelt abgelegt und sind daher nicht mehr als eigenst\u00e4ndige Datei notwendig.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Veroeffentlichen-von-eigenen-Komponenten\"><\/span>Ver\u00f6ffentlichen von eigenen Komponenten<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Im Dart-\u00d6kosystem wird der Pub-Packagemanager verwendet, um anderen eigene Bibliotheken zur Verf\u00fcgung zu stellen. Da im Grunde alle Dart-Projekte bereits Pub-Projekte sind, da sie so Abh\u00e4ngigkeiten zu anderen Bibliotheken aufl\u00f6sen, fehlen nur noch wenige Schritte zum Erstellen eines eigenen Packages. Wichtig dabei ist, dass den Layout-Spezifikationen von Pub-Packages gefolgt wird. Die folgende Ordner-Struktur ist dabei vorgegeben:<\/p>\n<pre class=\"lang:sh decode:true \">enchilada\/\r\n\r\npubspec.yaml\r\n\r\nREADME.md\r\n\r\nCHANGELOG.md\r\n\r\nLICENSE\r\n\r\nlib\/\r\n\r\nenchilada.dart\r\n\r\ntortilla.dart\r\n\r\nguacamole.css\r\n\r\nsrc\/\r\n\r\nbeans.dart\r\n\r\nqueso.dart<\/pre>\n<p>Auf oberster Verzeichnis-Ebene befindet sich die <code>pubspec.yaml<\/code>-Datei, die die Konfiguration des Packages beinhaltet. In den Dateien <code>README.md<\/code>, <code>CHANGELOG.md<\/code> und <code>LICENSE<\/code> befinden sich zus\u00e4tzliche Hilfsinformationen f\u00fcr Entwickler:innen, die dieses Package nutzen wollen. Dart-Code und Assets, die sp\u00e4ter ins eigene Projekt importiert werden sollen, m\u00fcssen sich im Ordner <code>lib<\/code> befinden. Dabei ist es Konvention, dass die Hauptdatei, mit der die ganze Funktionalit\u00e4t des Packages importiert werden kann, den gleichen Namen wie das Projekt selbst tr\u00e4gt.<\/p>\n<p>Im Falle der selbstgeschriebenen Polymer-Komponente m\u00fcsste diese also nur im Lib-Ordner abgelegt werden, um ein g\u00fcltiges, zur Ver\u00f6ffentlichung bereites Package zu erstellen. \u00dcber den Befehl <span class=\"lang:sh decode:true crayon-inline \">pub publish &#8211;dry-run<\/span> kann ein Testlauf durchgef\u00fchrt werden, der pr\u00fcft, ob alle Informationen vollst\u00e4ndig sind und ob das Package problemlos von anderen Entwicklern genutzt werden kann. Dabei wird z.B. auch \u00fcberpr\u00fcft, ob Ranges von Versionen f\u00fcr Abh\u00e4ngigkeiten des Packages angegeben werden \u2013 wird eine spezifische Abh\u00e4ngigkeitsversion gew\u00e4hlt, kann das Probleme mit den Abh\u00e4ngigkeiten von anderen Packages ergeben, die vom Anwender ebenfalls genutzt werden. Nach der Ver\u00f6ffentlichung mit <span class=\"lang:sh decode:true crayon-inline \">pub publish<\/span>, das einen Google-Account zur Authentifizierung ben\u00f6tigt, ist das Package auf <code><a href=\"http:\/\/pub.dartlang.org\" target=\"_blank\" rel=\"noopener\">pub.dartlang.org<\/a><\/code> mitsamt automatisiert erstellten API-Docs verf\u00fcgbar und kann in anderen Packages eingebunden werden. Das Package <code><a href=\"https:\/\/github.com\/flash1293\/polymer_time_ago\" target=\"_blank\" rel=\"noopener\">polymer_time_ago<\/a><\/code> zeigt eine nach dieser Methodik ver\u00f6ffentlichte Polymer-Komponente in einem Minimalbeispiel.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Testen-von-Polymer-Apps-mit-Dart\"><\/span>Testen von Polymer-Apps mit Dart<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Um die selbsterstellten Komponenten zu testen, kann das <code>test<\/code>-Package per Pub installiert werden, mit dem beliebige Unit-Tests umgesetzt werden k\u00f6nnen. Mittels der Annotation <code>@TestOn(\u201aBrowser\u2019)<\/code> kann eine Test-Datei als Browser-Test markiert werden. Im Falle von Webcomponents muss, damit die Dart-Komponenten im Browser korrekt initialisiert werden, zuerst die Datei <code>interop_support.html<\/code> aus dem <code>web_components<\/code> Package eingebunden werden. Um die HTML-Umgebung des Tests auf diese Weise vorzubereiten, kann pro Dart-Testdatei eine HTML-Datei hinterlegt werden. Diese muss den gleichen Namen wie die Dart-Datei tragen und per die Unit-Tests importieren. Die HTML- und Dart-Dateien sollten dabei in einem separaten Ordner <code>test<\/code> im Projektverzeichnis liegen.<\/p>\n<p>F\u00fcr die Unit-Tests selbst k\u00f6nnen die Funktionen <code>setUp()<\/code> und <code>test()<\/code> verwendet werden, die einzelne Test-Cases separieren. Die <code>setUp<\/code>-Methode wird dabei vor jeder <code>test()<\/code>-Methode ausgef\u00fchrt. Es existieren viele weitere Hooks, um auch komplexe Test-Cases abbilden zu k\u00f6nnen. In einem beispielhaften Test-Case wird f\u00fcr die gerade erstelle Komponente <code>my-component<\/code> getestet, ob der Parameter <code>param<\/code> korrekt im Template angezeigt wird.<\/p>\n<pre class=\"lang:js decode:true \">@TestOn(\"browser\")\r\n\r\nimport \"dart:html\";\r\n\r\nimport \"package:test\/test.dart\";\r\n\r\nimport 'package:polymer\/polymer.dart';\r\n\r\nimport 'package:polymer_dart_example\/my_component.dart';\r\n\r\nmain() async {\r\n\r\n    MyComponent componentUnderTest;\r\n\r\n    await initPolymer();\r\n\r\n    setUp(() {\r\n\r\n        document.body.children.clear();\r\n\r\n        componentUnderTest = new Element.tag('my-component');\r\n\r\n        document.body.append(componentUnderTest);\r\n\r\n    });\r\n\r\n    test(\"my-component should reflect param to paragraph\", () {\r\n\r\n        componentUnderTest.setAttribute(\"param\", \"abc\");\r\n\r\n        Element paragraph = new PolymerDom(componentUnderTest.root).querySelector('p');\r\n\r\n        expect(paragraph.text, equals('abc'));\r\n\r\n    });\r\n\r\n}<\/pre>\n<p>Um die Tests erst dann zu starten, wenn Polymer initialisiert ist und Komponenten genutzt werden k\u00f6nnen, muss auf die Methode <code>initPolymer<\/code> gewartet werden. In der <code>setUp<\/code>-Methode wird dann ein frisches Element der Komponente generiert. Auf diese Weise wird verhindert, dass sich die einzelnen Test-Cases \u00fcber den State der Komponente gegenseitig beeinflussen k\u00f6nnen. Mit <code>PolymerDom()<\/code> kann auf die in einer Komponente gekapselten Elemente zugegriffen werden \u2013 der Zugriff muss an dieser Stelle polymer-spezifisch erfolgen, da die Elemente nicht immer in einem echten Shadow-DOM liegen sondern auch mithilfe von Polymers Polyfill Shady DOM direkt im HTML-Dokument. PolymerDom erkennt, welche Technik angewendet wurde und gibt die Referenz auf den richtigen DOM-Knoten zur\u00fcck.<\/p>\n<p>Um die Tests auszuf\u00fchren, wird der Befehl <span class=\"lang:sh decode:true crayon-inline \">pub run test-p chrome<\/span> ausgef\u00fchrt. Polymer-Komponenten nutzen jedoch den <code>web_components<\/code> Transformer, um den Output im Browser ausf\u00fchrbar zu machen. <span class=\"lang:sh decode:true crayon-inline \">pub run test<\/span> w\u00fcrde die ben\u00f6tigten Dateien direkt vom Dateisystem lesen und so den Transformer umgehen, was die Tests fehlschlagen lie\u00dfe. Damit die Tests auf den vom Transformer lauff\u00e4hig gemachten Komponenten ausgef\u00fchrt werden, muss mittels <span class=\"lang:sh decode:true crayon-inline \">pub serve<\/span> ein lokaler Webserver gestartet werden und in einem anderen Terminal der Test-Befehl <span class=\"lang:sh decode:true crayon-inline \">pub run test -p chrome &#8211;pub-serve=8081<\/span> eingegeben werden. Das Flag <code>--pub-serve<\/code> wei\u00dft den Test-Runner an, die ben\u00f6tigten Dateien nicht vom Dateisystem sondern vom lokalen Webserver zu laden.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Fazit\"><\/span>Fazit<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Es sind noch einige Unsch\u00f6nheiten zu bereinigen, um Dart in Kombination mit Polymer zu nutzen, vor allem das Zusammenspiel von in Javascript und in Dart entwickelten Komponenten muss noch vereinfacht werden. Abgesehen von diesen Kinderkrankheiten ist es mit Dart bereits heute m\u00f6glich, in einer typisierten, sorgf\u00e4ltig designten Sprache komponentenbasierte Web-Applikationen zu entwickeln, die sowohl vom wachsenden Dart-\u00d6kosystem als auch \u2013 wenn auch auf kleinen Umwegen \u2013 vom bestehenden Javascript-\u00d6kosystem profitieren k\u00f6nnen.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Links-Quellen\"><\/span>Links &amp; Quellen<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<ul>\n<li><a href=\"https:\/\/github.com\/dart-lang\/polymer-dart-patterns\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/dart-lang\/polymer-dart-patterns<\/a><\/li>\n<li><a href=\"https:\/\/angulardart.org\/\" target=\"_blank\" rel=\"noopener\">https:\/\/angulardart.org\/<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/flash1293\/polymer-highlander\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/flash1293\/polymer-highlander<\/a><\/li>\n<li><a href=\"https:\/\/pub.dartlang.org\/packages\/custom_element_apigen\" target=\"_blank\" rel=\"noopener\">https:\/\/pub.dartlang.org\/packages\/custom_element_apigen<\/a><\/li>\n<li><a href=\"https:\/\/pub.dartlang.org\/packages\/test\" target=\"_blank\" rel=\"noopener\">https:\/\/pub.dartlang.org\/packages\/test<\/a><\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"Were-hiring\"><\/span>We&#8217;re hiring!<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Tapetenwechsel gef\u00e4llig? Wir sind auf der Suche nach begeisterten Frontend-Entwickler:innen, die unsere Projektteams im Umfeld von JavaScript, HTML und CSS unterst\u00fctzen und auch vor innovativen Themen wie AngularJS und Progressive Web Apps nicht zur\u00fcckschrecken. <strong>Jetzt Bewerben!<\/strong><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Weiterlesen\"><\/span>Weiterlesen<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Mehr Informationen zu unseren Dienstleistungen rund um die Web-Entwicklung gibt es <a href=\"https:\/\/www.inovex.de\/de\/leistungen\/mobile\/mobile-web\/\" target=\"_blank\" rel=\"noopener\">auf unserer Website<\/a>. Unser Portfolio umfasst au\u00dferdem die <a href=\"https:\/\/www.inovex.de\/de\/leistungen\/mobile\/app-entwicklung\/\" target=\"_blank\" rel=\"noopener\">Anwendungsentwicklung f\u00fcr Android &amp; iOS<\/a> mit speziellem Fokus auf <a href=\"https:\/\/www.inovex.de\/de\/leistungen\/mobile\/mobile-enterprise\/\" target=\"_blank\" rel=\"noopener\">Enterprise-Apps<\/a>. F\u00fcr direkten Kontakt schreibt an <a href=\"mailto:info@inovex.de\" target=\"_blank\" rel=\"noopener\">info@inovex.de<\/a> oder ruft an unter <a href=\"tel:+497216190210\" target=\"_blank\" rel=\"noopener\">+49 721 619 021-0<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Javascript ist in vielerlei Hinsicht nicht die optimale Wahl, um komplexe Web-Applikationen zu entwickeln. Da die Sprache nicht von Anfang an sorgf\u00e4ltig entworfen wurde, gibt es \u2013 abgesehen von Problemen wie fehlender Typisierung und Modularisierung \u2013 viele kleine Unsch\u00f6nheiten. Um den Entwickler:innen eine ordentlich aufgebaute, saubere Sprache zu bieten, mit der Web-Applikationen erstellt werden k\u00f6nnen, [&hellip;]<\/p>\n","protected":false},"author":38,"featured_media":12487,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"ep_exclude_from_search":false,"footnotes":""},"tags":[70],"service":[420],"coauthors":[{"id":38,"display_name":"Johannes Reuter","user_nicename":"jreuter"}],"class_list":["post-21017","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","tag-web","service-apps"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Polymer in Dart [Tutorial] - inovex GmbH<\/title>\n<meta name=\"description\" content=\"Um den Entwicklern:inne eine ordentlich aufgebaute, saubere Sprache zu bieten, mit der Web-Applikationen erstellt werden k\u00f6nnen, hat Google Dart entworfen.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Polymer in Dart [Tutorial] - inovex GmbH\" \/>\n<meta property=\"og:description\" content=\"Um den Entwicklern:inne eine ordentlich aufgebaute, saubere Sprache zu bieten, mit der Web-Applikationen erstellt werden k\u00f6nnen, hat Google Dart entworfen.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/\" \/>\n<meta property=\"og:site_name\" content=\"inovex GmbH\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/inovexde\" \/>\n<meta property=\"article:published_time\" content=\"2016-04-05T13:47:20+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-17T07:00:04+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/04\/polymer-dart-artikelbild.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2300\" \/>\n\t<meta property=\"og:image:height\" content=\"678\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Johannes Reuter\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/04\/polymer-dart-artikelbild-1024x302.png\" \/>\n<meta name=\"twitter:creator\" content=\"@inovexgmbh\" \/>\n<meta name=\"twitter:site\" content=\"@inovexgmbh\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Johannes Reuter\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"15\u00a0Minuten\" \/>\n\t<meta name=\"twitter:label3\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data3\" content=\"Johannes Reuter\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/polymer-in-dart-tutorial\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/polymer-in-dart-tutorial\\\/\"},\"author\":{\"name\":\"Johannes Reuter\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/person\\\/2e7c8f474580d46832a7666b61f8c1ec\"},\"headline\":\"Polymer in Dart [Tutorial]\",\"datePublished\":\"2016-04-05T13:47:20+00:00\",\"dateModified\":\"2026-03-17T07:00:04+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/polymer-in-dart-tutorial\\\/\"},\"wordCount\":2537,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/polymer-in-dart-tutorial\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2016\\\/04\\\/polymer-dart-artikelbild.png\",\"keywords\":[\"Web\"],\"articleSection\":[\"Applications\",\"General\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/polymer-in-dart-tutorial\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/polymer-in-dart-tutorial\\\/\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/polymer-in-dart-tutorial\\\/\",\"name\":\"Polymer in Dart [Tutorial] - inovex GmbH\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/polymer-in-dart-tutorial\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/polymer-in-dart-tutorial\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2016\\\/04\\\/polymer-dart-artikelbild.png\",\"datePublished\":\"2016-04-05T13:47:20+00:00\",\"dateModified\":\"2026-03-17T07:00:04+00:00\",\"description\":\"Um den Entwicklern:inne eine ordentlich aufgebaute, saubere Sprache zu bieten, mit der Web-Applikationen erstellt werden k\u00f6nnen, hat Google Dart entworfen.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/polymer-in-dart-tutorial\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/polymer-in-dart-tutorial\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/polymer-in-dart-tutorial\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2016\\\/04\\\/polymer-dart-artikelbild.png\",\"contentUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2016\\\/04\\\/polymer-dart-artikelbild.png\",\"width\":2300,\"height\":678,\"caption\":\"Polymer in Dart\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/polymer-in-dart-tutorial\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Polymer in Dart [Tutorial]\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#website\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\",\"name\":\"inovex GmbH\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\",\"name\":\"inovex GmbH\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/inovex-logo-16-9-1.png\",\"contentUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/inovex-logo-16-9-1.png\",\"width\":1921,\"height\":1081,\"caption\":\"inovex GmbH\"},\"image\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/inovexde\",\"https:\\\/\\\/x.com\\\/inovexgmbh\",\"https:\\\/\\\/www.instagram.com\\\/inovexlife\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/inovex\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UC7r66GT14hROB_RQsQBAQUQ\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/person\\\/2e7c8f474580d46832a7666b61f8c1ec\",\"name\":\"Johannes Reuter\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4cd215069ed19f8429692365d40f5a8e94a674eea57579c97b182c853c9cd0d0?s=96&d=retro&r=g6e76acaf394b88ba3914670bfc4db231\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4cd215069ed19f8429692365d40f5a8e94a674eea57579c97b182c853c9cd0d0?s=96&d=retro&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/4cd215069ed19f8429692365d40f5a8e94a674eea57579c97b182c853c9cd0d0?s=96&d=retro&r=g\",\"caption\":\"Johannes Reuter\"},\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/author\\\/jreuter\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Polymer in Dart [Tutorial] - inovex GmbH","description":"Um den Entwicklern:inne eine ordentlich aufgebaute, saubere Sprache zu bieten, mit der Web-Applikationen erstellt werden k\u00f6nnen, hat Google Dart entworfen.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/","og_locale":"de_DE","og_type":"article","og_title":"Polymer in Dart [Tutorial] - inovex GmbH","og_description":"Um den Entwicklern:inne eine ordentlich aufgebaute, saubere Sprache zu bieten, mit der Web-Applikationen erstellt werden k\u00f6nnen, hat Google Dart entworfen.","og_url":"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/","og_site_name":"inovex GmbH","article_publisher":"https:\/\/www.facebook.com\/inovexde","article_published_time":"2016-04-05T13:47:20+00:00","article_modified_time":"2026-03-17T07:00:04+00:00","og_image":[{"width":2300,"height":678,"url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/04\/polymer-dart-artikelbild.png","type":"image\/png"}],"author":"Johannes Reuter","twitter_card":"summary_large_image","twitter_image":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/04\/polymer-dart-artikelbild-1024x302.png","twitter_creator":"@inovexgmbh","twitter_site":"@inovexgmbh","twitter_misc":{"Verfasst von":"Johannes Reuter","Gesch\u00e4tzte Lesezeit":"15\u00a0Minuten","Written by":"Johannes Reuter"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#article","isPartOf":{"@id":"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/"},"author":{"name":"Johannes Reuter","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/2e7c8f474580d46832a7666b61f8c1ec"},"headline":"Polymer in Dart [Tutorial]","datePublished":"2016-04-05T13:47:20+00:00","dateModified":"2026-03-17T07:00:04+00:00","mainEntityOfPage":{"@id":"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/"},"wordCount":2537,"commentCount":0,"publisher":{"@id":"https:\/\/www.inovex.de\/de\/#organization"},"image":{"@id":"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#primaryimage"},"thumbnailUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/04\/polymer-dart-artikelbild.png","keywords":["Web"],"articleSection":["Applications","General"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/","url":"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/","name":"Polymer in Dart [Tutorial] - inovex GmbH","isPartOf":{"@id":"https:\/\/www.inovex.de\/de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#primaryimage"},"image":{"@id":"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#primaryimage"},"thumbnailUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/04\/polymer-dart-artikelbild.png","datePublished":"2016-04-05T13:47:20+00:00","dateModified":"2026-03-17T07:00:04+00:00","description":"Um den Entwicklern:inne eine ordentlich aufgebaute, saubere Sprache zu bieten, mit der Web-Applikationen erstellt werden k\u00f6nnen, hat Google Dart entworfen.","breadcrumb":{"@id":"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#primaryimage","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/04\/polymer-dart-artikelbild.png","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/04\/polymer-dart-artikelbild.png","width":2300,"height":678,"caption":"Polymer in Dart"},{"@type":"BreadcrumbList","@id":"https:\/\/www.inovex.de\/de\/blog\/polymer-in-dart-tutorial\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.inovex.de\/de\/"},{"@type":"ListItem","position":2,"name":"Polymer in Dart [Tutorial]"}]},{"@type":"WebSite","@id":"https:\/\/www.inovex.de\/de\/#website","url":"https:\/\/www.inovex.de\/de\/","name":"inovex GmbH","description":"","publisher":{"@id":"https:\/\/www.inovex.de\/de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.inovex.de\/de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/www.inovex.de\/de\/#organization","name":"inovex GmbH","url":"https:\/\/www.inovex.de\/de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png","width":1921,"height":1081,"caption":"inovex GmbH"},"image":{"@id":"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/inovexde","https:\/\/x.com\/inovexgmbh","https:\/\/www.instagram.com\/inovexlife\/","https:\/\/www.linkedin.com\/company\/inovex","https:\/\/www.youtube.com\/channel\/UC7r66GT14hROB_RQsQBAQUQ"]},{"@type":"Person","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/2e7c8f474580d46832a7666b61f8c1ec","name":"Johannes Reuter","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/4cd215069ed19f8429692365d40f5a8e94a674eea57579c97b182c853c9cd0d0?s=96&d=retro&r=g6e76acaf394b88ba3914670bfc4db231","url":"https:\/\/secure.gravatar.com\/avatar\/4cd215069ed19f8429692365d40f5a8e94a674eea57579c97b182c853c9cd0d0?s=96&d=retro&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4cd215069ed19f8429692365d40f5a8e94a674eea57579c97b182c853c9cd0d0?s=96&d=retro&r=g","caption":"Johannes Reuter"},"url":"https:\/\/www.inovex.de\/de\/blog\/author\/jreuter\/"}]}},"_links":{"self":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/21017","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/users\/38"}],"replies":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/comments?post=21017"}],"version-history":[{"count":5,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/21017\/revisions"}],"predecessor-version":[{"id":66538,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/21017\/revisions\/66538"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/media\/12487"}],"wp:attachment":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/media?parent=21017"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/tags?post=21017"},{"taxonomy":"service","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/service?post=21017"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/coauthors?post=21017"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}