Поля формы и ошибки валидации в шаблонах template/news/create.html и template/news/edit.html выводятся полностью одинаково. Воспользуемся тегом <core:include>, который является как бы аналогом функции include PHP.
Создадим шаблон template/news/form_fields.html следующего содержания:
<label for="title">Title</label> : <input name='title' type='text' size='60' title='Title'/><br/> <label for="date">Date</label> : <input name='date' type='text' size='15' title='Date'/><br/> <label for="annotation">Annotation</label> : <textarea name='annotation' rows='2' cols='40' title='Annotation'></textarea><br/> <label for="content">Content</label> : <textarea name='content' rows='5' cols='40'></textarea><br/>
Теперь шаблон template/news/form_errors.html следующего содержания:
<form:errors target='errors'/> <list:list id='errors'> <table> <list:ITEM> <tr valign="top"> <td width="20%"> </td> <td width="80%"><FONT COLOR="RED">{$message}</FONT></td> </tr> </list:ITEM> </table> </list:list>
Теперь эти шаблоны подключаем в наши template/news/create.html и template/news/edit.html:
<html> <head> <title>Limb3 tutorial</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body bgcolor="#FFFFFF" text="#000000" > <h1>Create news</h1> <form id='news_form' name='news_form' method='post' runat='server'> <core:include file="news/form_errors.html" /> <core:include file="news/form_fields.html" /> <input type='submit' value='Create' runat='client'/> </form> </body> </html>
и
<html> <head> <title>Limb3 tutorial</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body bgcolor="#FFFFFF" text="#000000" > <h1>Edit news</h1> <form id='news_form' name='news_form' method='post' runat='server'> <core:include file="news/form_errors.html" /> <core:include file="news/form_fields.html" /> <input type='submit' value='Edit' runat='client'/> </form> </body> </html>
Обратите внимание на использование тега <core:include>. Атрибут file указывает на относительное имя шаблона (относительно папки template), который нужно включить в шаблон вместо тега.
Что ж, уже лучше, но можно сделать еще компактнее.
Код в шаблонах create.html и edit.html до формы и после нее повторяется дважды. В других шаблонных системах мы сделали бы еще 2 шаблона: header.html и footer.html, но в WACT есть средства намного лучше. Подход header/footer имеет большой недостаток в том, что разбивает базовый шаблон на 2 составляющие, которые усложняют общее понимание шаблона в целом. При помощи WACT этот недостаток можно обойти.
Воспользуемся тегом <core:wrap>, который позволяет вставлять содержимое тега внуть другого шаблона, то есть как бы обворачивать один шаблон другим.
Но для начала выделим шаблон page.html следующего содержимого:
<html> <head> <title>Limb3 tutorial</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body bgcolor="#FFFFFF" text="#000000" > <core:PLACEHOLDER id="page_placeholder"/> </body> </html>
Обратите внимание на тег <core:placeholder> - при помощи этого тега мы декларируем место, в которое может быть вставлен другой шаблон. Теперь изменим наши шаблоны create.html и edit.html следующим образом:
<core:wrap file="page.html" in="page_placeholder"> <h1>Create news</h1> <form id='news_form' name='news_form' method='post' runat='server'> <core:include file="news/form_errors.html" /> <core:include file="news/form_fields.html" /> <input type='submit' value='Create' runat='client'/> </form> </core:wrap>
и
<core:wrap file="page.html" in="page_placeholder"> <h1>Edit news</h1> <form id='news_form' name='news_form' method='post' runat='server'> <core:include file="news/form_errors.html" /> <core:include file="news/form_fields.html" /> <input type='submit' value='Edit' runat='client'/> </form> </core:wrap>
Тег <core:wrap> имеет атрибуты file, который указывает на относительное имя файла, в какой шаблон делать вставку, и in, который указывает, в какое место этого шаблона нужно её делать. Тег <core:wrap> имеет обязательный закрывающий тег, который как бы отмечает зону, которая должна быть завраплена в другой шаблон.
На самом деле тег <core:wrap> дает очень широкий простор для разбиения шаблонов, однако эти возможности и принципы их использования выходят за рамки данного примера.
Список новостей может быть слишком большим для отображения на одной странице. В этом случае обычно применяют разбиение списка на страницы (пейджинация). При помощи WACT сделать разбиение на страницы проще простого.
Создадим шаблон template/pager.html следующего содержимого:
<pager:NAVIGATOR id="pager" items="3"> Shown: from <b>{$BeginItemNumber}</b> to <b>{$EndItemNumber}</b> <pager:FIRST><a href="{$href}">|--</a></pager:FIRST> <pager:LIST> <pager:CURRENT><b><a href="{$href}">{$number}</a></b></pager:CURRENT> <pager:NUMBER><a href="{$href}">{$number}</a></pager:NUMBER> </pager:LIST> <pager:LAST><a href="{$href}">--|</a></pager:LAST> Total: <b>{$TotalItems}</b> </pager:NAVIGATOR>
Центральный тег при постраничном разбиении - <pager:NAVIGATOR>, который ограничивает пейджер. Он содержит атрибут items, который указывает, какое количество элементов списка выводить на одной странице. Остальными тегами выводятся ссылки на первую (тег <pager:FIRST>), предыдущую(тег <pager:PREV>, здесь не использовался), текущую(тег <pager:CURRENT>), следующую(тег <pager:NEXT>, здесь не использовался) и последнюю(тег <pager:LAST>) страницы, а также на некоторое количество страниц в середине (тег <pager:NUMBER>).
Также при помощи выражений {$TotalItems}, {$BeginItemNumber} и {$EndItemNumber}, который по-умолчанию поддерживаются внутри тега <pager:NAVIGATOR> мы выводим общее количество элементов в списке, а также номера элементов, с которого начинается текущая страница и которым заканчивается текущая страница.
Теперь необходимо этот шаблон подключить на странице отображения списка новостей и связать список новостей с пейджером. Вот новый вид шаблона template/news/display.html (мы также использовали здесь тег <core:wrap>, точно также как и для шаблонов форм):
<core:WRAP file="page.html" in="page_placeholder"> <h1>Newsline</h1> <route_url params="action:create">Create news</route_url> <p/> <active_record:fetch using='src/model/News' target="news" navigator='pager'/> <core:include file='pager.html' /> <list:LIST id="news"> <table border="1"> <tr> <th>ID</th> <th>Date</th> <th>Title</th> <th>Actions</th> </tr> <list:ITEM> <tr> <td>#{$id}</td> <td>{$date}</td> <td>{$title}</td> <td> <route_url params="action:edit,id:{$id}">Edit</route_url> <route_url params="action:delete,id:{$id}">Delete</route_url> </td> </tr> <tr> <td colspan='4'> {$annotation} </td> </tr> </list:ITEM> </table> </list:LIST> </core:wrap>
Обратите внимание на новый атрибут тега <active_record:fetch> navigator, который имеет в качестве значения идентификатор тега <pager:NAVIGATOR>. Именно таким образом мы связали список новостей и пейджер. Более ничего делать не нужно.
Если вы все сделали правильно, тогда у вас должно получиться нечто подобное этому:
Обсуждение