Что значит имя 7: Новые модули для Durandal и встроенные компоненты фреймворка
Сайтостроение | создано: 04.07.2014 | опубликовано: 05.07.2014 | обновлено: 13.01.2024 | просмотров: 5237
В этой статье будем использовать гаджеты (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
});
Третья строка включает этот компонент. Запустим приложение, попробуем вывести информацию по имени Сергей, и кликнем на букву “р”

Получилось!
Заключение
Мы добились того, к чему шли долгие семь статей из этого цикла про одностраничные порталы. Как всегда жду комментарии по поводу прочитанного, и предлагаю скачать проект для ознакомления и экспериментов.