4
votes

I have an interesting issue. I have a website which sends emails. The email templates are often straight forward but for one client he wants me to convert content from his public website into email friendly html.

I want to not just solve the problem for his specific website but for other unknown websites. So I remembered that you can run Razor as a template engine.

Long story short. It is working and working well. My issue comes down to this. When someone edits the template with razor style for loops Ckeditor acts quite strangely.

Any idea how to keep CKEditor from screwing up?

<table style="width: 100%;" width="100%">
<tbody>
@foreach (var row in body.indexPageRow) { 
foreach (var cell in row.teaser) {
    <tr>
        <td class="row">@Raw(cell.teaserContent.a.Html)</td>
        <td class="row">@Raw(cell.teaserContent.div.InnerHtml)</td>
    </tr>
    }}
</tbody>
</table>

The above code when saved in ckeditor removes the razor information and becomes an empty table

<table style="width: 100%;" width="100%">
    <tbody></tbody>
</table>
2
Why are you editing a template with ckeditor? How would you expect WYSIWYG for loops to work?Eric

2 Answers

4
votes

The only way I can think of to achieve this would be to use html comments in conjunction with razor comments.

Initially you would author the razor template like so:

@{
    Layout = null;
}

<!DOCTYPE html>
<html>
<head>
    <title>Index</title>
</head>
<body>
<table>
<tbody>
    <tr><td>X</td><td>Y</td></tr>
@*<!--*@
    @for (var x = 1; x < 5; x++) { 
    for (var y = 1; y < 5; y++) {
@*-->*@
    <tr>
        <td class="row">@Html.Raw(x)</td>
        <td class="row">@Html.Raw(y)</td>
    </tr>
@*<!--*@
    }
}
@*-->*@
</tbody>
</table>
</body>
</html>

The code above is valid and will render without error. But when you put it into the html editor it will be rearranged by the browser, so you will need to alter it just before it is displayed for editing so that the razor comments are removed and only the html comments remain.

So, once you have removed the razor comments by replacing all instances of @*<!--*@ with <!-- and all instances of @*-->*@ with --> you should have the following

<!DOCTYPE html>
<html>
<head>
    <title>Index</title>
</head>
<body>
<table>
<tbody>
    <tr><td>X</td><td>Y</td></tr>
<!--
    @for (var x = 1; x < 5; x++) { 
    for (var y = 1; y < 5; y++) {
-->
    <tr>
        <td class="row">@Html.Raw(x)</td>
        <td class="row">@Html.Raw(y)</td>
    </tr>
<!--
    }
}
-->
</tbody>
</table>
</body>
</html>

This will render in the html editor and wont get mangled by the browser as pointed out by Alfonso, an example of this on jsfiddle http://jsfiddle.net/wPGLd/3/

Once the editing is complete you will need to capture the html and reapply the razor comments by replacing all instances of <!-- with @*<!--*@ and all instances of --> with @*-->*@

Intercepting the html before and after it enters the ckeditor is fairly straight forward and well documented. I found the following article that explains a little about how to get the ckeditor content on submit

How to update CKEditor content on form submit – equivalent of OnAfterLinkedFieldUpdate FCKEditor

The following question also covers this

Update editor content immediately before save in CKEditor plug-in

0
votes

You can't.

The browser will rearrange those contents: http://jsfiddle.net/wPGLd/

<!DOCTYPE html>
<html>
<head>
<script type='text/javascript'>//<![CDATA[ 
window.onload=function(){
alert(document.body.innerHTML)
}//]]>  
</script>
</head>
<body>
  <table style="width: 100%;" width="100%">
<tbody>
@foreach (var row in body.indexPageRow) { 
foreach (var cell in row.teaser) {
    <tr>
        <td class="row">@Raw(cell.teaserContent.a.Html)</td>
        <td class="row">@Raw(cell.teaserContent.div.InnerHtml)</td>
    </tr>
    }}
</tbody>
</table>

</body>
</html>