我正在使用 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> {}
服务/ProcedureModelMap
public class ProcedureModelMap : LayoutModelMapBase<Procedure> {}
View /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
元素,我可以将其从工具箱拖动到我的布局上,但它没有使用我的模板呈现,即使我可以通过这种方式覆盖其他布局元素的模板,并且我仍然不能把任何 child 拖进去。我曾希望简单地从 Container
继承就可以实现这一点。
我本质上只是想制作一个更具限制性的行和列对,以将一些自定义样式应用于任意内容列表。我如何告诉 Orchard 过程只能包含在列中,并且它应该接受 Steps
(或其他一些元素)作为子元素?
最佳答案
我通过查看 Mainbit's layout module 了解了如何制作容器和可包含元素。 。 容器元素需要一些额外的 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 使用的 Provider:
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
然后我制作了一个资源 list ,以便轻松地在 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仅允许其自身包含在我的容器中。看起来调整 LayoutEditor.Container.call(this, ["Grid", "Content"], Children); 就足以实现这一目标,但事实并非如此。仍然欢迎更多帮助。
关于orchardcms - 如何为 Orchard 布局创建自定义容器元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36476114/