Подтвердить что ты не робот

Thymeleaf th: inline = "javascript" выпуск

Я не знаю, как решить следующее: я хотел бы позволить моей модели генерировать реальный javascript динамически на основе некоторой логики модели.

Этот последний фрагмент кода javascript затем должен быть добавлен в часть $(document).ready {} моей html-страницы.

Дело в том, что если я использую inline = "javascript", код будет процитирован как мой getter - это String (так оно упоминается в документе Thymeleaf, но это не то, что мне нужно;)

Если я использую inline = "text" in, не цитируется, но все кавычки вместо этого исключаются;-) - также приятно, но непригодно 8)

Если я попробую inline = "none", ничего не произойдет.

Вот примеры

Моя модель getter создала следующий код Javascript.

PageHelper class

public String documentReady() {

// do some database operations to get the numbers 8,5,3,2
return "PhotoGallery.load(8,5,3,2).loadTheme(name='basic')";

}

Итак, если я сейчас попробую inline = "javascript"

<script th:inline="javascript">
/*<![CDATA[*/
    jQuery().ready(function(){
        /*[[${pageHelper.documentReady}]]*/
    });
/*]]>*/
</script>

будет отображаться

<script>
/*<![CDATA[*/
    jQuery().ready(function(){
        'PhotoGallery.load(8,5,3,2).loadTheme(name=\'basic\')'
    });
/*]]>*/
</script>

Что не помогает, поскольку это строковый литерал, не более того (так с ним и занимается Thymeleaf).

Итак, если я попробую inline = "text"

<script>
/*<![CDATA[*/
    jQuery().ready(function(){
        PhotoGallery.load(8,5,3,2).loadTheme(name=&#39;basic&#39;)
    });
/*]]>*/
</script>

Что скрывает кавычки.

inline = "none" Я действительно не понимаю, поскольку он ничего не делает

<script>
/*<![CDATA[*/
    jQuery().ready(function(){
        [[${pageHelper.documentReady}]]
    });
/*]]>*/
</script>

Честно говоря, я понятия не имею, как решить эту проблему, и, надеюсь, кто-то там знает, как с этим справиться.

Большое спасибо заранее ура Джон

4b9b3361

Ответ 1

Я бы изменил подход. Thymeleaf легко позволяет добавлять переменные модели в ваши шаблоны для использования в Javascript. В моих реализациях я обычно помещаю эти переменные где-то перед закрывающим тегом заголовка; чтобы они были на странице после загрузки JS. Я позволю шаблону решить, что именно загружать, конечно. Если вы показываете галерею, тогда визуализируйте ее так, как вы, и используйте атрибуты данных, чтобы определить галерею, относящуюся к некоторому JS-коду. Затем напишите себе приятный плагин jQuery для обработки вашей галереи.

Относительно базовый пример:

По умолчанию 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>

То, что следует заметить здесь, - это включение общих сценариев нижнего колонтитула, а затем макет: определение фрагмента div. Этот макет div - это то, что мы собираемся использовать для включения нашего плагина jQuery, необходимого для галереи.

Файл с общими скриптами: fragments/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>

В файле сценариев есть два фрагмента, которые включены в декоратор. В фрагменте заголовка полезный контекстный путь включен для уровня JS, а также для defaultTheme только для ада. Затем объект галереи определяется и назначается из нашей модели. Фрагмент нижнего колонтитула загружает библиотеку jQuery и файл JS основного сайта снова для целей этого примера.

Страница с ленивой загруженной галереей: 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>

На нашей странице продуктов не так много. Используя декоратор по умолчанию, эта страница отменяет заголовок страницы в голове. Наш фрагмент контента включает заголовок в теге h1 и пустой div с атрибутом галереи данных. Этот атрибут - это то, что мы будем использовать в нашем плагине jQuery для инициализации галереи. Значение установлено на lazyload, поэтому наш плагин знает, что нам нужно найти идентификаторы изображений в некоторой переменной, заданной где-нибудь. Это может быть легко пустым, если единственное, что поддерживает наш плагин, - это lazyloaded gallery.

Таким образом, макет загружает некоторые скрипты по умолчанию и с умным размещением макета: фрагменты, вы позволяете определенным разделам сайта загружать библиотеки независимо от остальных.

Вот пример базового Spring контроллера для работы с нашим приложением: 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";
  }
}

Класс Gallery был брошен inline в методе продуктов, чтобы упростить наш пример здесь. Это может быть просто сервис или репозиторий какого-либо типа, который возвращает массив идентификаторов или все, что вам нужно.

Наш плагин jQuery, который мы создали, может выглядеть примерно так: 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 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));

Окончательная рендеринг страницы продуктов будет выглядеть так:

<!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>

Как вы можете видеть, Thymeleaf делает довольно хорошую работу по переводу вашей модели на действительную JS и фактически добавляет кавычки там, где это необходимо, и избегает их. Когда страница заканчивается рендерингом, с плагином jQuery в конце файла все необходимое для инициализации галереи должно быть загружено и готово к работе.

Это не идеальный пример, но я думаю, что это довольно простой дизайн для веб-приложения.