Reputation: 13581
I am using ckeditor with the jQuery adapter in an ajax scenario. The ckeditor is bound to a textarea element using jQuery.
I am designing an eLearning app for a client. Each course has many steps, drawn from a database table.
The UI of the app is just a form with Previous and Next buttons to navigate through the course.
The issue is with the admin facility, where Tutors can create and update the steps in each course.
Again, the admin facility is just a form with previous and next buttons. However, there is a field called StepText that I want to have html rather than plain text. Hence the requirement for a Rich Text Editor.
The scrolling from step to step is down with Ajax calls, that go off to the controller, get the data for the next (or previous) step, and inject it into the page. The ajax calls return html, created from a partial view.
The textarea is in this partial view. The CKEditor binds correctly the first time the page is loaded, but not for any subsequent ajax responses.
The result is that the ckEditor does not appear with all its goodness and I just get the unappealing nakedness of the textarea.
Any ideas why this is happening?
The following scripts are used:
<script type="text/javascript" src="@Url.Content("~/ckeditor/ckeditor.js")"></script>
<script type="text/javascript" src="@Url.Content("~/ckeditor/adapters/jquery.js")"></script>
This allows me to use ckEditor with jQuery as follows:
$(document).ready(function () {
$('#StepText').ckeditor(function () { }, { toolbar: 'Basic' });
});
The text area is in a partial .cshtml file, within a div that acts as the target for the ajax call:
Edited!! to show how the ajax call is made !!
<div id="ajaxEditor">
@using (Ajax.BeginForm(MVC.Admin.StepEditor.Edit(), new AjaxOptions { UpdateTargetId = "ajaxEditor", HttpMethod = "POST" },
new { @name = "EditStepForm", @id = "EditStepForm" }))
{
<div class="editor-label">
@Html.LabelFor(model => model.StepText)
</div>
<div class="editor-field">
@Html.TextAreaFor(model => model.StepText, 20, 68, null)
@Html.ValidationMessageFor(model => model.StepText)
</div>
}
</div>
I tried rebinding the ckeditor in the OnSuccess of the ajax call, but when debugging the jQuery in Chrome, I get the following error:
Uncaught [CKEDITOR.editor] The instance "myTextArea" already exists.
Which is what you would expect: the control name is still the same and there has not been a full page refresh.
Upvotes: 3
Views: 9380
Reputation: 760
I had this problem too, but the senario was a bit different, I used ckeditor in an Ajax.BeginForm but my form(partial view) is coming up in a jquery ui dialog, the first answer gave me a great idea to fix that. I did rebinding for ckeditor when dialog is coming up!
$('input[type=submit]').bind('click', function () {
$('.ckeditor').ckeditorGet().updateElement();
});
CKEDITOR.editorConfig =
new { @class = "ckeditor" })
to TextAreaFor(partial view) and adding this line in parent page delete CKEDITOR.instances['FieldName'];
in the parent page i call the dialog:
function openDialog() {
$('#dialog').dialog('open');
delete CKEDITOR.instances['Ingredient'];
CKEDITOR.editorConfig = function (config) {
config.uiColor = "#EFEFEF";
config.toolbar =
[{ name: 'basicstyles', items: ['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat']}];
config.width = 400;
config.height = 100;
config.autoParagraph = false;
config.removePlugins = 'elementspath';
config.resize_enabled = false;
config.enterMode = CKEDITOR.ENTER_BR;
config.startupFocus = true;
};
$('.ckeditor').ckeditor();
$('input[type=submit]').bind('click', function () {
$('.ckeditor').ckeditorGet().updateElement();
});
}
in my partial view with Ajax.BeginForm:
<div class="editor-field">
@Html.TextAreaFor(model => model.Ingredient, new { @class = "ckeditor" })
@Html.ValidationMessageFor(model => model.Ingredient)
</div>
as you see I did NOT use OnCompelete or OnBegin. hope it helps somebody!
Upvotes: 1
Reputation: 51
this worked best for me using the jquery ckeditor adapter. I just call this when I load up some ajax with a ckeditor textarea.
function initCKEditor() {
$('.wysiwyg').ckeditor(function(e){
delete CKEDITOR.instances[$(e).attr('name')];
},{
toolbar:
[
['Bold','Italic','Underline','Strike','-','NumberedList','BulletedList','-','Paste','PasteFromWord','-','Outdent','Indent','-','Link','-','Maximize','-','Source']
],
skin: 'office2003'
}
);
}
Upvotes: 1
Reputation: 13581
If Chris Marisic wants to upgrade his comment to an answer, I will give him the biscuit.
I have solved as follows:
<div id="ajaxEditor">
@using (Ajax.BeginForm(MVC.Admin.StepEditor.Edit(), new AjaxOptions { UpdateTargetId = "ajaxEditor", HttpMethod = "POST", OnComplete="ReBindCKEditor" },
new { @name = "EditStepForm", @id = "EditStepForm" }))
{
<div class="editor-label">
@Html.LabelFor(model => model.StepText)
</div>
<div class="editor-field">
@Html.TextAreaFor(model => model.StepText, 20, 68, null)
@Html.ValidationMessageFor(model => model.StepText)
</div>
}
</div>
As the error coming back (see response to Chris Marisic in question) states that the CKEDITOR instance already exists, I need to get rid of it. So:
function BindCKEditor() {
var elem = $('#StepText');
elem.ckeditor(function () {}, { toolbar: [
['Source'],
['Preview'],
['Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Scayt'],
['Undo', 'Redo', '-', 'Find', 'Replace', '-', 'SelectAll', 'RemoveFormat'],
['Image', 'Table', 'HorizontalRule'],
['Styles', 'Format'],
['Bold', 'Italic', 'Strike'],
['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', 'Blockquote'],
['Link', 'Unlink', 'Anchor']
]
});
}
BindCKEditor() just does what it says on the tin. It configures the editor and applies it.
Now, when I overwrite the text area with the ajax response, I need to delete that instance and recreate it. So:
function ReBindCKEditor() {
delete CKEDITOR.instances['StepText'];
BindCKEditor();
}
Note that I use ReBindCKEditor() in the OnComplete for the Ajax Form. I use oncomplete and not onsuccess, because I want it to rebind regardless of the success or otherwise of the ajax call.
I can't recommend ckeditor highly enough. I thought this was going to be a nightmare to solve, but once I sat down and put such thoughts aside, I found that there was very concise documentation and good user forums.
I looked at a lot of other Rich Text Editors, and none were as good or as well supported. Yahoo's one looked good, but was a nightmare and documentation poor unless you are a javascript expert which I ain't.
I nearly went with lwrte, it looked good, but no support behind it.
I looked at other that shall remain unnamed.
But ckEditor really has impressed me. I can now roll it out where I want to with no fear or trepidation.
I am not working for CKEditor nor have any connection with them. This is genuine enthusiasm. Yes, such a thing does exist.
Upvotes: 2