Embed layout editor

Topics: Customizing Orchard, Writing modules
Aug 13, 2015 at 6:12 PM
Anyone here know how to embed the layout editor into a page? I'm trying to add a layout to a custom action and I cant seem to get the layout editor to embed in the edit action screen. Honestly, I'm not even sure how to approach this problem in a proper orchard way...
Developer
Aug 13, 2015 at 10:11 PM
Edited Aug 13, 2015 at 10:13 PM
Yes, very easy actually. All you need is a property of type Orchard.Layouts.ViewModels.LayoutEditor on your viewmodel and render its editor using the Html.EditorFor<TModel> HTML helper. There is a service called ILayoutEditorFactory that can create the Orchard.Layouts.ViewModels.LayoutEditor for you. An example:
public class MyViewModel {
   public LayoutEditor LayoutEditor { get; set; }
}

// Construct the view model.
var layoutData = ""; // Initially we don't have any layout data (layout data is the JSON serialized representation of the layout elements).
var viewModel = new MyViewModel {
   LayoutEditor = _layoutEditorFactory.Create(layoutData, sessionKey: "") // Ignore SessionKey, it's for advanced scenarios.
};

// Render the layout editor.
@model MyViewModel
@Html.EditorFor(m => m.LayoutEditor)
On postback, simply model bind your view model and persist the layout editor data wherever you like (most likely as part of some content part or some some record):
// From some controller action:
var viewModel = new MyViewModel(); // Or accept an action method argument of this type to automatically bind the model.
UpdateModel(viewModel);

var layoutData = viewModel.LayoutEditor.Data;
// Save the layout data somewhere nice.
With the serialized layout data in hand, you can turn it into a layout shape for rendering on the front end using the ILayoutManager.RenderLayout method, which returns a shape you can render using @Display in a view:
var layoutShape = _layoutManager.RenderLayout(layoutData);

@Display(layoutShape)
Aug 14, 2015 at 2:36 PM
Thank you, I did actually end up finding this after asking and a little more digging :) but i still have one more question (I dont know if it belongs in its own topic)
When I describe a form for this custom action, the data is pulled and mapped by a javascript function on the client side, but how do I get the action in order to extract the data here? this form has no cshtml, it just uses this describe function. As it stands right now, the form data is retrieved by the loadForm javascript function, but seems to be ignored by the loading editor.
public void Describe(DescribeContext context)
        {
            Func<IShapeFactory, dynamic> form =
                shape =>
                {
                    LayoutPart part = new LayoutPart();
                    var f = shapeFactory.Form(
                        Id: "ActionForm",
                        _Outcomes: shapeFactory.TextBox(Id: "action-text-box", Name: "Action", Title: T("Action")),
                        _HasForm: shapeFactory.CheckBox(Id: "HasForm", Name: "HasForm", Title: T("Uses a Form"), Value: "true"),
                        _Form: shapeFactory.EditorTemplate(Id: "Form", Name: "Form", Title: T("From"), TemplateName: "Parts.Layout", Prefix: "LayoutPart",
                            Model: new LayoutPartViewModel {
                                LayoutEditor = layoutEditorFactory.Create("", "")
                            })

                    );
                    
                    return f;
                };

            context.Form("ActionForm", form);
        }
Aug 14, 2015 at 6:17 PM
So actually I figured this out myself, I added a script to the form that runs that reloads the editor with the bound data.
Sep 16, 2015 at 9:19 PM
I'm having an issue where it is throwing an exception
LayoutEditor = layoutEditorFactory.Create("", "")
I keep getting an exception farther down the pipe that the content is null, but the default for content is null for this function call...