Доведем форму до ума
В первой части статьи была подготовлена основа для формы обратной связи, в этой части закончим начатое. Я добавил некоторое количество полей на форму. Теперь разметка формы выглядит так:
1: <h3data-bind=»text: view.title»></h3> 2: <pdata-bind=»text: sendResult»></p> 3: <divdata-bind=»ifnot: isbusy, visible: sended»> 4: <p> 5: <labelfor=»Subject»>Выберите тему сообщения</label> 6: <selectdata-bind=»options: subjects, value: vm().Subject, optionsCaption:’выбрать тему'»id=»Subject»></select> 7: <small>загружено тем: <spandata-bind=»text: subjects().length»></span>шт.</small> 8: <br/> 9: <spandata-bind=»visible: vm().Subject»>Выбранная тема: <b> 10: <spandata-bind=»text: vm().Subject»></span></b> 11: </span> 12: </p> 13: <p> 14: <labelfor=»userName»>Ваше имя</label> 15: <inputtype=»text»data-bind=»value: vm().UserName»id=»userName»required/> 16: </p> 17: <p> 18: <labelfor=»email»>Ваш почтовый адрес для ответа</label> 19: <inputtype=»email»data-bind=»value: vm().Email»id=»email»required/> 20: </p> 21: <p> 22: <labelfor=»message»>Тескт сообщения</label> 23: <textareaid=»message»data-bind=»value: vm().Message»rows=»5″required></textarea> 24: </p> 25: <p> 26: <buttondata-bind=»click: sendMessage»>Отправить сообщение</button> 27: </p> 28: </div> 29: 30: @section scripts { 31: @Scripts.Render(«~/bundles/koval») 32: <scriptsrc=»@Scripts.Url(«~/js/site.core.js»)»></script> 33: <script src=»@Scripts.Url(«~/js/site.service.feedback.js»)»></script> 34: <script src=»@Scripts.Url(«~/js/site.vm.feedback.js»)»></script> 35: }
Поясню некоторые строки этого листинга:
Новый JsonResult
Напишем новый метод контролера Ajax, который как раз и должен будет отправлять сообщение администратору.
1: /// <summary> 2: /// Отправленная с формы модель 3: /// будет приходить сюда 4: /// </summary> 5: /// <param name=»model»></param> 6: /// <returns></returns> 7: [HttpPost] 8: public JsonResult SendFeedback(FeedbackViewModel feedback) { 9: string message = «Простите ошибка. Не могу отправить сообщение. Возможно форма неверно заполнена или проблемы на сервере.»; 10: bool sended = false; 11: if (ModelState.IsValid) { 12: 13: // реальная отправка сообщения 14: message = «Спасибо за ваше сообщение. Приходите еще!»; 15: sended = true; 16: } 17: return Json(new { Message = message, Sended = sended }); 18: }
Опять вернемся Javascript
А теперь на код изменившегося ViewModel’а для javascript:
1: /////////////////////////////////////////////////////////////// 2: // site.feedback 3: // Работает через dataService с объектами на форме 4: // Feedback 5: // автор: calabonga.net 6: /////////////////////////////////////////////////////////////// 7: 8: (function (site) { 9: 10: «use strict»; 11: 12: site.vm.feedbackViewModel = function () { 13: var 14: view = { 15: title: «Отправка сообщения» 16: }, 17: subjects = ko.observableArray([]), 18: sendResult = ko.observable(«Заполните все поля формы, пожалуйста»), 19: isbusy = ko.observable(false), 20: cansended = ko.observable(true), 21: feedback = ko.observable({ 22: «Subject»: ko.observable(), 23: «UserName»: ko.observable(), 24: «Email»: ko.observable(), 25: «Message»: ko.observable() 26: }), 27: 28: loadSubjects = function () { 29: isbusy(true); 30: site.services.feedbackForm.loadSubjects(callbackSubjects); 31: }, 32: callbackSubjects = function (json) { 33: isbusy(false); 34: ko.mapping.fromJS(json, {}, subjects); 35: var total = subjects().length; 36: }, 37: sendMessage = function () { 38: sendResult(«Ждите. Идет отправка сообщения»); 39: isbusy(true); 40: site.services.feedbackForm.sendFeedback(JSON.stringify(feedback), callbackMessage); 41: }, 42: callbackMessage = function (json) { 43: isbusy(false); 44: cansended(json.Sended ? false : true) 45: sendResult(json.Message); 46: }; 47: 48: loadSubjects(); 49: 50: return { 51: view: view, 52: vm: feedback, 53: isbusy: isbusy, 54: sendResult: sendResult, 55: sended: cansended, 56: subjects: subjects, 57: sendMessage: sendMessage 58: } 59: 60: }(); 61: 62: })(site);
Как не трудно заметить, добавились новые свойства и новый ViewModel для модели FeedbackViewModel:
1: /////////////////////////////////////////////////////////////// 2: // ViewModel для отправки feedback на сервер 3: // автор: calabonga.net 4: /////////////////////////////////////////////////////////////// 5: 6: function FeedbackViewModel(subject, userName, email, message) { 7: this.Subject = subject; 8: this.UserName = userName; 9: this.EmailAdrress = email; 10: this.Message = message; 11: };
Вот так теперь выглядит форма обратной связи:
А теперь опишу как это работает. Сейчас валидация объекта не предусмотрена. Как можно догадаться, проверку на правильность ввода пользователя проверяет метод контролера SendFeedback. У меня в планах показать, как можно использовать валидацию отправляемого объекта при помощи Knockout.Validation. И это я сделаю чуть позже, а пока посмотрите как работает текущий вариант формы.
Так выглядит форма если пользователь ввел неправильные данные. Подчеркнутое сообщение приходит как результат действия метода контроллера (то есть это серверная валидация):
Вот так форма отображается, если пользователь отправил верные данные:
Работает всё прекрасно, вот только пользователь, ни коим образом не знает о том, какую именно ошибку он совершил, а если бы форма была посложнее? Очень трудно было бы определить, в каком именно поле была допущена ошибка. Решить данную проблему поможет Knockout.Validation. Раз у ж мы используем ko, то и валидацию будем использовать на его основе, хотя нельзя забывать что существует еще и jquery.validation (и другие, сторонние разработки). Более того, существует вариант использовать jquery.validation в knockout.
Knockout.Validation в действии
Так как сборки (пакеты) уже все подключены. Мне остается немного подправить Javascript ViewModel’а чтобы заработала валидация. Вот измененные строки, которые немного дополнили объявление feedback:
1: feedback = ko.validatedObservable({ 2: «Subject»: ko.observable().extend({ required: true }), 3: «UserName»: ko.observable().extend({ required: true, minLength: 4 }), 4: «Email»: ko.observable().extend({ required: true, email: true }), 5: «Message»: ko.observable().extend({ required: true, minLength: 10 }) 6: }),
Обратите внимание, что сам объект feedback стал теперь не просто ko.observable(), а ko.validatedObservable(). И еще надо немного на форме подправить привязку формы отправки:
1: <p> 2: <buttondata-bind=»click : sendMessage, enable: vm().isValid()»>Отправить сообщение</button> 3: </p>
Теперь кнопка отправки будет влючена, только если объект feedback будет валиден (правильно заполнен). Правда же ничего сложного? Если попробовать ввести некорректные данные, форм заартачится и вывалит кучу сообщений:
Дополнительная информация по типам валидации расширяемости свойств можно посмтреть на сайте плагина. Кстати, кажется не очень удачная идея отображать русскому пользователю сообщения на английском языке. Можно скачать локализацию положить ее в папку scripts под названием knockout.validation.ru-RU.js. Более ничего делать не надо, даже добавлять в пакет (Bundle), потому файл будет подключен автоматически из-за того, что виртуальный путь до пакета Knockout.Validation использует “*”.
1: bundles.Add(new ScriptBundle(«~/bundles/koval»).Include( 2: «~/Scripts/knockout.validation.*»
Обновив страницу, можно будет читать сообщения на русском языке.
Ну, и на последок, остается немного разукрасить выводимое сообщение, что они были более заметны. Нужно в CSS задать стиль validationMessage.
1: .validationMessage 2: { 3: background-color:red; 4: color:white; 5: padding:5px; 6: }
Вот окончательный вариант формы обратной связи:
Вместо заключения
Вот наверное и всё. Пишите комментарии. И ссылка на демонстрационный проект.
Подробнее: http://feedproxy.google.com/~r/blogmusor/~3/d14dgm8iOpo/94
Источник: