Get the FREE Ultimate OpenClaw Setup Guide →

orchardcore-content-fields

Scanned
npx machina-cli add skill CrestApps/CrestApps.AgentSkills/orchardcore-content-fields --openclaw
Files (1)
SKILL.md
19.1 KB

Orchard Core Content Fields - Prompt Templates

Add and Configure Content Fields

You are an Orchard Core expert. Generate migration code and recipes for adding content fields with all available settings.

Guidelines

  • Fields are added to content parts using AlterPartDefinitionAsync in a migration.
  • Each field has a FieldSettings base with Hint (string) and Required (bool).
  • Each field type has its own specific settings class (e.g., TextFieldSettings, NumericFieldSettings).
  • Fields also have ContentPartFieldSettings controlling DisplayName, Description, Editor, DisplayMode, and Position.
  • Use .WithEditor("EditorName") to select an editor variant.
  • Use .WithDisplayMode("DisplayModeName") to select a display variant.
  • Third-party modules providing fields (CrestApps, Lombiq, etc.) must be installed as NuGet packages in the web project (the startup project of the solution), not just in the module project.
  • Always seal classes.

General Pattern for Adding a Field

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("{{FieldType}}")
        .WithDisplayName("{{DisplayName}}")
        .WithDescription("{{Description}}")
        .WithPosition("{{Position}}")
        .WithSettings(new {{FieldType}}Settings
        {
            // Field-specific settings
        })
    )
);

TextField

Stores a single text value. Supports multiple editor modes.

TextField Settings

SettingTypeDefaultDescription
HintstringnullHelp text displayed below the field.
RequiredboolfalseWhether the field is required.
DefaultValuestringnullDefault value for new content items.
TypeFieldBehaviorTypeUnsetField behavior type.
PatternstringnullThe pattern used to build the value.
Placeholderstring""Placeholder text.

TextField Editors

EditorDescription
(default)Standard single-line text input.
TextAreaMulti-line text area.
CodeMirrorCode editor with syntax highlighting.
PredefinedListDropdown or radio buttons from a predefined list.
MonacoMonaco code editor.

TextField Migration

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("TextField")
        .WithDisplayName("{{DisplayName}}")
        .WithPosition("{{Position}}")
        .WithSettings(new TextFieldSettings
        {
            Required = true,
            Hint = "{{Hint}}",
            DefaultValue = "{{DefaultValue}}",
            Placeholder = "{{Placeholder}}"
        })
    )
);

TextField with TextArea Editor

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("TextField")
        .WithDisplayName("{{DisplayName}}")
        .WithEditor("TextArea")
        .WithPosition("{{Position}}")
        .WithSettings(new TextFieldSettings
        {
            Hint = "Enter a detailed description"
        })
    )
);

TextField with PredefinedList Editor

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("TextField")
        .WithDisplayName("{{DisplayName}}")
        .WithEditor("PredefinedList")
        .WithPosition("{{Position}}")
        .WithSettings(new TextFieldPredefinedListEditorSettings
        {
            Editor = EditorOption.Dropdown,
            DefaultValue = "option1",
            Options = new[]
            {
                new ListValueOption("Option 1", "option1"),
                new ListValueOption("Option 2", "option2"),
                new ListValueOption("Option 3", "option3")
            }
        })
    )
);

HtmlField

Stores HTML content with optional sanitization.

HtmlField Settings

SettingTypeDefaultDescription
HintstringnullHelp text displayed below the field.
RequiredboolfalseWhether the field is required.
SanitizeHtmlbooltrueWhether to sanitize HTML content.

HtmlField Editors

EditorDescription
(default)Rich text editor (WYSIWYG).
WysiwygWYSIWYG HTML editor.
TrumbowygTrumbowyg WYSIWYG editor.
MonacoMonaco code editor for raw HTML.

HtmlField Migration

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("HtmlField")
        .WithDisplayName("{{DisplayName}}")
        .WithEditor("Wysiwyg")
        .WithPosition("{{Position}}")
        .WithSettings(new HtmlFieldSettings
        {
            Required = true,
            SanitizeHtml = true,
            Hint = "Enter HTML content"
        })
    )
);

NumericField

Stores a numeric (decimal) value.

NumericField Settings

