Chciałbym zmienić podejście. Thymeleaf pozwala łatwo dodawać zmienne modelowe do twoich szablonów do użycia w JavaScript. W moich implementacjach zwykle umieszczam te zmienne gdzieś przed zamykającym tagiem nagłówka; aby upewnić się, że są na stronie po załadowaniu WS. Pozwoliłem szablonowi zdecydować, co dokładnie załadować, oczywiście. Jeśli wyświetlasz galerię, wyrenderuj ją tak, jak chcesz i użyj atrybutów danych, aby zdefiniować galerię powiązaną z pewnym kodem JS. Następnie napisz sobie miłe jQuery plugin do obsługi swojej galerii.
Stosunkowo prosty przykład:
Układ domyślny Dekorator: Układ/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>
Należy zwrócić uwagę na ogólne skrypty stopki, a następnie na układ: zdefiniowany fragment div. Ten layout div jest tym, czego użyjemy do włączenia naszej wtyczki jquery potrzebnej do galerii.
plików ze skryptami ogólnych: fragmenty/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>
W skryptach pliku, są 2 fragmenty, które są zawarte od dekoratora. W fragmencie nagłówka użyta jest pomocna ścieżka kontekstu dla warstwy JS, a także domyślna metoda dla samego piekła. Obiekt galerii jest następnie definiowany i przypisywany z naszego modelu. Fragment stopki ładuje bibliotekę jQuery i plik JS głównej witryny, ponownie dla celów tego przykładu.
Strona z leniwym załadowane galerii: 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>
Strona produkty nie ma zbyt wiele na jej temat. Korzystając z domyślnego dekoratora, ta strona zastępuje tytuł strony w nagłówku. Nasz fragment treści zawiera tytuł w znaczniku h1 i pusty element div z atrybutem galerii danych. Ten atrybut jest użyty w naszej wtyczce jQuery do zainicjowania galerii. Wartość jest ustawiona na lazyload, więc nasza wtyczka wie, że musimy znaleźć identyfikatory obrazów w niektórych zmiennych zestaw gdzieś. Mogło to być łatwo puste, jeśli jedyną rzeczą, którą obsługuje nasza wtyczka, jest galeria z leniwymi załadowaniami.
Tak więc układ ładuje niektóre domyślne skrypty i sprytnie rozmieszczony układ: fragmenty, pozwalasz niektórym sekcjom strony ładować biblioteki niezależne od reszty.
Oto prosty przykład kontroler Wiosna, aby pracować z naszej aplikacji: 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";
}
}
Klasa Galeria została rzucił inline w metodzie produktów, w celu uproszczenia naszego przykładu tutaj. Może to być usługa lub repozytorium jakiegoś typu, które zwraca tablicę identyfikatorów lub cokolwiek, czego potrzebujesz.
Nasz jQuery plugin, który stworzyliśmy, mógłby wyglądać tak: 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));
Ostateczne renderowanie strony produktów będzie wyglądać tak:
<!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>
Jak widać , Thymeleaf robi całkiem niezłą robotę, tłumacząc twój model na poprawny JS i dodaje cytaty tam, gdzie jest to potrzebne, i ucieka im również. Po zakończeniu renderowania strony, z wtyczką jQuery na końcu pliku, wszystko, co potrzebne do zainicjowania galerii, powinno być załadowane i gotowe do pracy.
To jest , a nie idealny przykład, ale uważam, że jest to całkiem prosty wzór dla aplikacji internetowej.
Zawsze można użyć 'eval()', chociaż zdecydowanie nie jest to najładniejsze rozwiązanie. – Kejml
Hi Kejml. Dzięki za szybką pomoc. I rzeczywiście eval() działa ;-) Co za brudny hack. Musiałem google eval(), którego zdecydowanie nie mogłem sobie przypomnieć, ale na końcu mój 'inline =" javascript "w połączeniu z' eval ([[$ {pageHelper.documentReady}]]) naprawdę dobrze się sprawdził. Chociaż chciałbym, aby ta kwestia pozostała bezładna przez chwilę, aby zobaczyć, czy istnieje "oficjalny" sposób Thymeleaf tego. W każdym razie. Wielkie dzięki jeszcze raz. Twoje zdrowie. Jan. –
Jasne, nie sądzę, że jest to właściwy sposób na zrobienie tego, dlatego opublikowałem to jako komentarz, a nie jako odpowiedź, ale przynajmniej to może pomóc. Mam nadzieję, że ktoś przyjdzie z poprawną odpowiedzią. Pozdrawiam :) – Kejml