Шаблоны в jQuery - jQuery Templates
Итак, рассмотрим примитивное использование шаблонов. Качаем плагин отсюда.Удобнее всего текст шаблона брать в объятия тега <script>, ибо a)контейнеру надо присвоить идентификатор для обращения; б)содержимое этого тега не отображается на странице. Рассмотрим на примере массива из объектов с двумя полями: числовым id и текстовым title.
var places = [{ id: 0, title: "home" }, { id: 1, title: "work"}];Я хочу, чтобы элементы выводились так:
[0] home
[1] work
Шаблон для этого случая будет следующим:
<script type="text/html" id="listTmpl"> <li>[{{= id}}] {{= title}}</li> </script>В виду того, что шаблоны используются для отображения элементов массива, которыми являются объекты, то в коде шаблона переменные для форматирования вывода – имена полей объекта. В нашем случае объект имеет два поля, которые мы хотим отобразить: id и title. Указать их можно двумя способами: a){{= имя_поля}} или б)${имя_поля}. Разница в том, что вторая запись вводилась позже, и её подстановка займет немножко больше времени.
А теперь, чтобы шаблон сработал, надо у элемента его содержащего (в нашем случае это тег <script> с id=listTmpl) вызвать метод tmpl(), передав ему параметром массив с объектами, а также добавить в цепочку вывода метод appendTo(), указывая ему в какой элемент поместить сгенерированное по шаблону содержание:
$("#listTmpl").tmpl(places).appendTo("#list");Полностью код и разметка страницы представлены ниже. По нему видно, что в appendTo был передан элемент списка <ul>:
<html> <head> <title>Test</title> <script type="text/javascript" src="js/jquery.js"></script> <script type="text/javascript" src="js/jquery.tmpl.js"></script> <script type="text/javascript"> $().ready(function () { var places = [{ id: 0, title: "home" }, { id: 1, title: "work"}]; $("#listTmpl").tmpl(places).appendTo("#list"); }); </script> </head> <body> <ul id="list"> <script type="text/html" id="listTmpl"> <li>[{{= id}}] {{= title}}</li> </script> </ul> </body> </html>
Связывание данных в jQuery data- bindinglinking
Для связывания данных понадобится указать три параметра: 1) имя поля у объекта; 2) идентификатор элемента вывода; 3) метод получения данных. Я буду рассматривать здесь и далее привязку в оба конца через метод linkBoth. Допустим, у нас объект с двумя полями: title и description. Тогда код для привязки поля title к содержимому текстового поля <input type="text" id="title" /> будет выглядеть так:var obj = { title: "someTitle", description: "Foo" }; $(obj).linkBoth("title", "#title", "val");Первый параметр – имя связываемого поля в объекте. Второй – идентификатор текстового поля ввода. Третий – метод jQuery, с помощью которого можно получить значение этого текстового поля.
Комбинация шаблонов с привязкой данных
Конечно, хочется использовать связывание данных совместно с шаблонами. Но как это сделать, если data-linking берет на вход объект, а шаблоны хотят массив объектов? Лично я не нашла статей о том, что разработчики сделали этот уже давно планируемый апдэйт с комбинацией.Поэтому я у каждого элемента массива вызываю linkBoth, а в шаблоне атрибуту id элемента вывода приписываю id объекта, к примеру: у объекта есть поле id:11, тогда в шаблоне блок данных одного объекта можно взять в объятия тега <div id="obj_{{= id}}"></div> и больше в шаблоне не использовать обращение к другим полям {{= другие_поля_объекта}}, а контейнерам полей прописать классы, чтобы значения передавались только один раз - через data-linking (если указать значения контейнеров еще и через шаблон, то дважды отработает присвание значения: первый раз при генерации шаблона, и второй раз при первом вызове link), указанием идентификатора вида #obj_11 .Obj_field.
Давайте рассмотрим конкретный пример. Есть у меня класс с относительно большим набором полей. event: id, title, description, duration. И я хочу выводить массив объектов этого класса в редактируемом виде. Притом для демонстрации дополнительных возможностей связывания поле duration выводится с односторонней связкой в видоизмененном виде относительно того, как оно представлено в объекте, т.е. используя вместо метода linkBoth методы linkFrom и linkTo, можно указать 4ый параметр – конвертер передаваемого значения. Как выше было сказано, я использую див-контейнер для вывода полей объекта, прописывая id объекта только ему. До вызова шаблона массив заполняется тремя объектами, вызывается шаблон, а потом к каждому элементу массива вызывается цепочка методов связывания данных. Каждое новое событие создается конструктором, в котором есть метод linkEvents, где идет вызов функций связывания. Чтобы вывести новый объект на страницу, к контейнеру шаблона вызывается метод tmpl с новым объектом в качестве параметра, а не массивом всех объектов. И уже после того, как шаблоном были добавлены новые ui-элементы на страницу, у объекта вызывается linkEvents, в котором отрабатывается привязка всех полей объекта к только что созданным элементам их представления.
<html> <head> <title>Test</title> <script type="text/javascript" src="js/jquery.js"></script> <script type="text/javascript" src="js/jquery.tmpl.js"></script> <script type="text/javascript" src="js/jquery.datalink.js"></script> <script type="text/javascript"> var events; var curId = 100; function event(id, title, desc, dur) { this.id = id; this.title = title; this.description = desc; this.duration = dur; this.linkEvents = linkEvents; } $().ready(function () { events = [new event(curId++, "sleep", "go to see pink-sweety dreams", 480), new event(curId++, "morning", "time to read a book", 30), new event(curId++, "breakfast", "time to eat!", 70)]; $("#evTmpl").tmpl(events).appendTo("#events"); $(events).each(linkEvents); }); function showData() { var message = ""; for (var i in events) { $(events[i]).attr('duration', Math.floor(Math.random() * 111) ); message += events[i].title + " <font color=Gray>" + events[i].description + " </font><i> " + events[i].duration + "minutes</i> <br />"; } $("#outputArea").html(message); } function addNewEvent() { var newEv = new event(curId++, "event_" + curId, "description " + curId, 100 ); $("#evTmpl").tmpl(newEv).appendTo("#events"); events[events.length] = newEv; newEv.linkEvents(); } function linkEvents () { var id = "#ev_" + $(this).attr("id") + " ."; $(this) .linkBoth("title", id + "Title", "val") .linkBoth("description", id + "Description", "val") .linkTo("duration", id + "Time", "text", function (value) { value = parseInt(value); var m = value % 60; var h = (value - m) / 60; m = (m == 0) ? "" : m + "min"; h = (h == 0) ? "" : h + "h "; return h + m; }); } </script> </head> <body> <input type="submit" value="output" onclick="showData();" /> <input type="submit" value="generate new event" onclick="addNewEvent();" /> <ul id="events" style="list-style:none;"> <script type="text/tmpl" id="evTmpl"> <li id="ev_{{= id}}"> title: <input type="text" class="Title" /> description: <input type="text" class="Description" /> <span class="Time"></span> </li> </script> </ul> <div style="margin-top:20px;;" id="outputArea"></div> </body> </html>В примере две кнопки: отобразить содержимое массива в диве и сгенерировать новое событие. При отображении в див также происходит генерация новых значений duration для каждого уже имеющегося объекта. Пример того, что делает скрипт, представлен ниже:
Не надо забывать, что связывание не будете работать, пока шаблон не создаст содержимое – те контейнеры, к которым будет осуществляться привязка данных.
Живая демонстрация скрипта и его исходник.
Комментариев нет:
Отправить комментарий