SettingTypeDefaultDescription
HintstringnullHelp text displayed below the field.
RequiredboolfalseWhether the field is required.
Scaleint0Number of decimal places.
Minimumdecimal?nullMinimum allowed value.
Maximumdecimal?nullMaximum allowed value.
PlaceholderstringnullPlaceholder text.
DefaultValuestringnullDefault value.

NumericField Migration

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("NumericField")
        .WithDisplayName("{{DisplayName}}")
        .WithPosition("{{Position}}")
        .WithSettings(new NumericFieldSettings
        {
            Required = true,
            Minimum = 0,
            Maximum = 999999,
            Scale = 2,
            Placeholder = "0.00",
            Hint = "Enter the price"
        })
    )
);

BooleanField

Stores a true/false value.

BooleanField Settings

SettingTypeDefaultDescription
HintstringnullHelp text displayed below the field.
RequiredboolfalseWhether the field is required.
LabelstringnullLabel text for the checkbox.
DefaultValueboolfalseDefault checked state.

BooleanField Migration

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("BooleanField")
        .WithDisplayName("{{DisplayName}}")
        .WithPosition("{{Position}}")
        .WithSettings(new BooleanFieldSettings
        {
            Label = "Is Featured",
            DefaultValue = false,
            Hint = "Check to mark as featured"
        })
    )
);

DateField

Stores a date value (no time component).

DateField Settings

SettingTypeDefaultDescription
HintstringnullHelp text displayed below the field.
RequiredboolfalseWhether the field is required.

DateField Migration

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("DateField")
        .WithDisplayName("{{DisplayName}}")
        .WithPosition("{{Position}}")
        .WithSettings(new DateFieldSettings
        {
            Required = true,
            Hint = "Select a date"
        })
    )
);

DateTimeField

Stores a date and time value.

DateTimeField Settings

SettingTypeDefaultDescription
HintstringnullHelp text displayed below the field.
RequiredboolfalseWhether the field is required.

DateTimeField Migration

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("DateTimeField")
        .WithDisplayName("{{DisplayName}}")
        .WithPosition("{{Position}}")
        .WithSettings(new DateTimeFieldSettings
        {
            Required = true,
            Hint = "Select date and time"
        })
    )
);

TimeField

Stores a time value.

TimeField Settings

SettingTypeDefaultDescription
HintstringnullHelp text displayed below the field.
RequiredboolfalseWhether the field is required.
StepstringnullStep interval for the time picker (e.g., "00:15:00" for 15-minute steps).

TimeField Migration

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("TimeField")
        .WithDisplayName("{{DisplayName}}")
        .WithPosition("{{Position}}")
        .WithSettings(new TimeFieldSettings
        {
            Required = true,
            Step = "00:15:00",
            Hint = "Select a time"
        })
    )
);

ContentPickerField

References other content items.

ContentPickerField Settings

SettingTypeDefaultDescription
HintstringnullHelp text displayed below the field.
RequiredboolfalseWhether the field is required.
MultipleboolfalseWhether to allow selecting multiple content items.
DisplayAllContentTypesboolfalseWhether to show all content types in the picker.
DisplayedContentTypesstring[][]Content types to display in the picker.
DisplayedStereotypesstring[][]Stereotypes to filter displayed content types.
Placeholderstring""Placeholder text.
TitlePatternstring"{{ Model.ContentItem | display_text }}"Liquid pattern for the displayed title.

ContentPickerField Migration

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("ContentPickerField")
        .WithDisplayName("{{DisplayName}}")
        .WithPosition("{{Position}}")
        .WithSettings(new ContentPickerFieldSettings
        {
            Required = true,
            Multiple = false,
            DisplayedContentTypes = new[] { "BlogPost", "Article" },
            Hint = "Select a related article"
        })
    )
);

MediaField

Attaches media files from the media library.

MediaField Settings

SettingTypeDefaultDescription
HintstringnullHelp text displayed below the field.
RequiredboolfalseWhether the field is required.
MultiplebooltrueWhether to allow multiple files.
AllowMediaTextbooltrueWhether to allow alt text for media.
AllowAnchorsboolfalseWhether to allow anchor points on images.
AllowedExtensionsstring[][]Allowed file extensions (empty = all allowed).

MediaField Migration

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("MediaField")
        .WithDisplayName("{{DisplayName}}")
        .WithPosition("{{Position}}")
        .WithSettings(new MediaFieldSettings
        {
            Required = true,
            Multiple = false,
            AllowMediaText = true,
            AllowedExtensions = new[] { ".jpg", ".jpeg", ".png", ".gif", ".webp" },
            Hint = "Upload an image"
        })
    )
);

