如何为Orchard Layout创建自定义容器元素?

劳耶森

我正在使用Orchard 1.9.3,并遵循了一些有关如何在Orchard中创建自定义普通元素的教程。我找不到专门用于创建容器元素的任何东西,因此我在源代码中进行了一些挖掘,到目前为止,这是我所拥有的:

Elements / Procedure.cs

public class Procedure : Container
{
    public override string Category
    {
        get { return "Content"; }
    }

    public override string ToolboxIcon
    {
        get { return "\uf0cb"; }
    }

    public override LocalizedString Description
    {
        get { return T("A collection of steps."); }
    }

    public override bool HasEditor
    {
        get { return false; }
    }
}

驱动程序/ProcedureElementDriver.cs

public class ProcedureElementDriver : ElementDriver<Procedure> {}

服务/过程模型图

public class ProcedureModelMap : LayoutModelMapBase<Procedure> {}

视图/LayoutEditor.Template.Procedure

@using Orchard.Layouts.ViewModels;
<div class="layout-element-wrapper" ng-class="{'layout-container-empty': getShowChildrenPlaceholder()}">
<ul class="layout-panel layout-panel-main">
    <li class="layout-panel-item layout-panel-label">Procedure</li>
    @Display()
    @Display(New.LayoutEditor_Template_Properties(ElementTypeName: "procedure"))
    <li class="layout-panel-item layout-panel-action" title="@T("Delete {{element.contentTypeLabel.toLowerCase()}} (Del)")" ng-click="delete(element)"><i class="fa fa-remove"></i></li>
    <li class="layout-panel-item layout-panel-action" title="@T("Move {{element.contentTypeLabel.toLowerCase()}} up (Ctrl+Up)")" ng-click="element.moveUp()" ng-class="{disabled: !element.canMoveUp()}"><i class="fa fa-chevron-up"></i></li>
    <li class="layout-panel-item layout-panel-action" title="@T("Move {{element.contentTypeLabel.toLowerCase()}} down (Ctrl+Down)")" ng-click="element.moveDown()" ng-class="{disabled: !element.canMoveDown()}"><i class="fa fa-chevron-down"></i></li>
</ul>
<div class="layout-container-children-placeholder">
    @T("Drag a steps here.")
</div>
@Display(New.LayoutEditor_Template_Children())

所有这些或多或少都是从Row元素复制的。现在Procedure,我有一个可以从工具箱拖动到布局上元素,但是即使我可以用这种方式覆盖其他布局元素的模板,也无法将其与模板一起渲染,而且我仍然无法将任何子级拖动到它。我曾希望,仅从中继承Container就可以实现这一点。

我本质上只是想做一个限制性更强的“行”和“列”对,以对任意内容列表应用一些自定义样式。我怎么能告诉Orchard,一个过程只能包含在一个列中,并且它应该接受Steps(或其他一些元素)作为子元素?

劳耶森

通过查看Mainbit的layout模块,我了解了如何制作容器和可包含元素容器元素需要一些其他的Angular代码才能使它们起作用。我仍然需要帮助弄清楚如何限制可以包含哪些元素!

脚本/LayoutEditor.js

我必须用指令扩展LayoutEditor模块,以容纳与我的元素有关的所有Angular东西:

angular
.module("LayoutEditor")
.directive("orcLayoutProcedure", ["$compile", "scopeConfigurator", "environment",
    function ($compile, scopeConfigurator, environment) {
        return {
            restrict: "E",
            scope: { element: "=" },
            controller: ["$scope", "$element",
                function ($scope, $element) {
                    scopeConfigurator.configureForElement($scope, $element);
                    scopeConfigurator.configureForContainer($scope, $element);
                    $scope.sortableOptions["axis"] = "y";
                }
            ],
            templateUrl: environment.templateUrl("Procedure"),
            replace: true
        };
    }
]);

脚本/Models.js

Orchard的LayoutEditor的提供者可以使用:

var LayoutEditor;
(function (LayoutEditor) {

LayoutEditor.Procedure = function (data, htmlId, htmlClass, htmlStyle, isTemplated, children) {
    LayoutEditor.Element.call(this, "Procedure", data, htmlId, htmlClass, htmlStyle, isTemplated);
    LayoutEditor.Container.call(this, ["Grid", "Content"], children);

    //this.isContainable = true;
    this.dropTargetClass = "layout-common-holder";

    this.toObject = function () {
        var result = this.elementToObject();
        result.children = this.childrenToObject();
        return result;
    };
};

LayoutEditor.Procedure.from = function (value) {
    var result = new LayoutEditor.Procedure(
        value.data,
        value.htmlId,
        value.htmlClass,
        value.htmlStyle,
        value.isTemplated,
        LayoutEditor.childrenFrom(value.children));
    result.toolboxIcon = value.toolboxIcon;
    result.toolboxLabel = value.toolboxLabel;
    result.toolboxDescription = value.toolboxDescription;
    return result;
};

LayoutEditor.registerFactory("Procedure", function (value) {
    return LayoutEditor.Procedure.from(value);
});

})(LayoutEditor || (LayoutEditor = {}));

具体来说,这是告诉元素可以包含哪些内容的行:

LayoutEditor.Container.call(this, ["Grid", "Content"], children);

ResourceManifest.cs

然后,我制作了一个资源清单,以轻松地在Orchard的模块中使它们可用。

public class ResourceManifest : IResourceManifestProvider
{
    public void BuildManifests(ResourceManifestBuilder builder)
    {
        var manifest = builder.Add();
        manifest.DefineScript("MyModule.Models").SetUrl("Models.js").SetDependencies("Layouts.LayoutEditor");
        manifest.DefineScript("MyModule.LayoutEditors").SetUrl("LayoutEditor.js").SetDependencies("Layouts.LayoutEditor", "MyModule.Models");
    }
}

默认情况下,.SetUrl()指向模块/主题中的/ Scripts文件夹。

处理程序/LayoutEditorShapeEventHandler.cs

最后,我添加了此处理程序,以在使用布局编辑器的管理页面上加载脚本。

public class LayoutEditorShapeEventHandler : IShapeTableProvider
{
    private readonly Work<IResourceManager> _resourceManager;
    public LayoutEditorShapeEventHandler(Work<IResourceManager> resourceManager)
    {
        _resourceManager = resourceManager;
    }

    public void Discover(ShapeTableBuilder builder)
    {
        builder.Describe("EditorTemplate").OnDisplaying(context =>
        {
            if (context.Shape.TemplateName != "Parts.Layout")
                return;

            _resourceManager.Value.Require("script", "MyModule.LayoutEditors");
        });
    }
}

希望这会在将来对某人有所帮助。但是,我仍然不知道如何做到这一点,以使我的容器包含我的Containable或我的Containable允许其自身包含在我的Container中。似乎调整LayoutEditor.Container.call(this, ["Grid", "Content"], children);就足以实现这一目标,但事实并非如此。仍然欢迎更多帮助。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章