Статьи

Thymeleaf — фрагменты и ангулярный роутер, частичные виды

Еще одна из множества интересных функций тимелиста — это возможность рендеринга фрагментов шаблонов — я обнаружил, что это особенно полезная функция для использования с AngularJ.

Маршрутизатор AngularJS $ routeProvider или AngularUI можно настроить так, чтобы он возвращал частичные представления для разных «путей», при этом использование thymeleaf для возврата этих частичных представлений работает очень хорошо.

Рассмотрим простой поток CRUD, в котором представления маршрутизатора AngularUI определены следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
app.config(function ($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise("list");
 
    $stateProvider
        .state('list', {
            url:'/list',
            templateUrl: URLS.partialsList,
            controller: 'HotelCtrl'
        })
        .state('edit', {
            url:'/edit/:hotelId',
            templateUrl: URLS.partialsEdit,
            controller: 'HotelEditCtrl'
        })
        .state('create', {
            url:'/create',
            templateUrl: URLS.partialsCreate,
            controller: 'HotelCtrl'
        });
});

Вышеприведенный templateUrl представляет собой частичное представление, отображаемое при активации соответствующего состояния, здесь они определяются с использованием переменных javascript и устанавливаются с использованием шаблонов thymeleaf таким образом (чтобы чисто разрешить контекстный путь развернутого приложения в качестве корневого пути):

1
2
3
4
5
6
7
8
<script th:inline="javascript">
    /*<![CDATA[*/
    var URLS = {};
    URLS.partialsList = /*[[@{/hotels/partialsList}]]*/ '/hotels/partialsList';
    URLS.partialsEdit = /*[[@{/hotels/partialsEdit}]]*/ '/hotels/partialsEdit';
    URLS.partialsCreate = /*[[@{/hotels/partialsCreate}]]*/ '/hotels/partialsCreate';
    /*]]>*/
</script>

Теперь рассмотрим одно из определений фрагмента, скажем, одно, которое обрабатывает список:

файл: templates / hotels /partList.html

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" layout:decorator="layout/sitelayout">
<head>
    <title th:text="#{app.name}">List of Hotels</title>
    <link rel="stylesheet" th:href="@{/webjars/bootstrap/3.1.1/css/bootstrap.min.css}"
    <link rel="stylesheet" th:href="@{/webjars/bootstrap/3.1.1/css/bootstrap-theme.css}"
    <link rel="stylesheet" th:href="@{/css/application.css}" href="../../static/css/application.css"/>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-xs-12">
            <h1 class="well well-small">Hotels</h1>
        </div>
    </div>
    <div th:fragment="content">
        <div class="row">
            <div class="col-xs-12">
                <table class="table table-bordered table-striped">
                    <thead>
                    <tr>
                        <th>ID</th>
                        <th>Name</th>
                        <th>Address</th>
                        <th>Zip</th>
                        <th>Action</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr ng-repeat="hotel in hotels">
                        <td>{{hotel.id}}</td>
                        <td>{{hotel.name}}</td>
                        <td>{{hotel.address}}</td>
                        <td>{{hotel.zip}}</td>
                        <td><a ui-sref="edit({ hotelId: hotel.id })">Edit</a> | <a
                                ng-click="deleteHotel(hotel)">Delete</a></td>
                    </tr>
                    </tbody>
                </table>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-12">
                <a ui-sref="create" class="btn btn-default">New Hotel</a>
            </div>
        </div>
    </div>
</div>
</body>
</html>

Самое замечательное в этом листе — это то, что это представление можно открыть в браузере и просмотреть. Чтобы вернуть часть представления, которая в данном случае является разделом, который начинается с «th: фрагмент =» контент », все, что мне нужно сделать, это вернуть имя представления как« hotels / частичный список :: контент » !

Тот же подход можно использовать для обновления и создания представлений.

Одна часть, которую я оставил открытой, касается того, как URI в пользовательском интерфейсе, который является «/ hotels / partialsList», сопоставляется с «hotels /partList :: content», с помощью Spring MVC это легко сделать через View Controller, который по существу способ вернуть имя представления без необходимости проходить через контроллер и может быть настроен следующим образом:

01
02
03
04
05
06
07
08
09
10
11
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
 
 @Override
 public void addViewControllers(ViewControllerRegistry registry) {
  registry.addViewController("/hotels/partialsList").setViewName("hotels/partialsList::content");
  registry.addViewController("/hotels/partialsCreate").setViewName("hotels/partialsCreate::content");
  registry.addViewController("/hotels/partialsEdit").setViewName("hotels/partialsEdit::content");
 }
 
}

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

  • Образец, который следует этому шаблону, доступен по адресу github — https://github.com/bijukunjummen/spring-boot-mvc-test