LinkField

Stores a URL with optional link text and target.

LinkField Settings

SettingTypeDefaultDescription
HintstringnullHelp text displayed below the field.
RequiredboolfalseWhether the field is required.
HintLinkTextstringnullHint text for the link text input.
LinkTextModeLinkTextModeOptionalLink text mode (Optional, Required, Static, Url).
UrlPlaceholderstringnullPlaceholder for the URL input.
TextPlaceholderstringnullPlaceholder for the text input.
DefaultUrlstringnullDefault URL value.
DefaultTextstringnullDefault link text.
DefaultTargetstringnullDefault target (e.g., _blank).

LinkField Migration

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("LinkField")
        .WithDisplayName("{{DisplayName}}")
        .WithPosition("{{Position}}")
        .WithSettings(new LinkFieldSettings
        {
            Required = true,
            LinkTextMode = LinkTextMode.Required,
            UrlPlaceholder = "https://example.com",
            TextPlaceholder = "Click here",
            Hint = "Enter an external link"
        })
    )
);

MultiTextField

Stores multiple text values from predefined options.

MultiTextField Settings

SettingTypeDefaultDescription
HintstringnullHelp text displayed below the field.
RequiredboolfalseWhether the field is required.
OptionsMultiTextFieldValueOption[][]Available options with Name, Value, and Default.

MultiTextField Migration

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("MultiTextField")
        .WithDisplayName("{{DisplayName}}")
        .WithPosition("{{Position}}")
        .WithSettings(new MultiTextFieldSettings
        {
            Options = new[]
            {
                new MultiTextFieldValueOption { Name = "Red", Value = "red", Default = false },
                new MultiTextFieldValueOption { Name = "Green", Value = "green", Default = true },
                new MultiTextFieldValueOption { Name = "Blue", Value = "blue", Default = false }
            },
            Hint = "Select one or more colors"
        })
    )
);

UserPickerField

References users.

UserPickerField Settings

SettingTypeDefaultDescription
HintstringnullHelp text displayed below the field.
RequiredboolfalseWhether the field is required.
MultipleboolfalseWhether to allow multiple users.
DisplayAllUsersbooltrueWhether to display all users.
DisplayedRolesstring[][]Roles to filter displayed users.
Placeholderstring""Placeholder text.

UserPickerField Migration

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("UserPickerField")
        .WithDisplayName("{{DisplayName}}")
        .WithPosition("{{Position}}")
        .WithSettings(new UserPickerFieldSettings
        {
            Required = true,
            Multiple = false,
            DisplayAllUsers = false,
            DisplayedRoles = new[] { "Author", "Editor" },
            Hint = "Select an author"
        })
    )
);

YoutubeField

Stores a YouTube video URL and embeds the player.

YoutubeField Settings

SettingTypeDefaultDescription
HintstringnullHelp text displayed below the field.
RequiredboolfalseWhether the field is required.
LabelstringnullLabel text.
Widthint0Embed player width (0 = default).
Heightint0Embed player height (0 = default).
Placeholderstring""Placeholder text.

YoutubeField Migration

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("YoutubeField")
        .WithDisplayName("{{DisplayName}}")
        .WithPosition("{{Position}}")
        .WithSettings(new YoutubeFieldSettings
        {
            Required = false,
            Width = 640,
            Height = 360,
            Placeholder = "https://www.youtube.com/watch?v=...",
            Hint = "Paste a YouTube video URL"
        })
    )
);

TaxonomyField

References taxonomy terms. Provided by the OrchardCore.Taxonomies module.

TaxonomyField Settings

SettingTypeDefaultDescription
HintstringnullHelp text displayed below the field.
RequiredboolfalseWhether the field is required.
TaxonomyContentItemIdstringnullThe content item ID of the taxonomy.
UniqueboolfalseWhether to enforce unique selection.
LeavesOnlyboolfalseWhether to allow only leaf terms (no parents).
OpenboolfalseWhether the taxonomy tree is open by default.

TaxonomyField Migration

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("TaxonomyField")
        .WithDisplayName("{{DisplayName}}")
        .WithPosition("{{Position}}")
        .WithSettings(new TaxonomyFieldSettings
        {
            Required = true,
            TaxonomyContentItemId = "{{TaxonomyContentItemId}}",
            LeavesOnly = true,
            Hint = "Select a category"
        })
    )
);

