一键导入
ewl-page-advanced
Advanced EWL page patterns including forms, PostBack, validation, client-side modification, and component state
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Advanced EWL page patterns including forms, PostBack, validation, client-side modification, and component state
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Configure opencode on a new development machine for EWL work by creating the global AGENTS.md and granting access to the EWL source, EWL System Manager source, EWL folder, and EWL client systems directory. Use when setting up opencode on a new machine, or when the user asks to bootstrap, initialize, or configure global opencode for EWL.
Run local EWL Development Utility (DU) operations on EWL systems. Use when asked to run DU operations such as sync or update-data against a particular path or system.
Database schema migration using FluentMigrator with the EWL Data Migrator project
Inspect and troubleshoot EWL systems hosted in Azure — locating an installation's App Service, Container App Job, and Log Analytics workspace, and reliably reading Container App (data migrator) console and system logs. Use when checking whether a deploy's data migrator ran, reading container logs for a hosted installation, or investigating an installation's Azure resources. Companion to ewl-azure-pipelines, which covers the build/deploy pipelines that create these resources.
Test changes to EWL agent rules, subagents, skills, OpenCode plugins, and MCP tools by driving OpenCode headlessly, capturing transcripts, and cleaning up afterwards. Load this skill when verifying changes to anything under Library\Files\Agent Rules.md, Library\Files\Agents\, Library\Files\Agent Skills\, Library\Files\OpenCode Plugins\, or Library\Files\OpenCode Tools\.
Azure Pipelines CI/CD for EWL systems including build templates, deploy templates, and pipeline code generation
| name | ewl-page-advanced |
| description | Advanced EWL page patterns including forms, PostBack, validation, client-side modification, and component state |
Forms use FormState.ExecuteWithActions to connect form controls to a
PostBack. PostBack execution has three stages: form validation, modification
method, and post-modification action.
protected override PageContent getContent() {
var mod = ServiceOrderId.HasValue
? serviceOrderRow.ToModification()
: ServiceOrdersModification.CreateForInsert();
return FormState.ExecuteWithActions(
PostBack.CreateFull(
modificationMethod: () => {
if( !ServiceOrderId.HasValue )
mod.ServiceOrderId = MainSequence.GetNextValue();
mod.Execute();
},
actionGetter: () => new PostBackAction( ParentResource ) ),
() => {
var content = new UiPageContent( contentFootActions: new ButtonSetup( "Submit" ) );
var formItemList = FormItemList.CreateStack()
.AddItem( mod.GetCustomerNameFormItem( false ) )
.AddItem( mod.GetCustomerEmailFormItem( false ) );
content.Add( formItemList );
return content;
} );
}
Modification objects generate form controls with built-in validation. The first boolean parameter typically controls whether the field is optional.
mod.GetCustomerNameFormItem( false )
mod.GetCustomerEmailFormItem( false )
mod.GetServiceTypeIdRadioListFormItem(
RadioListSetup.Create( items.Select( i => SelectListItem.Create( (int?)i.Id, i.Name ) ) ) )
mod.GetNotesFormItem( true, controlSetup: TextControlSetup.Create( numberOfRows: 4 ) )
mod.GetBudgetFormItem( label: "Amount".ToComponents(), allowEmpty: false, minValue: 10, valueStep: 5 )
Use FormState.ExecuteWithValidationPredicate to conditionally skip validation
for hidden or irrelevant controls:
FormState.ExecuteWithValidationPredicate(
() => customerHasBudget.Value,
() => mod.GetBudgetFormItem( false ).ToComponentCollection() );
DataValue<T> tracks a temporary value that is not directly persisted:
var customerHasBudget = new DataValue<bool>( ServiceOrderId.HasValue, () => serviceOrderRow.Budget.HasValue );
Use with checkboxes via ToFlowCheckbox:
customerHasBudget.ToFlowCheckbox(
"Customer has budget".ToComponents(),
setup: FlowCheckboxSetup.Create( nestedContentGetter: () => /* nested controls */ ),
additionalValidationMethod: validator => {
if( !customerHasBudget.Value )
budgetClearer!();
} )
PageModificationValue<T> enables instant client-side changes based on form
control values:
var serviceTypeIdPmv = new PageModificationValue<int?>();
// Connect to a radio list
mod.GetServiceTypeIdRadioListFormItem(
RadioListSetup.Create( items, itemIdPageModificationValue: serviceTypeIdPmv ) );
// Toggle visibility based on value
var displaySetup = serviceTypeIdPmv
.ToCondition( ( (int?)ServiceTypesRows.GeneralService ).ToCollection() )
.ToDisplaySetup();
// Toggle CSS classes based on value
var classes = serviceTypeIdPmv
.ToCondition( ( (int?)ServiceTypesRows.FlatTireRepair ).ToCollection() )
.ToElementClassSet( ElementClasses.FlatTire );
Intermediate post-backs update parts of a page without fully processing the form. They require declaring which regions change.
var requestLineCount = ComponentStateItem.Create( "requestLineCount", initialValue, v => v > 0, false );
var updateRegion = new UpdateRegionSet();
// Button triggers intermediate post-back
new EwfButton(
new StandardButtonStyle( "Add line" ),
behavior: new PostBackBehavior(
postBack: PostBack.CreateIntermediate(
updateRegion,
id: "addLine",
modificationMethod: () => requestLineCount.Value += 1 ) ) );
ComponentStateItem stores data in a hidden field across intermediate
post-backs. Place it within the component tree so it is automatically
discarded when its containing region is rebuilt by another post-back.
Use tailUpdateRegions in ComponentListSetup to declare that new items
added to a list belong to a specific update region.
Wrap components in FlowAutofocusRegion to control focus:
// Focus first control on initial request
content.Add( new FlowAutofocusRegion( AutofocusCondition.InitialRequest(), formItemList.ToCollection() ) );
// Focus after a specific post-back using a focus key
PostBack.CreateIntermediate( region, id: "add", reloadBehaviorGetter: () => new PageReloadBehavior( focusKey: "add" ) );
// In ComponentListSetup:
lastItemAutofocusCondition: AutofocusCondition.PostBack( "add" )
For edit pages that save automatically (no explicit Submit button):
var content = new UiPageContent(
dataUpdateModificationMethod: () => { foreach( var m in modMethods ) m(); },
isAutoDataUpdater: true );