ASP.NET MVC: Редактируем Html в CKEditor через Knockout
В этой статье при помощи Knockout будем редактировать Html-код в WYSIWYG редакторе CKeditor.
Введение
Редактирование html-кода достаточно тривиальная задача. Если учесть, что количество WYSIWYG-редакторов в сети огромное количество, то единственным объяснением, почему именно взят именно CKeditor это то, что я с ним работаю уже более 6 лет, а еще этот редактор может в загружать файлы (например, картинок или флэш) на сервер (правда для этого используется модуль CKFinder).
Тестовый проект
Сразу к делу. Создаю новый проект. Mvc будет 4-ый, .Net пусть будет 4.5, потому как это не принципиально для Knockout. После того как проект создала Visual Studio запускаю команду обновления всех nuget-пакетов. Теперь когда проект почти готов, надо бы загрузить и установить сам редактор CKEditor. Иду по ссылки и качаю последнюю версию (на момент написания статьи версия 4.0.1). Распаковываю архив и (для экономии времени) закидываю всю папку ckeditor в корень проекта. По идеи можно было бы "почистить" немного папку, удалив файлы примера и ненужные плагины, а еще файлы справки (всё равно их никто не читает).

Классы и формы
Создаю новый класс, который будет использоваться… Не будет у меня никаких классов, ибо цель данной статьи показать другое. Ставим новый nuget-пакет, который называется JsSite:
PM> install-package jssite Successfully installed 'JsSite 0.3.0'. Successfully added 'JsSite 0.3.0' to CKEditor_Knockout. PM>
После установки этого пакета, в папке Scripts появилась еще одна папка App. В этот папке набор полезных файликов (немного описания можно найти в статье), которые я сделал, чтобы ускорить разработку проектов такого типа как этот. Просто и быстро. Далее...
Для начала удаляю содержание представления (view) в Home/Index.cshtml, потому что буду писать новую разметку под Knockout. А теперь немного кода на JavaScript.
/// <reference path="../knockout-2.2.1.debug.js" />
/// <reference path="site.services.js" />
/// <reference path="site.controls.js" />
/// <reference path="site.core.js" />
$(function () {
"use strict";
site.vm.homeIndex = function () {
var meta = new site.fw.Metadata("Демонстрация редактирования HTML",
"Данный CKEditor используется в связке с Knockout. Дополнительные инструкции в статье.",
"http://www.calabonga.net/blog/post/107"),
title = ko.observable("Этот текст редактируется!"),
html = title,
save = function () {
alert("Сохранилось! " + html());
};
return {
title: title,
save: save,
meta: meta,
html: html
};
}();
ko.applyBindings(site.vm.homeIndex);
});
В строке 6 создается viewModel для страницы, а в строке 24 осуществляется привязка.
В строке 10 создаем поле, которое я и собираюсь редактировать. А 11-ой я создаю временную переменную, дальше будет понятно.
Теперь немного много разметки. Вся форма (представление Index) целиком:
@{
ViewBag.Title = "Home Page";
}
<h1 data-bind="text: meta.title"></h1>
<p>
<span data-bind="text: meta.description"></span>
<a data-bind="attr: {href: meta.helplink}">
<img style="border: 0" src="~/Images/help.png" alt="" /></a>
</p>
<p><span data-bind="html: title"></span></p>
<p>
<input id="html" name="html" data-bind="ckeditor: html" type="text" value=" " />
</p>
<p>
<button data-bind="click: save">сохранить</button>
</p>
@section scripts
{
<script src="~/ckeditor/ckeditor.js"></script>
<script src="~/Scripts/knockout-2.2.1.js"></script>
<script src="~/Scripts/app/site.bindingHandlers.js"></script>
<script src="~/Scripts/app/site.core.js"></script>
<script src="~/Scripts/app/site.controls.js"></script>
<script src="~/Scripts/app/site.services.js"></script>
<script src="~/Scripts/app/site.vm.homeIndex.js"></script>
}
Ключевыми строчками кода является 13 (прекрасный номер для главной строки, не правда ли?) и строчка номер 23. В 13-ой посмотрите на атрибут data-bind и, соответственно, на ckeditor (код может скачать и посмотреть). В 24 строке как раз, тот самый custom binding.
Запускаем

Отобразился редактор – уже хорошо! Попробуем чего-нибудь написать в редакторе:

Работает!
Заключение
В качестве заключения хочется сказать следующее. У меня задача была редактировать только свойства типа ko.observable(), поэтому я сделал свойство html в моделе и делаю привязку к нему.
Редактировать простой текст простого свойства из Literal Object не получится.