ASP.NET MVC: Knockout, JsSite - редактирование комплексных типов или DbLookUp на AJAX
А что в итоге?
Для того, чтобы сразу же стало понятно, ради чего мы сегодня собрались в этом маленьком блоге, позвольте показать вам видеоролик, который наглядно демонстрирует результат реализации поставленной задачи.
Редактирование комплексных типов при помощи Knockout
В конце статьи вы можете скачать демонстрационный проект и провести свои эксперименты.
Постановка задачи
Есть две сущности “Пользователь” и “Питомец” (Person и Pet). У пользователя может быть один питомец. Требуется возможность выбирать домашнего питомца у пользователя при редактировании. Отображение и подстановка питомца должны быть в виде объекта. Контрол для отображение должен иметь подменяемые шаблоны.
Немного классов на JavaJscript
Если учесть, что сущности имеют зависимость “один-ко-многим”, то классы моделей в JavaScript могут выглядеть таким образом:
1: $(function () {
2:
3: "use strict";
4:
5: site.m.Pet = function (dto) {
6: var me = this, data = dto || {};
7: me.id = ko.observable(data.id);
8: me.name = ko.observable(data.name);
9: me.type = ko.observable(data.type);
10:
11: me.selected = ko.observable(false);
12:
13: me.petName = ko.computed(function () {
14: if (me.name && me.type) {
15: return me.type() + ' ' + me.name();
16: }
17: return'';
18: });
19: return me;
20: };
21:
22: site.m.Person = function (dto) {
23: var me = this, data = dto || {};
24: me.firstName = ko.observable(data.firstName);
25: me.lastName = ko.observable(data.lastName);
26: me.pet = ko.observable(data.pet);
27:
28: me.selected = ko.observable(false);
29:
30: me.dirtyFlag = new ko.DirtyFlag([
31: me.firstName,
32: me.lastName
33: ]);
34: return me;
35: };
36:
37: });
Обратите внимание на строки 11 и 28 – это свойство требуется для контрола DataSource (именно его я и буду использовать). Подробное описание самого контрола, его принципов работы, свойств и методов можно посмотреть в описании (скоро).
А в строках 30-34 я подключил возможность отслеживания состояния полей на предмет изменения. Надеюсь в следующих статьях я затрону и эту тему.
Тестовые данные для классов
Наполнение данных я вынесу в отдельный не только класс, но и в отдельный файл. Наполним наши классы некоторым количеством данных:
1: site.utils.dataPets = [
2: new site.m.Pet({ 'id': 51, 'name': 'Пупсик', 'type': 'Кот' }),
3: new site.m.Pet({ 'id': 52, 'name': 'Семен', 'type': 'Конь' }),
4: new site.m.Pet({ 'id': 53, 'name': 'Мурка', 'type': 'Хорек' }),
5: new site.m.Pet({ 'id': 54, 'name': 'Золотуха', 'type': 'Рыбка' })
6: ];
7:
8: site.utils.dataPeople = [
9: new site.m.Person(
10: {
11: 'firstName': 'Иван',
12: 'lastName': 'Прохоров',
13: 'pet': site.utils.dataPets[2]
14: }
15: ),
16: new site.m.Person(
17: {
18: 'firstName': 'Игорь',
19: 'lastName': 'Пупкин',
20: 'pet': site.utils.dataPets[1]
21: }
22: ),
23: new site.m.Person(
24: {
25: 'firstName': 'Александр',
26: 'lastName': 'Болотов',
27: 'pet': site.utils.dataPets[0]
28: }
29: )
30: ];
Пришло время создавать ViewModel для главной (стартовая) страницы.
1: $(function () {
2:
3: "use strict";
4:
5: site.vm.viewModel = function () {
6: var
7: meta = site.utils.metaForDemo,
8: clock = new site.controls.Clock(),
9: dsPets = new site.controls.DataSource({
10: items: site.utils.dataPets
11: }),
12: dsPeople = new site.controls.DataSource({
13: items: site.utils.dataPeople,
14: events: {
15: selectedHandler: function (item) {
16: selectedItem(item);
17: }
18: }
19: }),
20: selectedItem = ko.observable(),
21: select = function (item) {
22: selectedItem(item);
23: };
24: return {
25: meta: meta,
26: select: select,
27: selectedItem: selectedItem,
28: clock: clock,
29: dsPeople: dsPeople,
30: //pets: pets,
31: dsPets: dsPets
32: };
33: }();
34:
35: ko.applyBindings(site.vm.viewModel);
36:
37: });
Теперь немного HTML-разметки:
1: @{
2: ViewBag.Title = "Контрол подброра";
3: }
4:
5: <h2data-bind="text: meta.title,
6: click: function () { window.location = meta.helplink(); },
7: attr: { 'style': 'cursor:pointer' }"></h2>
8: <pdata-bind="text: meta.description"></p>
9:
10:
11: <divclass="row">
12: <divclass="span6">
13: <h3>Список "Person"</h3>
14: <uldata-bind="template: { 'name': 'person-template.view', foreach: dsPeople.items }"></ul>
15: </div>
16: <divclass="span6">
17: <h3>Список "Pets"</h3>
18: <uldata-bind="template: { 'name': 'pet-template.view', foreach: dsPets.items }"></ul>
19: </div>
20: </div>
21:
22: <!-- ko if: selectedItem -->
23:
24: <divclass="row">
25: <divclass="span12">
26: <h3>Выбранный пользователь</h3>
27: <divdata-bind="template: { 'name': 'person-template.view', 'data': selectedItem }"></div>
28: </div>
29: <divclass="span6">
30: <h3>Первый способ</h3>
31: <divdata-bind="template: { 'name': 'person-template.edit', data: selectedItem }"></div>
32: </div>
33:
34: <divclass="span6">
35: <h3>Второй способ</h3>
36: <divdata-bind="template: { 'name': 'person-template.edit2', data: selectedItem }"></div>
37: </div>
38: </div>
39:
40: <!-- /ko -->
41:
42: @section scripts {
43: <scriptsrc="~/Scripts/app/dump.js"></script>
44: <script src="/scripts/app/site.homeIndex.js"></script>
45: }
46:
47: @*<divdata-bind="dump: dsPets.items"></div>*@
48: <divclass="clock"data-bind="text: clock.time"></div>
Строки 5-7 выводят заголовок (header), на который можно кликнуть, чтобы перейти на наш блок. Это сделано лишь для примера связывания (binding), и не несет никакой смысловой нагрузки (Олег, надеюсь ты понял как можно использовать function в разметке knockout для связывания).
Строка 14: Выводим все записи из DataSource “Person” (dsPerson) при помощи шаблона (template), который берется из отдельного файла.
Примечание: все шаблоны загружаются из удаленных шаблонов при помощи специального модуля External Template Engine. Шаблоны я положил в папку Templates. Настройка (указание путей и всё такое) модуля происходит в файле site.core.js.
И что же мы видим?
После некоторых манипуляций с буквами английского алфавита, у меня появилось некоторое количество файлов с классами, сервисами и другой всякой фигней. Теперь можно запустить проект и посмотреть что получилось. Итак, у нас есть список пользователей:
Также на странице отображается список домашних питомцев:
Если мы выберем одного из пользователей, то он отобразится ниже:
А также станут доступны для редактирования данные этого пользователя. Для того чтобы вы смогли сравнить, я сделал это двумя способами. Первый способ “стандартный” при выборка происходит при помощи html-контрола <select>.
А вот второй способ “продвинутый” – уже использует DataSource, DBLookup и шаблоны для отображения.
Остановлюсь немного подробнее на контроле DbLookUp. Контрол имеет несколько шаблонов:
- Шаблон FieldTemplate (не обязательный). Этот шаблон отвечает за отображение самого контрола (например, поле label и кнопка с точками, так как показан на картинке) при просмотре формы, по умолчанию если не задан шаблон, используется именно это отображение.
- Шаблон ModalTemplate (не обязательный). Шаблон для отображения модально окна. На видео хорошо видно, что используется Twitter Bootstrap. Вы можете использовать CSS Framework для вывода модального окна.
- Шаблон DsTemplate (обязательный). Этот шаблон используется для отображения списка.
Нажимаем на кнопку вызова диалога.
Выбираем новое значение, нажимаем [выбрать] и, ву-а-ля! Новое значение “падает”
В качестве заключения
В качестве заключения хочу привести вашему вниманию некоторое количество ссылок:
- Knockoutjs фрэймворк на javascript, обеспечивающий MVVM паттерн на HTML.
- JsSite nuget-пакет, который содержит некоторое количество файлов (скриптов), использующие knockout для построения приложений в стиле SPA (Single Page Application).
- Twitter Bootstrap фрэймворк на CSS+JavaScript, который существенно облегчает разработку дизайна, в том числе одним из плюсов которого является возможность замены тем (themes).
Следующая статья будет о том самом контроле, который называется DataSource, и о том как можно просто из без особых усилий вывести данные с Web API на странице. На этом хочу закончить и сказать “спасибо за внимание”.
Подробнее: http://feedproxy.google.com/~r/blogmusor/~3/vxEA5DmR2WM/115
Дайджест новых статей по интернет-маркетингу на ваш email
Новые статьи и публикации
- 2024-09-30 » Как быстро запустить Laravel на Windows
- 2024-09-25 » Next.js
- 2024-09-05 » OpenAI рассказал, как запретить ChatGPT использовать содержимое сайта для обучения
- 2024-08-28 » Чек-лист: как увеличить конверсию интернет-магазина на примере спортпита
- 2024-08-01 » WebSocket
- 2024-07-26 » Интеграция с Яндекс Еда
- 2024-07-26 » Интеграция с Эквайринг
- 2024-07-26 » Интеграция с СДЕК
- 2024-07-26 » Интеграция с Битрикс-24
- 2024-07-26 » Интеграция с Travelline
- 2024-07-26 » Интеграция с Iiko
- 2024-07-26 » Интеграция с Delivery Club
- 2024-07-26 » Интеграция с CRM
- 2024-07-26 » Интеграция с 1C-Бухгалтерия
- 2024-07-24 » Что такое сторителлинг: техники и примеры
- 2024-07-17 » Ошибка 404: что это такое и как ее использовать для бизнеса
- 2024-07-03 » Размещайте прайс-листы на FarPost.ru и продавайте товары быстро и выгодно
- 2024-07-01 » Профилирование кода в PHP
- 2024-06-28 » Изучаем ABC/XYZ-анализ: что это такое и какие решения с помощью него принимают
- 2024-06-17 » Зачем вам знать потребности клиента
- 2024-06-11 » Что нового в работе Яндекс Метрики: полный обзор обновления
- 2024-06-11 » Поведенческие факторы ранжирования в Яндексе
- 2024-06-11 » Скорость загрузки сайта: почему это важно и как влияет на ранжирование
- 2024-05-27 » Подборка сервисов для расшифровки аудио в текст
- 2024-05-27 » PostgreSQL 16. Изоляция транзакций. Часть 2
- 2024-05-06 » Как настраивать конверсионные стратегии: работа над ошибками
- 2024-04-22 » Комментирование кода и генерация документации в PHP
- 2024-04-22 » SEO в России и на Западе: в чем основные отличия
- 2024-04-22 » SEO для международного масштабирования
- 2024-04-22 » Как использовать XML-карты для продвижения сайта
Кто мало хочет, тот дешево стоит |
Мы создаем сайты, которые работают! Профессионально обслуживаем и продвигаем их , а также по всей России и ближнему зарубежью с 2006 года!
Как мы работаем
Заявка
Позвоните или оставьте заявку на сайте.
Консультация
Обсуждаем что именно Вам нужно и помогаем определить как это лучше сделать!
Договор
Заключаем договор на оказание услуг, в котором прописаны условия и обязанности обеих сторон.
Выполнение работ
Непосредственно оказание требующихся услуг и работ по вашему заданию.
Поддержка
Сдача выполненых работ, последующие корректировки и поддержка при необходимости.