LocalizationSetContentPickerField

References content items by localization set (for multi-lingual content). Provided by OrchardCore.ContentLocalization.

LocalizationSetContentPickerField Migration

await _contentDefinitionManager.AlterPartDefinitionAsync("{{PartName}}", part => part
    .WithField("{{FieldName}}", field => field
        .OfType("LocalizationSetContentPickerField")
        .WithDisplayName("{{DisplayName}}")
        .WithPosition("{{Position}}")
    )
);

Installing Third-Party Field Modules

Modules that provide custom fields from external sources (CrestApps, Lombiq, or community modules) must be installed as NuGet packages in the web project (the startup project of the solution):

<Project Sdk="Microsoft.NET.Sdk.Web">
  <ItemGroup>
    <!-- Orchard Core base -->
    <PackageReference Include="OrchardCore.Application.Cms.Targets" Version="2.*" />

    <!-- Third-party modules must be added to the web project -->
    <PackageReference Include="CrestApps.OrchardCore.AI" Version="1.*" />
    <PackageReference Include="Lombiq.HelpfulExtensions.OrchardCore" Version="1.*" />
  </ItemGroup>
</Project>

For local project references to third-party modules:

<ItemGroup>
  <!-- Local third-party module project reference in the web project -->
  <ProjectReference Include="../ThirdParty.Module/ThirdParty.Module.csproj" />
</ItemGroup>

Source

git clone https://github.com/CrestApps/CrestApps.AgentSkills/blob/main/src/CrestApps.AgentSkills/orchardcore/orchardcore-content-fields/SKILL.mdView on GitHub

Overview

This skill teaches how to add and configure content fields in Orchard Core. It covers every built-in field type, their available settings, editor options, display modes, and migration code patterns to define content schemas reliably.

How This Skill Works

Fields are added to content parts via AlterPartDefinitionAsync, using a fluent pattern: .WithField("FieldName", field => field.OfType("FieldType").WithDisplayName("DisplayName").WithDescription("Description").WithPosition("Position").WithSettings(new FieldSettings)). Each field type has its own Settings class (e.g., TextFieldSettings, NumericFieldSettings). ContentPartFieldSettings controls DisplayName, Description, Editor, DisplayMode, and Position. Editors and display modes are selected with .WithEditor("EditorName") and .WithDisplayMode("DisplayModeName"). If using third‑party fields, the corresponding NuGet packages must be installed in the startup project.

When to Use It

  • You are designing a new content part and need to add one or more fields with precise settings.
  • You want to migrate or duplicate an existing schema, leveraging field-specific settings and editors.
  • You need to offer editor variants (TextArea, CodeMirror, Monaco, etc.) for a field to improve UX.
  • You must control how a field is displayed by selecting display modes and ordering with position.
  • You are integrating third-party field types and must ensure their packages are installed in the startup project.

Quick Start

  1. Step 1: Use AlterPartDefinitionAsync("{{PartName}}", part => part.WithField("{{FieldName}}", field => field.OfType("{{FieldType}}").WithDisplayName("{{DisplayName}}").WithPosition("{{Position}}").WithSettings(new {{FieldType}}Settings { /* field-specific settings */ }) ))
  2. Step 2: For editor variants, chain .WithEditor("EditorName") and/or .WithDisplayMode("DisplayModeName").
  3. Step 3: Apply the migration and verify the field renders correctly in the admin UI and on the front end.

Best Practices

  • Use AlterPartDefinitionAsync consistently to define or update fields in migrations.
  • Always rely on FieldSettings base (Hint and Required) and the field-specific Settings class for precise configuration.
  • Specify DisplayName, Description, Editor, DisplayMode, and Position via ContentPartFieldSettings for clear UI.
  • Leverage WithEditor and WithDisplayMode to tailor the field presentation to user needs.
  • Ensure any third-party field modules are installed as NuGet packages in the startup project, not just in the module project.

Example Use Cases

  • Add a TextField with a DisplayName 'Title' and a placeholder for article content.
  • Add a TextField with a TextArea editor to capture long-form descriptions.
  • Add a TextField using PredefinedList editor to enforce predefined tags.
  • Add a numeric field for item ordering with a sensible DefaultValue.
  • Configure a field’s ContentPartFieldSettings to set DisplayName, Editor, DisplayMode, and Position.

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers