728x90
1. 속성 값 설정
타임리프는 주로 HTML 태그에 th:'속성명' 을 지정하는 방식으로 동작한다.
th:'속성명' 로 속성을 적용하면 기존 속성을 대체한다. 만약 기존 속성이 없으면 새로 만든다.
checkbox 같은 경우 th:checked="true, false" 로 사용한다
<h1>속성 설정</h1>
<input type="text" name="mock" th:name="userA" />
<h1>속성 추가</h1>
- th:attrappend class 속성 뒤에 붙는다 = <input type="text" class="text" th:attrappend="class=' large'" /><br/>
- th:attrprepend class 속성 앞에 붙는다 = <input type="text" class="text" th:attrprepend="class='large '" /><br/>
- th:classappend class 속성에 자연스럽게 추가 = <input type="text" class="text" th:classappend="자연스럽게"><br/>
<h1>checked 처리</h1>
- checked o <input type="checkbox" name="active" th:checked="true" /><br/>
- checked x <input type="checkbox" name="active" th:checked="false" /><br/>
- checked=false <input type="checkbox" name="active" checked="false" /><br/>
2. 반복문
타임리프에서 반복은 th:each 를 사용한다. 추가로 반복에서 사용할 수 있는 여러 상태 값을 지원한다.
index : 0부터 시작하는 값
count : 1부터 시작하는 값
size : 전체 사이즈
even , odd : 홀수, 짝수 여부( boolean )
first , last :처음, 마지막 여부( boolean )
current : 현재 객체
<h1>기본 테이블</h1>
<table border="1">
<tr>
<th>username</th>
<th>age</th>
</tr>
<tr th:each="user : ${characters}">
<td th:text="${user.username}">username</td>
<td th:text="${user.age}">0</td>
</tr>
</table>
<h1>반복 상태 유지</h1>
<table border="1">
<tr>
<th>count</th>
<th>username</th>
<th>age</th>
<th>etc</th>
</tr>
<tr th:each="user, userStat : ${characters}">
<td th:text="${userStat.count}">username</td>
<td th:text="${user.username}">username</td>
<td th:text="${user.age}">0</td>
<td>
index = <span th:text="${userStat.index}"></span>
count = <span th:text="${userStat.count}"></span>
size = <span th:text="${userStat.size}"></span>
even? = <span th:text="${userStat.even}"></span>
odd? = <span th:text="${userStat.odd}"></span>
first? = <span th:text="${userStat.first}"></span>
last? = <span th:text="${userStat.last}"></span>
current = <span th:text="${userStat.current}"></span>
</td>
</tr>
</table>
3. 조건문
if, unless : 타임리프는 해당 조건이 맞지 않으면 태그 자체를 렌더링하지 않는다.
만약 다음 조건이 false 인 경우 ${...} 부분 자체가 렌더링 되지 않고 사라진다
switch : th:switch 와 th:case 를 사용한다. th:case="*" 인 경우 어떤 조건에도 만족하지 않는 기타 에 해당하는 내용을 출력한다
<table border="1">
<tr>
<th>count</th>
<th>username</th>
<th>age</th>
</tr>
<tr th:each="user, userStat : ${characters}">
<td th:text="${userStat.count}"></td>
<td th:text="${user.username}">username</td>
<td>
<span th:text="${user.age}">0</span>
<span th:text="'100보다 작거나 같다'" th:if="${user.age lt 100}"></span>
<span th:text="'100보다 크거나 같지 않다'" th:unless="${user.age ge 100}"></span>
</td>
</tr>
</table>
<h1>switch</h1>
<table border="1">
<tr>
<th>count</th>
<th>username</th>
<th>age</th>
</tr>
<tr th:each="user, userStat : ${characters}">
<td th:text="${userStat.count}">1</td>
<td th:text="${user.username}">username</td>
<td th:switch="${user.age}">
<span th:case="20">[[${user.username}]]</span>
<span th:case="1000">[[${user.username}]]</span>
<span th:case="*">[[${user.username}]]</span>
</td>
</tr>
</table>
4. 주석
1. 표준 HTML 주석 : 자바스크립트의 표준 HTML 주석은 타임리프가 렌더링 하지 않고, 그대로 남겨둔다.
<!-- 내용 -->
2. 타임리프 파서 주석 : 타임리프에서 사용하는 진짜 주석이다. 렌더링에서 주석 부분을 제거한다.
<!--/* 내용 */-->
3. 타임리프 프로토타입 주석 : 얘는 약간 특이한데, HTML 주석에 약간의 구문을 더했다. HTML 파일을 웹 브라우저에서 그대로 열어보면 HTML 주석이기 때문에 이 부분이 웹 브라우저가 렌더링하지 않는다. 타임리프 렌더링을 거치면 이 부분이 정상 렌더링 된다.
=> 즉 html 파일 자체를 열때는 주석처리되어서 보이지만, 타임리프로 랜더링해서 보여줄 때는 내용을 보여주게 된다
<!--/*/<span th:text="${...}"></span>/*/-->
<h1>예시</h1>
<span th:text="${data}">html data</span>
<h1>1. 표준 HTML 주석</h1>
<!--
<span th:text="${data}">html data</span>
-->
<h1>2. 타임리프 파서 주석</h1>
<!--/* [[${data}]] */-->
<!--/* 내용 */-->
<!--*/-->
<h1>3. 타임리프 프로토타입 주석</h1>
<!--/*/
<span th:text="${data}">html data</span>
/*/-->
5. 블록
<th:block th:each="user : ${characters}">
<div>
사용자 이름1 <span th:text="${user.username}"></span>
사용자 나이1 <span th:text="${user.age}"></span>
</div>
<div>
요약 <span th:text="${user.username} + ' / ' + ${user.age}"></span>
</div>
</th:block>
6. 자바스크립트 인라인 : 특히 중요
1) 자바스크립트 인라인 사용하기
<!-- 자바스크립트 인라인 사용 전 -->
<script>
var username1 = [[${user.username}]];
var age1 = [[${user.age}]];
//자바스크립트 내추럴 템플릿
var username2 = /*[[${user.username}]]*/ "test username";
//객체
var user1 = [[${user}]];
</script>
<!-- 자바스크립트 인라인 사용 후 -->
<script th:inline="javascript">
var username3 = [[${user.username}]];
var age2 = [[${user.age}]];
//자바스크립트 내추럴 템플릿
var username4 = /*[[${user.username}]]*/ "test username";
//객체
var user2 = [[${user}]];
</script>
2) 인라인 자바스크립트 each
자바스크립트 안에서 thymeleaf 의 each 반복문을 돌릴 수 있다
[# th:each="반복변수: ${반복대상}"]
~~~ 반복 내용 ~~~~
[/](끝)
<script th:inline="javascript">
[# th:each="user : ${characters}"]
var user[[${userStat.count}]] = [[${user}]];
[/]
</script>
7. 템플릿 조각 : 진짜 중요1
1) 템플릿 조각 사용 방법
태그와 함께 삽입할 템플릿 조각의 경로 지정 ~{경로 :: 템플릿 조각의 이름}템플릿 조각의 이름은 th:fragment="이름" 에서 이름 부분에 해당한다
insert : insert 는 말 그대로 삽입!! 때문에 불러오는 쪽에서 쓰이는 태그 + 템플릿 조각의 태그 까지 모두 들어간다.
-> th:insert="~{경로 :: 템플릿 조각이름}"
replace : replace 는 말 그대로 대체!! 때문에 불러오는 쪽에서 쓰이는 태그를 없애고, 템플릿 조각의 태그가 그 자리를 대체한다.
-> 일반 표현식 : th:replace="~{경로 :: 템플릿 조각이름}"
-> 단순 표현식(단순히 경로+이름만 으로 조각을 넣어도 되는 경우) th:replace="경로 :: 템플릿 조각이름"
파라미터 사용 : 파라미터가 있는 템플릿 조각의 경우 경로+조각명(파라미터) 를 넣어주면 넣어진 파라미터의 값이 그대로 템플릿 조각에게 넘어가고, 템플릿 조각에서 사용할 수 있게 된다.
-> th:replace="~{경로 :: 템플릿 조각명('파라미터1', '파라미터2'...)}"
2) 코드
footer
<body>
<footer th:fragment="copy">
푸터 자리 입니다.
</footer>
<footer th:fragment="copyParam (param1, param2)">
<p>파라미터 자리 입니다.</p>
<p th:text="${param1}"></p>
<p th:text="${param2}"></p>
</footer>
</body>
main
<h2>부분 포함 insert</h2>
<div th:insert="~{template/fragment/footer :: copy}"></div>
<h2>부분 포함 replace</h2>
<div th:replace="~{template/fragment/footer :: copy}"></div>
<h2>부분 포함 단순 표현식</h2>
<div th:replace="template/fragment/footer :: copy"></div>
<h1>파라미터 사용</h1>
<div th:replace="~{template/fragment/footer :: copyParam ('데이터1', '데이터2')}"></div>
</body>
8. 템플릿 레이아웃 - 기본
템플릿 조각이 조각의 일부를 가지고와서 사용했다면 레이아웃은 좀 더 확장된 개념이다.
레이아웃은 일종의 배경그림을 만들어두고, 각 페이지마다 배경그림은 동일하게 세부적인 내용만 내가 수정해서 사용하는 것이다.
즉 <head> 에 속한 JS, CSS 를 갖고 레이아웃을 만들고, 이를 가져와서 각 페이지에 맞게 수정해서 사용하는 것이다.
1) 템플릿 레이아웃 사용방법
- 템플릿 레이아웃은 템플릿 조각과 동일하게 태그와 함께 사용한다. 이때 단순한 값을 넘기는 것이 아닌 태그를 넘길수도 있다. 이때 태그는 ~{::태그} 를 사용한다. 단순한 값은 '값' 을 사용한다
- 미리 생성된 레이아웃에 맞춰서 넘어온 태그의 내용이
=> replace 의 경우 레이아웃에 맞춰 대체된다.
=> insert 의 경우 레이아웃에 맞춰 추가된다.
쉽게 생각해서 레이아웃 개념을 두고, 그 레이아웃에 필요한 코드 조각을 전달해서 완성하는 것으로 이해하면 된다
2) 코드
layout
- insert_body 와 replace_body 를 잘 기억해두자
- replace title 도 기억해두자
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="common_header(title,links)">
<title th:replace="${title}">레이아웃 타이틀</title>
<!-- 공통 -->
<link rel="stylesheet" type="text/css" media="all" th:href="@{/css/awesomeapp.css}">
<link rel="shortcut icon" th:href="@{/images/favicon.ico}">
<script type="text/javascript" th:src="@{/sh/scripts/codebase.js}"></script>
<!-- 추가 -->
<th:block th:replace="${links}"/>
</head>
<body>
<ul th:fragment="insert_body(data)">
<li th:text="${data}"></li>
</ul>
<ul th:fragment="replace_body(data)">
<li th:text="${data}"></li>
</ul>
</body>
Main
- th:replace layout 에 title 과 link 태그가 모두 넘어간다 => 태그를 넘길때는 {::태그명} 을 사용한다
- div 의 경우 하나는 insert, 하나는 replace 이다. 이에 따라서 각 내용이 추가, 대체 될 것이다
<head th:replace="template/layout/baselayout :: common_header(~{::title},~{::link})">
<title>넘어가서 replace 되는 타이틀</title>
<link rel="stylesheet" th:href="@{/css/넘어가서 replace 되는 링크1}">
<link rel="stylesheet" th:href="@{/themes/넘어가서 replace 되는 링크2}">
</head>
<body>
메인 컨텐츠
<div th:insert="template/layout/baselayout :: insert_body('추가되는 내용')"></div>
<div th:replace="template/layout/baselayout :: replace_body('대체되는 내용')">
원본 내용~~~~!!!!
</div>
</body>
9. 템플릿 레이아웃 - 고급
1) 템플릿 레이아웃 고급편
코드를 자세히 확인하면 <html> 에 th:fragment 속성이 정의되어 있다. 이 레이아웃 파일을 기본으로 하고 여기에 필요한 내용을 전달해서 부분부분 변경하는 것으로 이해하면 된다.
즉 html 자체를 th:replace 를 사용해서 변경하는 것이다. 결국 layout.html 에 필요한 내용만을 전달하고 폼은 layout.html 으로 변경한다.
2) 코드
layout
<!DOCTYPE html>
<html th:fragment="layout (title, content)" xmlns:th="http://www.thymeleaf.org">
<head>
<title th:replace="${title}">레이아웃 타이틀</title>
</head>
<body>
<h1>레이아웃 H1</h1>
<div th:replace="${content}">
<p>레이아웃 컨텐츠</p>
</div>
<footer>
레이아웃 푸터
</footer>
</body>
</html>
layoutMain
<!DOCTYPE html>
<html th:replace="~{template/layoutExtend/layout :: layout(~{::title}, ~{::section})}"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>layout으로 넘어가는 타이틀</title>
</head>
<body>
<section>
<h3>레이아웃 기능을 잘 사용하면 html 전체를 혹은 body 전체를 replace 가능하다</h3>
<h3>특히 각페이지의 동일한 부분은 그대로 살리고, 다른 부분만 변경하고 싶을 때 편리하다</h3>
<h3>아래의 section 부분과 위쪽의 title 부분이 넘어가서 title 과 아래의 section 부분만 레이아웃 폼에 맞게 변경된다</h3>
<ul>
<li>각 페이지에 맞게 변경되는 부분1</li>
<li>각 페이지에 맞게 변경되는 부분2</li>
</ul>
</section>
</body>
</html>
Thymeleaf 문법 정리
문법 | 설명 |
th:'html속성명' | 기존의 속성을 대체, 만약 해당 속성이 없다면 추가 |
th:checked="true, false" | true 인 경우 체크박스 체크 false 인 경우 checked 속성 자체를 제거 => 체크 없음 |
th:each="반복에 사용하는 변수 : ${반복대상}" | 반복문 사용법 |
index count size even, oadd first, last current 변수명.stat |
index : 0부터 시작하는 값 count : 1부터 시작하는 값 size : 전체 사이즈 even , odd : 홀수, 짝수 여부( boolean ) first , last :처음, 마지막 여부( boolean ) current : 현재 객체 변수명.stat : 반복의 상태 |
th:if="${조건식}", th:unless="${조건식}" | ${,,,,} 에 해당하는 조건에 맞게 출력 |
th:switch="${조건에 사용되는 변수}" th:case="조건" th:case="*" |
swtich 조건식 case="*" 의 경우 어떤 조건에도 맞지 않는 경우 사용한다 |
<!--/* 내용 */--> | 타임리프에서 사용하는 주석으로 렌더링에서 주석 부분을 제거 |
<th:block></th:block> | 해당 태그 내부를 하나의 블록으로 잡는다 => 여러개의 태그라도 하나의 태그로 만드는 느낌? |
<script th:inline="javascript"> | thymeleaf 가 지원하는 JS - var name = [[${.....}]] 으로 값을 바로 담을 수 있다 - var object = [[${...}]] 으로 객체를 담을 수 있다 => 이때 담겨진 객체는 JSON 형태로 변환되어 담긴다 |
th:insert="~{경로 :: 템플릿 조각이름}" | insert 는 말 그대로 삽입!! 때문에 불러오는 쪽에서 쓰이는 태그 + 템플릿 조각의 태그 |
th:replace="~{경로 :: 템플릿 조각이름}" | 불러오는 쪽에서 쓰이는 태그를 없애고, 템플릿 조각의 태그가 그 자리를 대체 |
th:replace="경로 :: 템플릿 조각이름" | replace 단순 표현식 |
th:replace="~{경로 :: 템플릿 조각명('파라미터1', '파라미터2'...)}" | 템플릿 조각 파라미터 사용하기 |
th:replace="~{경로 :: 템플릿 조각이름(~{::태그명})}" | 템플릿 조각에 태그를 넘겨서 레이아웃에 맞춰 해당 태그를 변경할 수 있다 |
'Front-End > thymeleaf' 카테고리의 다른 글
Thymeleaf 공부하기 (1) : 텍스트, 변수, 기본 객체, 유틸리티 객체와 날짜, url 링크, 리터럴, 연산 (0) | 2022.10.11 |
---|
댓글