I was able to supply the view layer with EditFrame
HTML by adding the opening and closing HTML markup into my MVC Model.
HTMLHelper
Step 1: Obtain access to HtmlHelper using your current context Controller and a "Fake View".
public static HtmlHelper GetHtmlHelper(this Controller controller)
{
StringBuilder sb = new StringBuilder();
HtmlTextWriter htw = new HtmlTextWriter(new System.IO.StringWriter(sb, System.Globalization.CultureInfo.InvariantCulture));
var viewContext = new ViewContext(controller.ControllerContext, new FakeView(), controller.ViewData, controller.TempData, htw);
return new HtmlHelper(viewContext, new ViewPage());
}
An example of using fake view can be found on this question.
EditFrame Rendering
Step 2: Use the EditFrameRendering class (similar to that in Habitat) to obtain the opening and closing HTML markup.
public void SetEditDatasourceEditFrame(IComponentModelBase model, Controller controller)
{
var htmlHelper = controller.GetHtmlHelper();
EditFrameRendering editFrame = new EditFrameRendering(htmlHelper.ViewContext.Writer, model.DataSourcePath, _editFrameLocation, "Edit Component", string.Empty, string.Empty, null);
model.EditDatasourceStart = editFrame.EditFrameStart();
model.EditDatasourceEnd = editFrame.EditFrameEnd();
}
EditFrameRendering.cs
Note the modification to EditFrameRendering.cs from the Habitat project to support the code above.
public string EditFrameStart()
{
StringWriter stringWriter = new StringWriter();
// Put HtmlTextWriter in using block because it needs to call Dispose.
using (HtmlTextWriter writer = new HtmlTextWriter(stringWriter))
{
this._editFrame.RenderFirstPart(writer);
}
// Return the result.
return stringWriter.ToString();
}
public string EditFrameEnd()
{
StringWriter stringWriter = new StringWriter();
// Put HtmlTextWriter in using block because it needs to call Dispose.
using (HtmlTextWriter writer = new HtmlTextWriter(stringWriter))
{
this._editFrame.RenderLastPart(writer);
}
// Return the result.
return stringWriter.ToString();
}
View Layer
In your view layer access the model, writing out the start and end HTML. Adding any content to go within the edit frame between the tags.
Example React View:
const ReactDOMServer = require('react-dom/server');
...
editFrameMarkup() {
const content = (<div>My Edit Frame</div>);
return (<li><div dangerouslySetInnerHTML={this.createMarkup(this.props.data.EditDatasourceStart, content, this.props.data.EditDatasourceEnd)} /></li>);
},
createMarkup(open, content, close) {
const htmlString = ReactDOMServer.renderToStaticMarkup(content);
const wrapper = open + htmlString + close;
return { __html: wrapper };
}
The above markup was taken from a reusable react component used across all renderings. The model was passed to this react component as a property called data.
The Github example is available here.