Что значит имя 7: Новые модули для Durandal и встроенные компоненты фреймворка
Сайтостроение | создано: 04.07.2014 | опубликовано: 05.07.2014 | обновлено: 13.01.2024 | просмотров: 4884
В этой статье будем использовать гаджеты (gadgets), которые предоставлены во фреймворке BreezeJS. Например, будем выводить модальное окно с информацией по значению для конкретной буквы имени.
Было… Будет
В прошлый раз мы создали страницу letters, где вывели список имен отфильтрованных по выбранной пользователем букве. В этой статье первым делом выведем информацию, по выбранному имени, а затем нашим код, который по клику на букву имени покажет характерные черты для человека, носящего выбранное имя.
Новый модуль – Info
В прошло статье мы реализовали просмотр списка имен отфильтрованных по выбранной букве:
<div class="row"> <div data-bind="foreach: namesByLetter"> <div class="col-lg-3 col-sm-12 col-md-3 name"> <a data-bind="attr:{href:'#info/'+ Name()}"> <h1 data-bind="text: Name"></h1> </a> </div> </div> </div>
В строке 4 можете заметить какой путь привязан (data-bind) к атрибуту href. Да, это – ‘#info/’+ Name(). Создадим два файла info.html и info.js в папках views и viewmodels соответственно. Пусть пока второй будет пустым, а первый наполним таким содержанием:
<b class="text-info" data-bind="html: gender"></b> <h1> <!-- ko foreach: letters --> <a data-bind="text: $data, attr:{href:'#'}, click: $parent.showInfo"></a> <!-- /ko --> </h1> <p class="margin20"> <span data-bind="html: item().Content()"></span> </p>
В первой строке выводим информацию о половой принадлежности просматриваемого имени. То есть свойство gender у нас модели не существует (ни в классе NameInfo, ни в классе LetterInfo нет описания “мужское” или “женское” имя). Есть только одна буква “М” или “Ж”. Таким образом, мы будем вычислять, какая принадлежность на основании этих букв. В нашем viewmodel это свойство будет вычисляемым. В третьей строке через foreach выводим значения из списка letters, в котором хранятся буквы выбранного имени. Возможно вы не использовали еще виртуальный способ привязки, так вот в строках 3 и 5 используется именно виртуальный способ привязки. В строке 9 выводится содержание свойство Content класса NameInfo. Если вы помните, то в начале этого цикла статей, я приводил скриншот таблицы SQL-сервера с именами. В поле таблицы Content храниться не просто текст, а html-разметка. Именно поэтому в строке 9 привязка осуществятся через байндинг html, а не text.
На этом пока про представление (view) достаточно. Перейдем к модулю info.js.
В модуле буду снова опишу основные моменты после представления полного листинга:
define(['services/logger', 'knockout', 'services/dataServices', 'durandal/app', 'services/busyIndicator', 'plugins/router'], function (logger, ko, dataService, app, indicator, router) { var currentName = ko.observable(), valueableLetters = ko.observableArray([]), gender = ko.observable(), selectedLetter, currentLetter = ko.observable(), item = ko.observable({}), success = function (data) { if (data && data.results) { item(data.results[0]); indicator.isbusy(false); } }, loadData = function () { indicator.isbusy(true); var name = currentName(); if (name) { dataService.getName(name) .then(success) .fail(function () { logger.logError('Не могу найти имя в списке', null, 'info', true); router.navigate('#/notfoud'); }).fin(function () { indicator.isbusy(false); }); } }, activate = function (name) { splitName(name); currentLetter(name.substr(0, 1)); currentName(name); loadData(); }, splitName = function (name) { var letters = []; for (var i = 0; i < name.length; i++) { letters[i] = name.substr(i, 1).toUpperCase(); } valueableLetters(letters); }, showInfo = function (letter) { indicator.isbusy(true); selectedLetter = letter; dataService.getLettersInfo(letter, showMessageInfo); }; item.subscribe(function (value) { if (value) { if (value.Gender() === 'М') gender('мужское имя'); else gender('женское имя'); } }); function showMessageInfo(data) { indicator.isbusy(false); app.showMessage(data.results[0].Content(), 'Значение буквы \"' + selectedLetter + '\"'); }; return { showInfo: showInfo, letters: valueableLetters, activate: activate, currentName: currentName, currentLetter: currentLetter, item: item, gender: gender }; });
Строки с 1 по 3 определяем новый модуль и вливаем зависимости, необходимые для работы модуля. С пятой под десятую строку определяем переменные. строка 5 хранит текущее имя пришедшее как параметр из активатора при переключении модуля (см. строки с 31 по 36). Это имя “разбирается на буквы и “складывается” в переменную valueableLetters определенную в строке 6. Разборки имени происходит в функции splitName (смотри строки 37-43). Строка 7 определяет свойство gender, которое является вычисляемым на основе параметров выбора пользователя. Строка 8 определяет переменную для хранения выбранной буквы из имени. В строке 9 определяем observable переменную, которая будет выводиться на UI, как информация о выбранной букве. Переменная item определенная в строке 10 является хранилищем полученного с сервера ответа, как результат запроса по фильтру, то есть объект типа NameInfo приходит с сервера в эту переменную. Наполнение и обработка происходит в методе success (смотри строки 11-16). Этот метод является callback-функцией для запроса метода сервиса, который вызывается в методе loadData (смотри строки 17-30). Метод showInfo, определенный в сорок четвертой строке, вызывается в четвертой строке предыдущего листинга, как раз при нажатии на конкретную букву имени. Этот метод использует метод сервиса getLettersInfo, а callback-функция showMessageinfo требует особого внимания. Вернемся к нему позже, а пока поговорим снова о маршрутах.
Не все маршруты проложены
Мы добавили новый модуль, а вот про маршрут до него не положен. На данный момент список маршрутов в роутере описан так:
var routes = [ { route: ['', 'home/index'], moduleId: 'site/home', title: 'Выбор буквы', nav: true }, { route: 'about', moduleId: 'site/about', title: 'О проекте', nav: true }, { route: 'letter/:letter', moduleId: 'site/letter', title: 'Имена по букве', nav: false } ];
Добавим новый маршрут, который также должен понимать обязательный параметр:
var routes = [ { route: ['', 'home/index'], moduleId: 'site/home', title: 'Выбор буквы', nav: true }, { route: 'about', moduleId: 'site/about', title: 'О проекте', nav: true }, { route: 'letter/:letter', moduleId: 'site/letter', title: 'Имена по букве', nav: false }, { route: 'info/:name', moduleId: 'site/info', title: 'Значение имени', nav: false } ];
Обязательный параметр я назвал name, то в методе activate его же я и буду получать от активатора роутера.
activate = function (name) { splitName(name); currentLetter(name.substr(0, 1)); currentName(name); loadData(); },
Новые методы в сервисе
Раз уж добавили маршрут, давайте еще и методы в dataServices добавим, тем более что они уже используются в листинге модели info.js. В этом листинге были упомянуты два новых метода, давайте добавим их реализацию в dataServices.js:
getName = function (name) { var byName = new Predicate('Name', filterOperator.Equals, name); var query = breeze.EntityQuery.from('Names').where(byName); return manager.executeQuery(query); },
Этот метод создает запрос на сервер для получения информации по выбранному пользователем имени (смотри параметр name). Во второй строке создается предикат, где подставляется имя свойства и его значение, а также названия операции фильтрации. Строка 3 определяет запрос. А в четвертой строке этот запрос выполняется.
Второй метод, который был упомянут:
getLettersInfo = function (letter, successInfo) { var query = breeze.EntityQuery.from('LettersInfo').where('Name', filterOperator.Equals, letter); return manager.executeQuery(query, successInfo); //}); },
Функционал этого метода тоже легко предугадать. Строка инициализации метода содержит параметры letter и successInfo, которые в свою очередь должны быть заданы при вызове метода. Первый параметр – это и есть буква, значение которой и требуется получить. Второй параметр – это callback-функция, которая должна обработать результат запроса при удачном его завершении.
Методы в сервис добавлены, маршруты новые “проложены”, пришло время запустить и проверить что же у нас получилось. Посмотрим значение имени Оксана.
Отлично, всё работает. Теперь поговорим про модальное окно.
Контролы DurandalJS: модальное окно
Строках 57-60 листинга модуля info.js определена callback-функция, которая выводит в модальном окне браузера информацию по толкованию значения буквы, которая присутствует в имени. Еще раз приведу этот отрывок листинга:
function showMessageInfo(data) { indicator.isbusy(false); app.showMessage(data.results[0].Content(), 'Значение буквы \"' + selectedLetter + '\"'); };
Обратите внимание на третью строку текущего листинга. Заметили метод showMessage у объекта app? Так вот этот самый объект и есть объект приложения DurandalJS, а метод вызывает модуль dialog. Чтобы компонент заработал в главном файле инициализации приложения main.js следует разрешить использовать данный модуль:
app.configurePlugins({ router: true, dialog: true });
Третья строка включает этот компонент. Запустим приложение, попробуем вывести информацию по имени Сергей, и кликнем на букву “р”
Получилось!
Заключение
Мы добились того, к чему шли долгие семь статей из этого цикла про одностраничные порталы. Как всегда жду комментарии по поводу прочитанного, и предлагаю скачать проект для ознакомления и экспериментов.