ASP.NET MVC: Делаем голосование на сайте при помощи Knockout

Рис.1 “Опрос на сайте (пользователь еще не голосовал)”
И второй вариант отображения формы, это когда пользователь уже проголосовал.

Рис.2 “Опрос на сайте (пользователь уже голосовал)”
Звучит и выглядит просто, и поэтому я стороной обойду загрузку данных с сервера, запись данных на сервер, чтение настроек и проверку cookies, чтобы по возможности максимально рассказать о Knockout. Итак, если учесть, что все приготовления выполнены, то можно сразу приступить к программированию.
Входные данные
В папке Scripts/App создаю новый файл site.vm.polls.js. Теперь первым делом определю формат данных для объекта (Poll) (листинг 1):
1: var pollData = {
2: "question": "За двумя зайцами погонишься...",
3: "answers": [
4: { votes: 11, name: "ни одного не поймаешь." },
5: { votes: 5, name: "больше двух не поймаешь." },
6: { votes: 15, name: "ни одного волка не поймаешь." },
7: { votes: 9, name: "порвешься на две части." },
8: { votes: 39, name: "зачем бегать, лучше на авто!" }
9: ],
10: "selectedAnswer": null};
Это, так сказать, входные данные. В моем случае, они “жестко” прописаны в коде. Вы же можете сделать получение данных для опроса с сервера, через Web API, или с сервиса WCF. Немного комментариев относительно представленного кода.
- Строка 2: Сам вопрос.
- Строка 3-8: Это предложенные варианты ответа на поставленный вопрос.
- Строка 10: Ответ, который возможно уже дал пользователь, посещая сайт. Вы можете хранить его в базе данных или даже в cookies. Сейчас он у меня null, поэтому форма должна отобразить список ответов и вопрос. А если поле было заполнено (выбранный ответ), то форма должна отобразить результаты голосования.
Класс Answer (Ответ)
В предыдущем листинге (листинг 1) в строка 3 эти самые ответы на вопрос. “Завернем” класс в JavaScript (листинг 2):
1: site.vm.Answer = function (value, total) {
2: var isSelected = ko.observable(false),
3: votes = ko.observable(total),
4: name = ko.observable(value);
5: return {
6: isSelected: isSelected,
7: name: name,
8: votes: votes
9: };
10: },
Всё просто, единственное, что хотелось быть отметить, что свойство isSelected будет указыват на то выбран ли ответ в списке вариантов или нет.
Класс Poll (Опрос)
Этот класс и будет представляет “входные данные” (см. листинг 1). Самый большой класс в моем решении (листинг 3).
1: site.vm.Poll = function (data) {
2: var selectedItem = ko.observable(new site.vm.Answer()),
3: question = ko.observable(data.question),
4: answers = ko.observableArray([]),
5: answer = ko.observable(),
6: maxVotes = ko.observable(),
7: init = function () {
8: var max = 0;
9: var i;
10: for (i in data.answers) {
11: var cur = data.answers[i].votes;
12: if (cur && cur>max) {
13: max = cur;
14: }
15: }
16: max = Math.round(max * 1.1);
17: maxVotes(max);
18: for (i in data.answers) {
19: answers.push(new site.vm.Answer(data.answers[i].name, data.answers[i].votes));
20: }
21: if (data.selectedAnswer) {
22: answer(data.selectedAnswer);
23: }
24: },
25: setSelected = function (item) {
26: if (!item.isSelected()) {
27: selectedItem(item.name());
28: ko.utils.arrayForEach(answers(), function (i) {
29: if (i.isSelected && i.isSelected()) { i.isSelected(false); }
30: });
31: item.isSelected(true);
32: }
33: };
34:
35: init();
36:
37: return {
38: max: maxVotes,
39: selectedItem: selectedItem,
40: question: question,
41: answers: answers,
42: answer: answer,
43: setSelected: setSelected
44: };
45: };
И опять немного комментариев:
- Строка 2: Представляет выбранный пользователем ответ.
- Строка 6: Вообще-то, это свойство (maxVotes) я ввел только для того, чтобы правильно работал jQuery UI Progressbar, при помощи которого я планирую отображать результаты.
- Строка 7: Инициализация класса на основании входных данных. Запуск инициализации происходит в строке 35.
ViewModel для формы
На форме может быть много опросов, в моем варианте он один. Создаем ViewModel для формы Index.cshtml. Вот так выглядит pollViewModel (листинг 4):
1: site.vm.pollViewModel = function () {
2: var message = ko.observable("Выберите ваш вариант ответа на вопрос."),
3: poll = site.vm.Poll(pollData),
4: save = function () {
5: poll.answer(poll.selectedItem());
6: };
7:
8: return {
9: save: save,
10: poll: poll,
11: message: message
12: };
13: }();
Строка 2: Сообщение для пользователя. Мне не пригодилось, но можно использовать для вывода ошибок при работе сервиса.
Строка 3: Создаем экземпляр класса голосования (см. листинг 3).
Строка 4: Функция сохранения результатов голосования. В моем решении это просто обновления свойства answer. Но вы можете отправить результат на сервер или сохранить в cookies.
Магия Knockout – applyBindings
Голосование (Poll) я планирую показать на главной странице (то есть в котроллере Home, метод – Index). Я открыл представление (index.cshtml) и полностью его отчистил, и добавил туда такую разметку:
1: <divdata-bind="ifnot: poll.answer">
2: <h2data-bind="text: poll.question">h2>
3: <h4data-bind="text: message">h4>
4: <divdata-bind="foreach: poll.answers">
5: <divdata-bind="click: $parent.poll.setSelected"class="big">
6: <inputtype="radio"value="true" data-bind="checked: isSelected().toString()"class="poll"/>
7: <spandata-bind="text: name, css: {'selected': isSelected}">span>
8: div>
9: div>
10: <p>
11: <buttondata-bind="click: save">голосоватьbutton>
12: p>
13: div>
14: <divdata-bind="if: poll.answer">
15: <h2data-bind="text: poll.question() ' ' poll.answer()">h2>
16: <divdata-bind="foreach: poll.answers">
17: <spandata-bind="text: name">span>
18: <divdata-bind="progressbar: {value: votes(), max: $parent.poll.max()}">div>
19: <br/>
20: div>
21: div>
Всё на форме просто и, надеюсь, понятно. Единственное, что хотелось бы отметить, для отображения результатов в шаблоне (строка 18) используется bindingHandler, который я назвал “progressbar”. Когда вы установите nuget-пакет JsJite, у вас в папке scripts/app появится файл site.bindingHandlers.js, в котором уже много полезных “штучек”.
Заключение
В качестве заключения хочу предложить создать демо-проект и поэкспериментировать.
Подробнее: http://feedproxy.google.com/~r/blogmusor/~3/ReoYRvxCyJU/106
|
В качестве вступления Я буду строить решение на базе проекта, который был опубликован в предыдущей статье “ASP.NET MVC: И снова про форму обратной связи или куда еще втыкнуть Knockout”. Хочу чтобы |
ASP.NET MVC: Делаем голосование на сайте при помощи Knockout |
Дайджест новых статей по интернет-маркетингу на ваш email
Новые статьи и публикации
- 2026-07-29 » «Адаптация бюджета» в Яндекс Директе: как автоматически масштабировать рекламу без потери эффективности
- 2026-07-29 » Overlay в РСЯ: новый формат мобильной рекламы, который не раздражает пользователей
- 2026-07-29 » «Панорама» в Яндекс Директе: новый уровень охватной рекламы для вашего бизнеса
- 2026-07-29 » Карточки товаров и отзывы на маркетплейсах: что по закону считается рекламой, а что нет
- 2026-07-29 » Комментарии в приватных каналах «Макс»: новый инструмент для бизнес-коммуникаций
- 2026-07-23 » Как ошибки в AI-ответах портят репутацию компании
- 2026-07-23 » Маркировка рекламы в 2026 году: фатальные ошибки, которые обойдутся вашему бизнесу в полмиллиона рублей
- 2026-07-23 » Нейросети в дизайне сайтов и графике: революция, эволюция или угроза?
- 2026-07-23 » РСЯ открыла инструмент авторасстановки рекламы для всех партнеров: как автоматизация меняет правила монетизации
- 2026-07-23 » Контент для стоматологических клиник: какими текстами наполнить сайт, чтобы пациенты записывались сами
- 2026-07-22 » Продающие анимированные баннеры для вашего бизнеса
- 2026-07-22 » Услуги таргетолога по настройке рекламы ВКонтакте (ВК)
- 2026-07-19 » GEO / AISEO / AEO для B2C
- 2026-07-19 » GEO / AISEO / AEO для B2B
- 2026-07-15 » ИИ-агент как сотрудник: права, журнал действий и управление доступом через BearPass
- 2026-07-15 » Как проверить юриста, адвоката или нотариуса онлайн: пошаговое руководство для бизнеса
- 2026-07-15 » Телефон в вашем кармане действительно следит: кто, зачем и как это остановить
- 2026-07-15 » Куки и трекеры: какую информацию о вас собирают сайты и как это отключить
- 2026-07-15 » Почему корпоративный мессенджер — это не роскошь, а необходимость для бизнеса
- 2026-07-15 » Реклама на Авито, которая реально работает
- 2026-07-15 » Реклама на Авито, которая реально работает
- 2026-07-10 » Корпоративный сайт, который показывает масштаб компании, укрепляет доверие и ведет клиента к целевому действию
- 2026-07-10 » Сайт бронирования, который превращает интерес клиента в прямую бронь, запись или заявку
- 2026-07-10 » Образовательный сайт под ключ
- 2026-07-03 » Аналитика нового поколения: как Яндекс Метрика превращает данные в управляемые конверсии
- 2026-07-03 » Прорыв в инфлюенс-маркетинге: Яндекс Директ научился оптимизировать рекламу в Telegram и MAX под реальные продажи
- 2026-07-03 » Нейросетевой дуэт: как Gorgona и Argus меняют правила игры в контекстной рекламе Яндекса
- 2026-07-03 » Рекламная революция в «Яндекс Директе»: с 14 июля текстово-графические объявления окончательно уступают место комбинаторным
- 2026-07-03 » Макс запустил тест комментариев в публичных каналах
- 2026-07-01 » Уникальность текста: когда копировать контент можно, а когда нельзя
Все мы сидим в сточной канаве, но некоторые при этом смотрят на звезды Уайльд Оскар - (1854-1900) - английский писатель |

Мы создаем практически любые сайты от продающих страниц до сложных, высоконагруженных и нестандартных веб приложений! Наши сайты это надежные маркетинговые инструменты для успеха Вашего бизнеса и увеличения вашей прибыли! Мы делаем красивые и максимально эффектные сайты по доступным ценам уже много лет!
Комплексный подход это не просто продвижение сайта, это целый комплекс мероприятий, который определяется целями и задачами поставленными перед сайтом и организацией, которая за этим стоит. Время однобоких методов в продвижении сайтов уже прошло, конкуренция слишком высока, чтобы была возможность расслабиться и получать \ удерживать клиентов из Интернета, просто сделав сайт и не занимаясь им...
Мы оказываем полный комплекс услуг по сопровождению сайта: информационному и техническому обслуживанию и развитию Интернет сайтов.
Контекстная реклама - это эффективный инструмент в интернет маркетинге, целью которого является увеличение продаж. Главный плюс контекстной рекламы заключается в том, что она работает избирательно.