würde ich den Ansatz ändern. Mit Thymeleaf können Sie einfach Modellvariablen in Ihre Vorlagen einfügen, um sie in Javascript zu verwenden. In meinen Implementierungen setze ich diese Variablen normalerweise vor das schließende Header-Tag; um sicherzustellen, dass sie auf der Seite sind, sobald JS geladen wird. Ich lasse die Vorlage natürlich entscheiden, was genau geladen werden soll. Wenn Sie eine Galerie anzeigen, rendern Sie sie wie gewünscht und verwenden Sie Datenattribute, um die Galerie zu definieren, die sich auf einen JS-Code bezieht. Dann schreibe dir eine nette jQuery plugin für deine Galerie.
Ein relativ einfaches Beispiel:
Standard-Layout Decorator: Layout/default.html
<!doctype html>
<html xmlns:layout="http://www.thymeleaf.org" xmlns:th="http://www.thymeleaf.org">
<head>
<title>My Example App</title>
<object th:remove="tag" th:include="fragments/scripts :: header" />
</head>
<body>
<div layout:fragment="content"></div>
<div th:remove="tag" th:replace="fragments/scripts :: footer"></div>
<div th:remove="tag" layout:fragment="footer-scripts"></div>
</body>
</html>
Die Sache zu bemerken ist hier die Einbeziehung der generischen Fußzeile Skripte und dann ein Layout: Fragment div definiert. Mit diesem Layout-Div werden wir unser jQuery-Plugin für die Galerie verwenden.
Datei mit allgemeinen Skripte: Fragmente/scripts.html
<div th:fragment="header" xmlns:th="http://www.thymeleaf.org">
<script type="text/javascript" th:inline="javascript">
/*<![CDATA[*/
var MY_APP = {
contextPath: /*[[@{/}]]*/,
defaultTheme: /*[[${theme == null} ? null : ${theme}]]*/,
gallery: {
theme: /*[[${gallery == null} ? null : ${gallery.theme}]]*/,
images: /*[[${gallery == null} ? null : ${gallery.images}]]*/,
names: /*[[${gallery == null} ? null : ${gallery.names}]]*/
}
};
/*]]>*/
</script>
</div>
<div th:fragment="footer" xmlns:th="http://www.thymeleaf.org">
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/my_app.js"></script>
</div>
In den Skripten Datei gibt es zwei Fragmente, die aus dem Dekorateur enthalten sind. Im Header-Fragment ist ein hilfreicher Kontextpfad für die JS-Ebene enthalten, ebenso wie ein DefaultTheme nur zum Spaß. Ein Galerieobjekt wird dann von unserem Modell definiert und zugewiesen. Das Fußzeilenfragment lädt die jQuery-Bibliothek und eine JS-Hauptdateidatei erneut, und zwar für die Zwecke dieses Beispiels.
Eine Seite mit einer faulen belasteten Galerie: products.html
<html layout:decorator="layout/default" xmlns:layout="http://www.thymeleaf.org/" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Products Landing Page</title>
</head>
<body>
<div layout:fragment="content">
<h1>Products</h1>
<div data-gallery="lazyload"></div>
</div>
<div th:remove="tag" layout:fragment="footer-scripts">
<script type="text/javascript" src="/js/my_gallery.js"></script>
</div>
</body>
</html>
Unsere Produkte Seite nicht viel drauf. Mit dem Standard-Dekorator überschreibt diese Seite den Seitentitel im Kopf. Unser Inhaltsfragment enthält einen Titel in einem h1 -Tag und ein leeres div mit einem Datengalerienattribut. Dieses Attribut wird in unserem jQuery-Plugin verwendet, um die Galerie zu initialisieren. Der Wert ist auf lazyload gesetzt, also weiß unser Plugin, dass wir die Bild-IDs irgendwo in einer Variablen finden müssen. Dies könnte leicht leer gewesen sein, wenn das einzige, was unser Plugin unterstützt, eine Lazy Loaded Gallery ist.
So lädt das Layout einige Standard-Skripte und mit geschickt platzierten Layout: Fragmente, erlauben Sie bestimmten Bereichen der Website Bibliotheken unabhängig von den Rest zu laden.
Hier ist ein grundlegendes Feder Controller Beispiel mit unseren App zu arbeiten: MyController.java
@Controller
public class MyController {
@RequestMapping("/products")
public String products(Model model) {
class Gallery {
public String theme;
public int[] images;
public String[] names;
public Gallery() {
this.theme = "basic";
this.images = new int[] {8,5,3,2};
this.names = new String[] {"Hey", "\"there's\"", "foo", "bar"};
}
}
model.addAttribute("gallery", new Gallery());
return "products";
}
}
Die Galerie Klasse inline in der Produkte-Methode geworfen wurde, unser Beispiel hier zu vereinfachen. Dies könnte leicht ein Service oder ein Repository eines Typs sein, der ein Array von Identifikatoren oder was auch immer Sie benötigen zurückgibt.
Unser jQuery-Plugin, das wir erstellt haben, könnte so etwas wie so aussehen: my_gallery.js
(function($) {
var MyGallery = function(element) {
this.$el = $(element);
this.type = this.$el.data('gallery');
if (this.type == 'lazyload') {
this.initLazyLoadedGallery();
}
};
MyGallery.prototype.initLazyLoadedGallery = function() {
// do some gallery loading magic here
// check the variables we loaded in our header
if (MY_APP.gallery.images.length) {
// we have images... sweet! let's fetch them and then do something cool.
PhotoGallery.load(MY_APP.gallery.images).loadTheme({
name: MY_APP.gallery.theme
});
// or if load() requires separate params
var imgs = MY_APP.gallery.images;
PhotoGallery.load(imgs[0],imgs[1],imgs[2],imgs[3]).loadTheme({
name: MY_APP.gallery.theme
});
}
};
// the plugin definition
$.fn.myGallery = function() {
return this.each(function() {
if (!$.data(this, 'myGallery')) {
$.data(this, 'myGallery', new MyGallery(this));
}
});
};
// initialize our gallery on all elements that have that data-gallery attribute
$('[data-gallery]').myGallery();
}(jQuery));
Die endgültige Wiedergabe der Produkte Seite würde wie so aussehen:
<!doctype html>
<html>
<head>
<title>Products Landing Page</title>
<script type="text/javascript">
/*<![CDATA[*/
var MY_APP = {
contextPath: '/',
defaultTheme: null,
gallery: {
theme: 'basic',
images: [8,5,3,2],
names: ['Hey','\"there\'s\"','foo','bar']
}
};
/*]]>*/
</script>
</head>
<body>
<div>
<h1>Products</h1>
<div data-gallery="lazyload"></div>
</div>
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/my_app.js"></script>
<script type="text/javascript" src="/js/my_gallery.js"></script>
</body>
</html>
Wie Sie sehen können , Thymeleaf ist ziemlich gut darin, Ihr Modell in gültiges JS zu übersetzen und fügt die Zitate dort hinzu, wo sie gebraucht werden und entgeht ihnen auch. Sobald die Seite mit dem jQuery-Plugin am Ende der Datei fertig ist, sollte alles, was zur Initialisierung der Galerie benötigt wird, geladen werden und fertig sein.
Das ist nicht ein perfektes Beispiel, aber ich denke, es ist ein ziemlich geradliniges Design-Muster für eine Web-App.
Nun, Sie können immer 'eval()' verwenden, obwohl es definitiv nicht die schönste Lösung ist. – Kejml
Hallo Kejml. Danke für diese schnelle Hilfe. Und in der Tat funktioniert eval() ;-) Was für ein schmutziger Hack. Hatte google eval() googeln, da ich mich definitiv nicht wirklich erinnern konnte, aber am Ende funktionierte mein 'inline =" javascript "' in Verbindung mit 'eval ([{{{Helper.documentReady}]]) wirklich gut. Obwohl ich diese Frage gerne für einen Moment unbeachtet lassen würde, um zu sehen, ob es einen "offiziellen" Thymelaf-Weg gibt. Jedenfalls. Vielen Dank nochmal. Prost. John. –
Sicher, ich denke nicht, dass dies der richtige Weg ist, deshalb habe ich es als Kommentar gepostet, nicht als Antwort, aber es bringt dich am wenigsten in Gang. Hoffentlich kommt jemand mit der richtigen Antwort. Prost :) – Kejml