0. 이전 기본 문법
- <html xmlns:th="http://www.thymeleaf.org">
- 타임리프 사용 선언
- 타임리프 사용 선언
- th : PROPERTY = " @{} or ${} or | | or ( )"
- PROPERTY ex: name, class 같은거 의미
- 타임리프는 th:로 타임리프 문법이 시작된다.
- th에 적용할 property를 쓰고 " " 내부에 적용하고 싶은 문법을 적용한다.
- 어지간한 property는 다 th: property 종류 가능하다.
- th: property를 해도 그냥 property도 작성을 하는데
이는 렌더링 전에는 그냥 property가 적용되고
렌더링 후에는 th: property가 적용된다.
- @{} : url 경로
- ${} : controller로 부터 받아온 model 객체의 key를 작성하면 value를 반환해줌
- | | : 리터럴로 JS의 벡틱 같은 역할이라고 보면 된다.
- 타임리프에서 문자와 표현식 등은 분리되어 있기 때문에 더해서 사용
<span th:text="'Welcome to our application, ' + ${user.name} + '!'">
<span th:text="|Welcome to our application, ${user.name}!|">
- 타임리프에서 문자와 표현식 등은 분리되어 있기 때문에 더해서 사용
- ()
- @{} 내부에서 model로받아온 정보를 변수를 설정해서 pathvariable로 사용하고 싶을 때
- 쿼리 파라미터도 사용 가능
th:href="@{/basic/items/{itemId}(itemId=${item.id}, query='test')}"
생성 링크: http://localhost:8080/basic/items/1?query=test
- th:each
반복문
1. 타임리프 특징
- SSR
- natural template : 순수 html을 최대한 유지하는 특징을 가짐
- 스프링 통합 지원
2. 기본 기능
- 타임리프 사용 선언 : <html xmlns:th="http://www.thymeleaf.org">
- 참고: https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#standard-expression-syntax
• 간단한 표현:
◦ 변수 표현식: ${...}
◦ 선택 변수 표현식: *{...}
◦ 메시지 표현식: #{...}
◦ 링크 URL 표현식: @{...}
◦ 조각 표현식: ~{...}
• 리터럴
◦ 텍스트: 'one text', 'Another one!',…
◦ 숫자: 0, 34, 3.0, 12.3,…
◦ 불린: true, false
◦ 널: null
◦ 리터럴 토큰: one, sometext, main,…
• 문자 연산:
◦ 문자 합치기: +
◦ 리터럴 대체: |The name is ${name}|
• 산술 연산:
◦Binary operators: +, -, *, /, %
◦Minus sign (unary operator): -
• 불린 연산:
◦Binary operators: and, or
◦Boolean negation (unary operator): !, not
• 비교와 동등:
◦ 비교: >, <, >=, <= (gt, lt, ge, le)
◦ 동등 연산: ==, != (eq, ne)
• 조건 연산:
◦If-then: (if) ? (then)
◦If-then-else: (if) ? (then) : (else)
◦Default: (value) ?: (defaultvalue)
• 특별한 토큰:
◦No-Operation: _
3. text,utext
- text
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>컨텐츠에 데이터 출력하기</h1>
<ul>
<li>th:text 사용 = <span th:text="${data}"></span></li>
<li>컨텐츠 안에서 직접 출력하기 = [[${data}]]</li>
</ul>
</body>
</html>
- utext
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>text vs utext</h1>
<ul>
<li>th:text = <span th:text="${data}"></span></li>
<li>th:utext = <span th:utext="${data}"></span></li>
</ul>
<h1><span th:inline="none">[[...]] vs [(...)]</span></h1>
<ul>
<li><span th:inline="none">[[...]] = </span>[[${data}]]</li>
<li><span th:inline="none">[(...)] = </span>[(${data})]</li>
<li>[[...]] = [[${data}]]</li>
<li>[(...)] = [(${data})]</li>
</ul>
</body>
</html>
- 텍스트 - text
- html content에 data를 출력할 때 사용
- th:text="${data}"
- [[${data}]]
- html content에 data를 출력할 때 사용
- 텍스트 - utext
- html tag의 속성이 아닌 html content 안에서 직접 데이터를 출력하고 싶을 경우 사용
- th:text="${data}" -> th:utext="${data}"
- [[${data}]] -> [(${data})]
- html tag의 속성이 아닌 html content 안에서 직접 데이터를 출력하고 싶을 경우 사용
4. meta 특징
4.1. Escape
- http 요청으로 들어온 값에서 html 형식의 code(특수문자: <,>,$,@)가 존재시 컴퓨터는 이를 html로 인식할지 아니면 그 자체를 문자로 인식해야될지 모른다. 그래서 thymeleaf는 default로 특수문자를 문자로 인식하기로 했다.
- model로부터 받아온 값은 client가 작성한 값인 경우가 많은데 이 때 사용자들이 <> 등등 별의 별걸 다 써서 이스케이프로 태그 처리되는 문제를 막을 필요가 있다.
- HTML 태그를 문자로 표현할 수 있는 방법을 HTML 엔티티라고 한다. < = < > = >
- 특수문자를 HTML 엔티티로 변경하는 과정을 Escape라고 한다.
- th:text="<b>abc</b>" 이렇게 변수 표현식이 아닌 값이 직접 들어온 경우 에러난다.
- 작동 순서
- http 요청 params data : "<b> Spring! <b>"
- thymeleaf 인코딩(Escape 수행) : <span th:text="${data}"></span> - 눈에는 안보임
- th:text="${data}" -> th:text= "<b> Spring! <b>" 으로 나타남 -> UI에서 escape 된다.
- UI 나타남: <b>Spring</b>
- 소스코드 : <b> Spring! <b> 이 아니라 th:text="<b>Spring</b>" 로 변경됨.
- 이유: < > 해당 특수기호를 실제 문자 형식으로 UI에 나타내고 싶기 때문, <b>로 적혀있으면 UI 표현시 html 코드로 인식해서 굵은 글씨로 바꿔버림
4.2. Unescape
- escape 기능을 사용하지 않기 위해서 thymeleaf가 제공하는 기능이 존재한다.
- 이런 기능이 있다는 것을 보여주기 위함이고 꼭 필요시만 사용할 것
text - utext 차이점 - 중괄호 대괄호
- text 표현 방식 2가지
- th:text="${data}"
- [[${data}]] : [ [ ] ]
- utext 표현 방식 2가지
- th:utext="${data}"
- [(${data})] : [ ( ) ]
기타
th:inline="none" : 중괄호 대괄호를 thymeleaf 코드로 해석하지 말라는 설정
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>text vs utext</h1>
<ul>
<li>th:text = <span th:text="${data}"></span></li>
<li>th:utext = <span th:utext="${data}"></span></li>
</ul>
<h1><span th:inline="none">[[...]] vs [(...)]</span></h1>
<ul>
<li><span th:inline="none">[[...]] = </span>[[${data}]]</li>
<li><span th:inline="none">[(...)] = </span>[(${data})]</li>
<li>[[...]] = [[${data}]]</li>
<li>[(...)] = [(${data})]</li>
</ul>
</body>
</html>
5. 변수 - SpringEL
- 변수 - SpringEL: spring이 제공하는 표현식을 사용 가능
- ${...} : Object, List, Map 으로 들어온 data 모두 처리 가능 + 지역변수도 가능
- 지역 변수는 해당 tag 내부에서만 작동
//object
th:text="${user.username} == [[${user.username}]]
th:text="${user['username']}" == [[${user['username']}]]
th:text="${user.getUsername()}" == [[${user.getUsername()}]]
//List
th:text="${users[0].username}"
th:text="${users[0]['username']}"
th:text="${users[0].getUsername()}"
//Map
th:text="${userMap['userA'].username}"
th:text="${userMap[userA]['username']}"
th:text="${userMap[userA].getUsername()}"
//지역변수 th:with
th:with="first=${users[0]}" // first라는 지역변수
th:text="${first.username}" // 지역변수는 선언한 태그 내에서만 사용 가능
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>SpringEL 표현식</h1>
<ul>Object
<li>${user.username} = <span th:text="${user.username}"></span></li>
<li>${user.username} = <span>[[${user.username}]]</span></li>
<p></p>
<li>${user['username']} = <span th:text="${user['username']}"></span></li>
<li>${user['username']} = <span>[[${user['username']}]]</span></li>
<p></p>
<li>${user.getUsername()} = <span th:text="${user.getUsername()}"></span></li>
<li>${user.getUsername()} = <span>[[${user.getUsername()}]]</span></li>
</ul>
<p th:inline="none"> List, Map 도 [[]] 동일하게 작용, th:inline="none" 사용 주의<p/>
<ul>List
<li>${users[0].username} = <span th:text="${users[0].username}"></span></li>
<li>${users[0]['username'] = <span th:text="${users[0]['username']}"></span></li>
<li>${users[0].getUsername()} = <span th:text="${users[0].getUsername()}"></span></li>
</ul>
<ul>Map
<li>${userMap['userA'].username} = <span th:text="${userMap['userA'].username}"></span></li>
<li>${userMap[userA].username} = <span th:text="${userMap[userA].username}"></span></li>
<li>${userMap[userA]['username']} = <span th:text="${userMap[userA]['username']}"></span></li>
<li>${userMap[userA].getUsername()} = <span th:text="${userMap[userA].getUsername()}"></span></li>
<li>${userMap[userA].getUsername()} = <span th:text="${userMap[userA].getUsername()}"></span></li>
</ul>
<h1>지역 변수 - (th:with)</h1>
<div th:with="first=${users[0]}">
<p>처음 사람의 이름은 <span th:text="${first.username}"> 1st 사람이름 </span></p>
</div>
</body>
</html>
5. 기본 객체
- url
http://localhost:8080/basic/basic-objects?paramData=HelloParam
- controller : spring 3.0 이후부터 Moel에 담아서 보내줘야한다.
@GetMapping("/basic-objects")
public String basicObjects(Model model, HttpServletRequest request, HttpServletResponse response, HttpSession session){
session.setAttribute("sessionData", "Hello Session");
model.addAttribute("request", request);
model.addAttribute("response", response);
model.addAttribute("servletContext", request.getServletContext());
return "basic/basic-objects";
}
@Component("helloBean")
static class HelloBean{
public String hello(String data){
return "Hello " + data;
};
}
- 스프링 부트 3.0 이전
- controller에서 model에 따로 기본 객체를 담지 않아도 thymeleaf에서 제공
<span th:text="${#request}"></span>
<span th:text="${#response}"></span>
<span th:text="${#session}"></span>
<span th:text="${#servletContext}"></span>
<span th:text="${#locale}"></span>
- 스프링 부트 3.0 이후
- thymeleaf에서 일부 제공 안함. controller에서 model에 따로 기본 객체를 담아야한다.
// 3.0 이후에도 제공하는 것들
<span th:text="${request}"></span>
<span th:text="${response}"></span>
<span th:text="${servletContext}"></span>
// 3.0 이후에도 제공하는 것들
// session은 기본 제공되지만 ${#session} -> ${session} 으로 변경
<span th:text="${session}"></span>
<span th:text="${#locale}"></span>
- 편의 객체
하도 자주 써서 제공해주는 것- params: request.getParameter("paramData") 필요 없음 -> 대신 url에서 query문이 들어와야함
- session: controller에 session.setAttribute("sessionData", "Hello Session"); 넣어야 함
- 스프링 bean 접근: @로 접근
<span th:text="${param.paramData}"></span>
<span th:text="${session.sessionData}"></span>
<span th:inline="none"> * session.setAttribute("sessionData", "Hello Session"); 필요</span></li>
<span th:text="${@helloBean.hello('spring!')}"></span>
6. thymeleaf 유틸리티 객체
- ${#유틸리티명.필요method}
유틸리티 종류
- #message : 메시지, 국제화 처리
- #uris : URI 이스케이프 지원
- #dates : java.util.Date 서식 지원
- #calendars : java.util.Calendar 서식 지원
- #temporals : 자바8 날짜 서식 지원
- #numbers : 숫자 서식 지원
- #strings : 문자 관련 편의 기능
- #objects : 객체 관련 기능 제공
- #bools : boolean 관련 기능 제공
- #arrays : 배열 관련 기능 제공
- #lists, #sets, #maps : 컬렉션 관련 기능 제공
- #ids : 아이디 처리 관련 기능 제공, 뒤에서 설명
타임리프 유틸리티 객체
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#expression-utility- objects
유틸리티 객체 예시
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#appendix-b-expression- utility-objects
존재 정도만 파악하고 필요시 찾아보기
6.1. #temporals : 자바8 날짜 서식 지원
- spring menual에 존재하지 않아서 작성
- springboot-thymeleaf에 해당 library가 내장되어있다.
- controller
- model에 model.addAttribute("localDateTime", LocalDateTime.now()); 추가
1. "localDateTime" default로 사용
${#temporals.format(localDateTime, 'yyyy-MM-dd HH:mm:ss<변경가능>')}
2. temporals util 사용
<span th:text="${#temporals.day(localDateTime)}"></span>
<span th:text="${#temporals.month(localDateTime)}"></span>
<span th:text="${#temporals.monthName(localDateTime)}"></span>
<span th:text="${#temporals.monthNameShort(localDateTime)}"></span>
<span th:text="${#temporals.year(localDateTime)}"></span>
<span th:text="${#temporals.dayOfWeek(localDateTime)}"></span>
<span th:text="${#temporals.dayOfWeekName(localDateTime)}"></span>
<span th:text="${#temporals.dayOfWeekNameShort(localDateTime)}"></span>
<span th:text="${#temporals.hour(localDateTime)}"></span>
<span th:text="${#temporals.minute(localDateTime)}"></span>
<span th:text="${#temporals.second(localDateTime)}"></span>
<span th:text="${#temporals.nanosecond(localDateTime)}"></span>
7. url 링크
- 중요
- @{...} 사용
- cf) spring bean의 ${@...} 랑 다름
- controller
@GetMapping("/link")
public String link(Model model){
model.addAttribute("param1", "data1");
model.addAttribute("param2", "data2");
return "basic/link";
}
종류 4가지
- 기본 role
- () : queary params
- ${} : pathvariable, 경로변수로 이용, 물론 () 내부에 경로변수로 사용될 변수들이 존재해야한다.
- th:href="@{/hello}" : 해당 url로 이동
- http://localhost:8080/hello
- th:href="@{/hello(param1=${param1}, param2=${param2})}" : 해당 url로 이동 + query문도 넣음
- http://localhost:8080/hello?param1=data1¶m2=data2
- th:href="@{/hello/{param1}/{param2}(param1=${param1}, param2=$ {param2})}" : 해당 url로 이동, 경로변수 넣기
- http://localhost:8080/hello/data1/data2
- th:href="@{/hello/{param1}(param1=${param1}, param2=$ {param2})}" : 경로변수, query 문 혼합
- http://localhost:8080/hello/data1?param2=data2
8. literals
- 문자: 'hello'
- 숫자: 10
- boolean: true , false
- null: null
- 실수 자주 하는 부분
- thymeleaf에서 문자 리터럴은 항상 '' 로 감싸야한다. -> 공백없이 이어나가는 문자에 한해서 생략해도 가능
- 공백 없이 쭉 이어진다면 하나의 의미있는 토큰으로 인지해서 다음과 같이 작은 따옴표를 생략할 수 있다.
룰: A-Z , a-z , 0-9 , [] , . , - , _
- literals 대체
- | ... | : 공백 상관없이 그냥 막써도 됨 ex)</span th:text="|hello ${data}|">
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>리터럴</h1>
<ul>
<!-- 예외 코드 - thymeleaf 문자 리터럴은 '' 없을 때 뛰어쓰기 불가 - 토큰이 인식 못함-->
<!-- <li>"hello world!" = <span th:text="hello world!"></span></li>-->
<li>'hello' + 'world' = <span th:text="'hello' + ' world'"></span></li>
<li>'hello world! = <span th:text="'hello world'"></span></li>
<li> 'hello ' + ${data} = <span th:text="'hello ' + ${data} "></span></li>
<li> 리터럴 대체 |hello ${data}| = <span th:text="|hello ${data}|"></span></li>
</ul>
</body>
</html>
9. 연산
- th 내부에서 연산을 하였을 때
- 비교 연산자나 일반 연산자 결과 까지 작성시 boolean으로 값 반환
- 일반 연산만 작성할 경우 값 반환
// 산술 연산
<li>10 +2 = <span>[[10+2]]</span></li> // 10 +2 = 12
<li>10 % 2 == 0 = [[10 % 2 == 0]]</li> // 10 % 2 == 0 = true
//비교연산
<li> 10 > 1 = [[10 > 1]]</li> // 10 > 1 = true
<li> 10 gt 1 = [[10 gt 1]]</li> // 10 gt 1 = true
<li> 10 > 1 = [[10 > 1]]</li> // 10 > 1 = true
<li>1 >= 10 = <span th:text="1 >= 10"></span></li>
<li>1 ge 10 = <span th:text="1 ge 10"></span></li>
<li>1 == 10 = <span th:text="1 == 10"></span></li>
<li>1 != 10 = <span th:text="1 != 10"></span></li>
- 조건식, Elvis 연산자, No-Operation
// 조건식
<li>(10 %2 ==0) ? '짝수': '홀수' = <span th:text="(10 %2 ==0) ? '짝수': '홀수' "></span></li> // 짝수
// elvis 연산자
<li>${data}? : 'data 없음' = <span th:text="${data}?:'data 없음'"></span></li> // Spring
// No-Operation
<li>${data}?: _ = <span th:text="${data}?: _">data 없음</span></li> // Spring
<li>${data}?: _ = <span th:text="${nullData}?: _">data 없음</span></li> // data 없음
- 비교연산: HTML 엔티티를 사용해야 하는 부분을 주의
- > (gt), < (lt), >= (ge), <= (le), ! (not), == (eq), != (neq, ne)
- > (gt), < (lt), >= (ge), <= (le), ! (not), == (eq), != (neq, ne)
- 조건식: 자바의 조건식과 유사
- Elvis 연산자: 조건식의 편의 버전
- No-Operation: _ 인 경우 마치 타임리프가 실행되지 않는 것 처럼 동작한다. 이것을 잘 사용하면 HTML
의 내용 그대로 활용할 수 있다.
10. 속성 값 설정
- 속성 설정
- th:* 지정한 속성으로 대체, 기존 속성 없을 시 새로 생성
- th:* 지정한 속성으로 대체, 기존 속성 없을 시 새로 생성
- 속성 추가
- th:attrappend - 속성 값의 뒤에 값을 추가 , 띄어쓰기 필요
- th:attrprepend - 속성 값의 앞에 값을 추가 . 띄어쓰기 필요
- th:classappend - class 속성에 자연스럽게 추가 , 띄어쓰기 자동
- checked 처리
- html checked="false" - checked 속성이 존재하기 때문에 checked 처리 되어버림
- thymeleaf
- th:checked="false" - checked 속성 자체를 제거
- th:checked="true" - checked 속성 유지
- html checked="false" - checked 속성이 존재하기 때문에 checked 처리 되어버림
<!-- 속성 설정 -->
<input type="text" name="mock" th:name="userA">
<!-- 속성 추가 -->
- th:attrappend = <input type="text" class="text" th:attrappend="class=' large'"/><br/>
- th:attrprepend = <input type="text" class="text" th:attrprepend="class='large '"/><br/>
- th:classappend = <input type="text" class="text" th:classappend="large"/>
<!-- checked 처리 -->
- 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"/>
11. 반복
- th:each
- th:each="user : ${users}"
- List, array, Iterable, Enumeration, Map 까지 사용 가능
Map의 경우 Map.Entry 작동
- userStat
- th:each의 2번째 params 이고 생략 가능, 생략시 변수명은 (1st 변수명) + Stat 가 된다.
- Stat 기능
- index : 0부터 시작하는 값
- count : 1부터 시작하는 값
- size : 전체 사이즈
- even , odd : 홀수, 짝수 여부( boolean )
- first , last :처음, 마지막 여부( boolean )
- current : 현재 객체
<tr th:each="user, userStat : ${users}"> // userStat 생략 가능
<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>
12. 조건부 평가 - java 문법과 동일
- if, unless : return 이 false인 경우 태그 자체가 렌더링 되지 않고 사라진다.
- switch: *은 만족하는 조건이 없을 때 사용하는 값이다.
@GetMapping("/condition")
public String condition(Model model){
addUsers(model);
return "basic/condition";
}
private void addUsers(Model model) {
List<User> list = new ArrayList<>();
list.add(new User("userA",10));
list.add(new User("userB",20));
list.add(new User("userC",30));
model.addAttribute("users", list);
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>if, unless</h1>
<table border="1">
<tr>
<th>count</th>
<th>username</th>
<th>age</th>
</tr>
<tr th:each="user: ${users}">
<td th:text="${userStat.count}">1</td>
<td th:text="${user.username}">username</td>
<td>
<span th:text="${user.age}">0</span>
<span th:text="미성년자111" th:if="${user.age < 20}"></span>
<span th:text="미성년자222" th:unless="${user.age > 20}"></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 : ${users}">
<td th:text="${userStat.count}">1</td>
<td th:text="${user.username}">username</td>
<td th:switch="${user.age}">
<span th:case="10">10살</span>
<span th:case="20">20살</span>
<span th:case="*">기타</span>
</td>
</tr>
</table>
</body>
</html>
13. 주석
- 표준 html 주석
- <!-- 주석 처리 내용 -->
- 타임리프 파서 주석 : 자주 사용, 렌더링된 html 파일에서는 소스코드에 나타나지도 않음
- <!--/* 주석 처리 내용 */-->
- <!--/*--> 주석 처리 내용 <!--*/-->
- 타임리프 프로토타입 주석 : rendering html에서는 값으로 나오고 static 일때 주석처리됨
- <!--/*/ 주석 처리 내용 /*/-->
<h1>1. 표준 html 주석</h1>
<!--
<span th:text="${data}">html data</span>
-->
<h1>2. thymeleaf html 주석 - 2가지: 렌더링된 html 파일에서는 소스코드에 나타나지도 않음</h1>
<p>1)</p>
<!--/*-->
<span th:text="${data}">html data</span>
<!--*/-->
<p>2)</p>
<!--/*[[${data]] */-->
<h1>3. 타임리프 프로토타입 주석: rendering html에서는 나오고 static 일때 주석처리됨</h1>
<!--/*/
<span th:text="${data}">html data</span>
/*/-->
14. 블록
- thymeleaf의 유일한 자체 태그
- div n개 동시에 each loop 돌리고 싶을 때 사용
- 웬만하면 사용하지 말고 꼭 필요할 때만 사용
- <th:block th:each="user : ${user}"> ~ </th:block>
<th:block th:each="user : ${users}">
<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>
15. 자바스크립트 인라인
- <script th:inline="javascript">
- 인라인 존재 유무 차이점
- text 렌더링
- var username = [[${user.username}]];
- 인라인 사용 전 결과 : var username = userA;
- 인라인 사용 후 결과 : var username = "userA"; // 문자 타입인 경우 " " 포함 해준다. escape 처리도 가능
- var username = [[${user.username}]];
- javaScript natural templete
- var username2 = /*[[${user.username}]]*/ "test username";
- 인라인 사용 전 var username2 = /*userA*/ "test username"; // 그대로 해석
- 인라인 사용 후 var username2 = "userA"; // 주석 부분 제거 하고 내부 실제 tyhemleaf 코드(=원하는 렌더링) 잘 적용
- var username2 = /*[[${user.username}]]*/ "test username";
- 객체
- var user = [[${user}]];
- 인라인 사용 전 var user = BasicController.User(username=userA, age=10); // toString 호출값
- 인라인 사용 후 var user = {"username":"userA","age":10}; // JSON으로 변환
- var user = [[${user}]];
- 자바스크립트 인라인 each
[# th:each="user, stat : ${users}"] ...[ / ]
<script th:inline="javascript">
[# th:each="user : ${users}"]
const user[[${userStat.count}]] = [[${user}]];
[/]
</script>
16. 템플릿 조각
주요 속성 3가지
- th:fragment - 해당 tag가 조각이라고 지정
- th:insert - fragment를 받는 부분, fragment를 받는 tag 내부에 fragment로 지정된 tag를 받는다.
- th:replace - fragment를 받는 부분, fragment를 받는 tag를 날리고 fragment tag 자체를 받는다.
- th:text - fragment를 받는 부분 해당 tag를 escape 시킨다.
th:fragment : 다른 곳에 포함되는 코드 조각으로 이해
fragment 지정 == footer.html == 다른 곳의 코드 조각
- params 없는 경우
- params 있는 경우
fragment 사용 방법
- ~{url :: fragment 명(params)}
- fragment 명은 꼭 필수값은 아니다. 하지만 어떤 역할인지 파악하기가 좋다.
- fragment가 없더라도 ~{url :: tag} 를 통해서 fragment 전달가능
- 이 경우 해당 tag가 여러개 일때 원하는 것을 지정할 수 없다.
- cf) ~{}로 감싸지 않아도 되지만 url 복잡해지면 감싸야 함
- 부분 포함
- insert : frgment를 부른 tag를 건들이지 않고 내부에 생성
- replace : fragment를 부른 tag를 제거하고 생성
- 파라미터 사용
- ('파라미터에 들어갈 값1', '파라미터에 들어갈 값2' ): params 값은 필수로 다 들어가야함
- ('파라미터에 들어갈 값1', '파라미터에 들어갈 값2' ): params 값은 필수로 다 들어가야함
<h1>부분 포함</h1>
<h2>insert</h2>
<div th:insert="~{template/fragment/footer :: copy}"></div>
<h2>replace</h2>
<div th:replace="~{template/fragment/footer :: copy}"></div>
<h2>단순 표현식 - 가능하지만 url이 복잡해지면 ~{::} 사용해야함 </h2>
<div th:replace="template/fragment/footer :: copy"></div>
<h1>파라미터 사용</h1>
<div th:replace="~{template/fragment/footer :: copyParam ('데이터1', '데이터2')}"></div>
17. 템플릿 레이아웃 1
- 템플릿 조각 수준에서 더 큰 규모로 접근
- 큰 규모로 공통부분을 넣어주고 개별적으로 가지고 싶은 부분은 개별적으로 넣는 방법
방식
- head tag를 fragment 지정함. fragment를 지정할 때 params를 받도록 지정을 한다. - params를 받는 부분이 개별적으로 추가하는 부분이다. -> 해당 head fragment를 사용할 때 params를 넣어줘야한다. 해당 params는 다른 html부터 받음.
- params부분은 UI에 나올 html의 title과 link들 을 추가해준다. - 현재 html의 title,link를 넣을 것이므로 ~{::title}, ~{::link} 설정하고 url 작성은 필요 없음
순서
- UI html 의 head 부분을 layout head로 교체
- 교체된 head 부분에서 UI로 부터 받은 params를 주입
// UI에 나올 html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="template/layout/base :: common_header(~{::title},~{::link})">
<!--자기 자신의 tag를 params로 보내는 거여서 url 작성 필요 X-->
<title>메인 타이틀</title>
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
<link rel="stylesheet" th:href="@{/themes/smoothness/jquery-ui.css}">
</head>
<body>메인 컨텐츠</body>
</html>
// head layout을 공유하는 html -
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="common_header(title,links)">
<title th:replace="${title}">레이아웃 타이틀</title>
<!--UI html로부터 tag 자체를 받아오기때문에 th:text가 아닌 th:replace로 받아 온다.-->
<!--공통-->
<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}" />
<!--UI html로 부터 link tag 자체를 받아 온것이므로 th:replace 사용-->
</head>
<body></body>
</html>
// source code
<!DOCTYPE html>
<html>
<head>
<title>메인 타이틀</title>
<!--공통-->
<link rel="stylesheet" type="text/css" media="all" href="/css/awesomeapp.css">
<link rel="shortcut icon" href="/images/favicon.ico">
<script type="text/javascript" src="/sh/scripts/codebase.js"></script>
<!--추가 -->
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/themes/smoothness/jquery-ui.css">>
</head>
<body>
메인 컨텐츠
</body>
</html>
18. 템플릿 레이아웃 2
- 템플릿 레이아웃 1과 원리 동일
- 그냥 범위만 더 넓혀서 html 수준에서 fragment 하는 것
사용 적기
- fragment: html page 수가 적을 때 사용
- template layout: html page 수가 많을 때 사용