Давайте начнем с того, где мы остановились. Загрузите исходный код предыдущей части, разархивируйте его и откройте в Visual Studio.
В прошлый раз мы получили список расписаний, поместили его в наблюдаемый массив и использовали декларативные привязки (привязка данных), чтобы связать элементы DOM с нашей моделью представления. Другими словами, мы привязываем это к таблице. Knockout затем автоматически отображает строку для каждого расписания в массиве.
Давайте перейдем к следующему шагу в нашем небольшом приложении CRUD и добавим поддержку создания новых расписаний.
Содержание
модальный
Давайте представим пользователю возможность добавить новый график. Скопируйте / вставьте следующий HTML-код чуть ниже таблицы в представлении Index.cshtml.
<div class="pull-right">
<a id="new-timesheet" class="btn btn-success"
data-toggle="modal" href="#timesheet-modal">Add timesheet</a>
</div>
Это отобразит следующую кнопку под правым нижним углом таблицы.
Это демонстрирует некоторые из базовых CSS Twitter Bootstrap для быстрого рендеринга круто выглядящих кнопок .
Кнопка здесь является простым якорем. Заметьте атрибуты data-toggle и href на привязке? Bootstrap магия снова работает. Атрибут data-toggle в основном говорит Bootstrap, что при нажатии кнопки отображается модальное окно с id (href) «timesheet-modal». Кнопка (data-) переключает модальное окно.
Время добавить актуальный модал. Вставьте следующий HTML-код под кнопкой.
<div class="modal hide fade" id="timesheet-modal">
<div class="modal-header">
<button type="button" class="close"
data-dismiss="modal">×</button>
<h3>Timesheet</h3>
</div>
<form id="Timesheet"
data-bind="submit:
function(form) { postTimesheet(form, 'timesheet-modal') }">
<div class="modal-body">
</div>
<div class="modal-footer">
<a href="#" class="btn" data-dismiss="modal">Cancel</a>
<input type="submit" class="btn btn-primary" value="Save" />
</div>
</form>
</div>
Модальный div изначально скрыт из-за класса CSS hide. Он состоит из трех частей, а именно:
- заголовок (модальный заголовок)
- тело (модальное тело)
- нижний колонтитул
Каждая часть украшена классом Bootstrap CSS (модальный заголовок, модальное тело и т. Д.). Заголовок содержит заголовок и кнопку (X), которая позволяет пользователю закрыть модальное окно. Атрибут кнопки data-dismiss сообщает начальной загрузке, что эта кнопка закрывает модальный режим. Тело пока пустое, в то время как нижний колонтитул содержит обычную кнопку отправки и еще одну кнопку для закрытия модального окна.
Перед запуском приложения необходимо изменить еще две вещи.
Сначала добавьте следующий CSS-код в файл site.css, который находится между bootstrap.css и bootstrap-responseive.css, чтобы удалить нижнее поле в 20px, которое начальная загрузка добавляет к формам. Обратите внимание, что тело и нижний колонтитул модала обернуты в форму.
form { margin: 0; }
Эта форма также привязана к нашей модели представления.
<form id="Timesheet"
data-bind="submit: function(form) { postTimesheet(form, 'timesheet-modal') }">
...
</form>
Этот атрибут указывает Knockout вызывать функцию postTimesheet модели представления при отправке формы. Добавьте эту новую функцию в модель представления.
Примечание : обратите внимание, что здесь я передал идентификатор модального параметра функции submitTimesheet (), обернув обработчик в литерал функции, который принимает необходимые параметры. Knockout предоставляет форму по умолчанию для отправки формы, я просто добавил литерал, который содержит идентификатор модального окна. Позже вы поймете, зачем нам это нужно.
postTimesheet: function (form, modalId) {
}
Хорошо, модал теперь полностью настроен. Скомпилируйте и запустите. Если вы сейчас нажмете кнопку «Добавить расписание», появится модальное окно.
Пять минут работы, и у вас есть рабочее модальное окно!
Форма
Теперь мы можем добавить форму тела тела, которую пользователь может заполнить, чтобы добавить новое расписание. Создайте частичное представление с именем _Timesheet.
Визуализируйте частичное представление в теле модала.
...
<div class="modal-body">
@{ Html.RenderPartial("_Timesheet", new Timesheet()); }
</div>
...
Частичное представление _Timesheet использует тип расписания в качестве модели. Он отображает некоторые элементы управления вводом для имени, фамилии, месяца и свойств года.
@model MvcApplication.Models.Timesheet
@Html.LabelFor(m => m.FirstName)
@Html.TextBoxFor(m => m.FirstName)
@Html.LabelFor(m => m.LastName)
@Html.TextBoxFor(m => m.LastName)
@Html.LabelFor(m => m.Month)
@Html.DropDownListFor(m => m.Month, Model.Months)
@Html.LabelFor(m => m.Year)
@Html.TextBoxFor(m => m.Year, new { disabled="disabled" })
Примечание . Если вы посмотрите на код модели расписания, вы заметите, что я добавил несколько аннотаций данных (требуется, отображение … и т. Д.) И IEnumerable из SelectListItem за месяцы.
Теперь ваш модал должен выглядеть следующим образом:
Давайте добавим немного CSS в файл site.css, чтобы убедиться, что обязательные поля помечены красной рамкой.
select.input-validation-error,
input.input-validation-error {
border-color: #FF0000;
border-radius: 7px;
}
select.input-validation-error:focus,
input.input-validation-error:focus {
outline: none;
border-color: #FF0000;
box-shadow: 0 0 10px #FF0000;
}
Если вы отправите форму, не заполнив ни одного поля, вы заметите, что поля имени и фамилии будут помечены как обязательные.
Сброс формы
Закройте модальное и снова откройте его. Что ты заметил? Да, поля по-прежнему помечены как обязательные, красная рамка и все. То же самое, если вы введете некоторые данные, они останутся там в следующий раз, когда вы снова откроете модальное окно. При открытии модальных мы должны вытереть шифер; нам нужно сбросить форму.
Свяжите событие нажатия кнопки «Добавить расписание» с функцией resetForm модели представления следующим образом:
<div class="pull-right">
<a id="new-timesheet" class="btn btn-success"
data-toggle="modal" href="#timesheet-modal"
data-bind="click: resetForm.bind($data, 'Timesheet')">
Add timesheet</a>
</div>
Мы передаем литеральный параметр в функцию resetForm, используя функцию bind , которая присоединяет конкретное значение параметра к ссылке на функцию. Здесь мы передаем идентификатор формы, которую мы хотим сбросить.
Что касается реализации функции resetForm, то это довольно просто. Просто добавьте следующую функцию в вашу модель представления.
resetForm: function (formId) {
var form = $('#' + formId);
form.validate().resetForm();
form.get(0).reset();
}
Используя проверку jQuery, информация о проверке формы сбрасывается и сама форма. Если вы снова откроете модальное поле, поля станут пустыми и больше не будут помечены как обязательные.
POST-он
Теперь все на месте. Форма закончена, давайте разместим данные, введенные пользователем, и создадим новое расписание. Время реализовать функцию postTimesheet модели представления, которую мы добавили ранее.
Давайте пройдем это шаг за шагом. Сначала мы проверяем, проходит ли форма необходимую проверку.
form = $(form);
if (!form.valid())
return;
Затем мы извлекаем введенную информацию из формы и сериализуем ее как JSON.
var json = JSON.stringify(this._getTimesheetFromFrom(form));
_GetTimesheetsFromForm () — это «закрытый» метод в нашей модели представления, который реализован следующим образом:
_getTimesheetFromFrom: function (form) {
form = $(form);
var timesheet = {};
form.find('input[type!=submit],select').each(function () {
timesheet[this.name] = $(this).val();
});
return timesheet;
}
Он берет все входные элементы INPUT и SELECT из формы и возвращает информацию в виде объекта JSON.
{"FirstName":"Dan","LastName":"Harrington","Month":"11","Year":"2012"}
Хорошо, давайте продолжим с реализацией функции postTimesheet (). Данные формы были проверены, полезная нагрузка JSON собрана. Время отправить данные на наш контроллер API Timesheets (REST).
Легкий Peasy Lemon Squeezy. Просто выполните вызов $ .ajax и поместите данные JSON. Когда вы получаете ответ, который является недавно добавленным расписанием, сериализованным как JSON, мы помещаем его в наш наблюдаемый массив расписаний. И последнее, но не менее важное: мы используем параметр modalId, чтобы скрыть модальное окно.
var self = this;
$.ajax({
url: '@Url.RouteUrl("DefaultApi", new { httproute = "", controller = "timesheets" })',
type: 'POST',
data: json,
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function (jsonObject) {
self.timesheets.push(new timesheet(jsonObject));
$('#' + modalId).modal('hide');
}
});
Благодаря магии Knockout наш список расписаний будет обновляться автоматически.
В предыдущем посте было показано, как реализовать READ-часть нашего приложения CRUD, в то время как эта часть демонстрировала CREATE. В третьей статье этой серии мы повторно используем многое из того, что узнали здесь, и реализуем ОБНОВЛЕНИЕ. Четвертый и последний пост обернет все с УДАЛИТЬ.
Вы можете скачать исходный код, сопровождающий эту статью, со страницы загрузки. Если у вас есть какие-либо вопросы или предложения, напишите мне по электронной почте или оставьте комментарий.





