Skip to main content الرئيسية المنشئون aiskillstore marketplace delon-form-dynamic-schema-forms
delon-form-dynamic-schema-forms Create dynamic schema-based forms using @delon/form (SF component). Use this skill when building complex forms with validation, conditional rendering, async data loading, custom widgets, and multi-step workflows. Ensures forms follow JSON Schema standards, integrate with Angular reactive forms, support internationalization, and maintain consistent validation patterns across the application.
الانتقال إلى التثبيت سوق المهارات اكتشف واستكشف مهارات الذكاء الاصطناعي التي بناها المجتمع.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
نسخ Promptعرض تفاصيل Prompt يتجاوز الأمر المباشر Prompt المخصّص للمراجعة. افحص المصدر قبل تشغيله.
npx skills add https://github.com/aiskillstore/marketplace --skill delon-form-dynamic-schema-formsيبقى الأمر في سطر واحد. مرّر أفقيًا لمراجعته كاملًا قبل النسخ.
تفضّل نسخة محلية؟ نزّل الملفات المتاحة حاليًا لدى SkillsMP.
تحميل Zip جاري التحميل... المهن ذات الصلة SOC
استنادا إلى تصنيف SOC المهني
name delon-form-dynamic-schema-forms description Create dynamic schema-based forms using @delon/form (SF component). Use this skill when building complex forms with validation, conditional rendering, async data loading, custom widgets, and multi-step workflows. Ensures forms follow JSON Schema standards, integrate with Angular reactive forms, support internationalization, and maintain consistent validation patterns across the application. license MIT
@delon/form Dynamic Schema Forms Skill
This skill helps create dynamic forms using @delon/form's SF (Schema Form) component.
Core Principles
Schema-Driven Forms
JSON Schema : Define forms declaratively with JSON Schema
Type Safety : Full TypeScript support for schema definitions
Validation : Built-in validation with custom validators
Dynamic Rendering : Conditional fields based on form state
Key Features
Automatic form generation from schema
Custom widgets for specialized inputs
Async data loading (dropdowns, autocomplete)
Multi-step forms (wizards)
Responsive grid layouts
Internationalization support
Basic Schema Form
import { Component , signal, output } from '@angular/core' ;
import { SFSchema , SFComponent , } ;
{ } ;
({
: ,
: ,
: [ , ],
:
})
{
loading = ( );
initialData = signal< >({});
formSubmit = output< >();
: = {
: {
: {
: ,
: ,
:
},
: {
: ,
: ,
:
},
: {
: ,
: ,
: ,
:
},
: {
: ,
: ,
: [ , , ],
:
}
},
: [ , , ]
};
: = {
: {
: ,
: ,
: { : }
},
: {
: ,
:
},
: {
: ,
:
},
: {
:
},
: {
: ,
:
}
};
( : ): {
. ( , value);
. . (value);
}
( : ): {
. ( , value);
}
( : ): {
. ( , errors);
}
}
SFUISchema
from
'@delon/form'
import
SHARED_IMPORTS
from
'@shared'
@Component
selector
'app-user-form'
standalone
true
imports
SHARED_IMPORTS
SFComponent
template
`
<sf
[schema]="schema"
[ui]="ui"
[formData]="initialData()"
[loading]="loading()"
(formSubmit)="handleSubmit($event)"
(formChange)="handleChange($event)"
(formError)="handleError($event)"
/>
`
export
class
UserFormComponent
signal
false
any
any
schema
SFSchema
properties
name
type
'string'
title
'Full Name'
maxLength
100
email
type
'string'
title
'Email'
format
'email'
age
type
'number'
title
'Age'
minimum
18
maximum
120
role
type
'string'
title
'Role'
enum
'admin'
'member'
'viewer'
default
'member'
required
'name'
'email'
'role'
ui
SFUISchema
'*'
spanLabel
6
spanControl
18
grid
span
24
$name
placeholder
'Enter full name'
widget
'string'
$email
placeholder
'user@example.com'
widget
'string'
$age
widget
'number'
$role
widget
'select'
placeholder
'Select role'
handleSubmit
value
any
void
console
log
'Form submitted:'
this
formSubmit
emit
handleChange
value
any
void
console
log
'Form changed:'
handleError
errors
any
void
console
error
'Form errors:'
Common Widgets
String Input {
name : {
type : 'string' ,
title : 'Name' ,
ui : {
widget : 'string' ,
placeholder : 'Enter name' ,
prefix : 'User' ,
suffix : '@' ,
maxLength : 100
}
}
}
Textarea {
description : {
type : 'string' ,
title : 'Description' ,
ui : {
widget : 'textarea' ,
autosize : { minRows : 3 , maxRows : 6 },
placeholder : 'Enter description'
}
}
}
Number Input {
amount : {
type : 'number' ,
title : 'Amount' ,
minimum : 0 ,
maximum : 1000000 ,
ui : {
widget : 'number' ,
precision : 2 ,
prefix : '$' ,
formatter : (value : number ) => `$ ${value} ` .replace (/\B(?=(\d{3})+(?!\d))/g , ',' )
}
}
}
Date Picker {
birthDate : {
type : 'string' ,
title : 'Birth Date' ,
format : 'date' ,
ui : {
widget : 'date' ,
mode : 'date' ,
displayFormat : 'yyyy-MM-dd' ,
end : 'today'
}
}
}
Date Range {
dateRange : {
type : 'string' ,
title : 'Date Range' ,
ui : {
widget : 'date' ,
mode : 'range' ,
displayFormat : 'yyyy-MM-dd'
}
}
}
Select Dropdown {
category : {
type : 'string' ,
title : 'Category' ,
enum : [
{ label : 'Technology' , value : 'tech' },
{ label : 'Business' , value : 'business' },
{ label : 'Science' , value : 'science' }
],
ui : {
widget : 'select' ,
placeholder : 'Select category' ,
allowClear : true ,
showSearch : true
}
}
}
Multi-Select {
tags : {
type : 'array' ,
title : 'Tags' ,
items : {
type : 'string' ,
enum : ['angular' , 'react' , 'vue' , 'typescript' ]
},
ui : {
widget : 'select' ,
mode : 'multiple' ,
placeholder : 'Select tags'
}
}
}
Autocomplete {
city : {
type : 'string' ,
title : 'City' ,
ui : {
widget : 'autocomplete' ,
asyncData : () => this .loadCities (),
debounceTime : 300 ,
placeholder : 'Search city'
}
}
}
private async loadCities (): Promise <any []> {
return [
{ label : 'New York' , value : 'ny' },
{ label : 'Los Angeles' , value : 'la' },
{ label : 'Chicago' , value : 'chi' }
];
}
Radio Buttons {
priority : {
type : 'string' ,
title : 'Priority' ,
enum : [
{ label : 'Low' , value : 'low' },
{ label : 'Medium' , value : 'medium' },
{ label : 'High' , value : 'high' }
],
default : 'medium' ,
ui : {
widget : 'radio' ,
styleType : 'button'
}
}
}
Checkbox {
agree : {
type : 'boolean' ,
title : 'Agree to terms' ,
ui : {
widget : 'checkbox'
}
}
}
Switch {
isActive : {
type : 'boolean' ,
title : 'Active Status' ,
ui : {
widget : 'switch' ,
checkedChildren : 'On' ,
unCheckedChildren : 'Off'
}
}
}
Slider {
rating : {
type : 'number' ,
title : 'Rating' ,
minimum : 0 ,
maximum : 100 ,
ui : {
widget : 'slider' ,
marks : {
0 : '0' ,
50 : '50' ,
100 : '100'
}
}
}
}
File Upload {
avatar : {
type : 'string' ,
title : 'Avatar' ,
ui : {
widget : 'upload' ,
action : '/api/upload' ,
accept : 'image/*' ,
limit : 1 ,
listType : 'picture-card'
}
}
}
Async Data Loading
Dynamic Dropdown Options {
assignee : {
type : 'string' ,
title : 'Assignee' ,
ui : {
widget : 'select' ,
asyncData : () => this .loadUsers (),
placeholder : 'Select user'
}
}
}
private async loadUsers (): Promise <any []> {
const users = await this .userService .getUsers ();
return users.map (u => ({
label : u.name ,
value : u.id
}));
}
Cascading Selects {
country : {
type : 'string' ,
title : 'Country' ,
ui : {
widget : 'select' ,
asyncData : () => this .loadCountries (),
change : (value : string ) => this .onCountryChange (value)
}
},
city : {
type : 'string' ,
title : 'City' ,
ui : {
widget : 'select' ,
asyncData : () => this .loadCities (this .selectedCountry ())
}
}
}
private selectedCountry = signal<string >('' );
onCountryChange (value : string ): void {
this .selectedCountry .set (value);
}
Conditional Fields
Show/Hide Based on Value schema : SFSchema = {
properties : {
userType : {
type : 'string' ,
title : 'User Type' ,
enum : ['individual' , 'company' ]
},
companyName : {
type : 'string' ,
title : 'Company Name' ,
ui : {
visibleIf : {
userType : ['company' ]
}
}
},
firstName : {
type : 'string' ,
title : 'First Name' ,
ui : {
visibleIf : {
userType : ['individual' ]
}
}
}
}
};
Custom Validators import { SFSchema } from '@delon/form' ;
schema : SFSchema = {
properties : {
password : {
type : 'string' ,
title : 'Password' ,
ui : {
type : 'password' ,
validator : (value : string , formProperty : any , form : any ) => {
if (value.length < 8 ) {
return [{ keyword : 'minLength' , message : 'Password must be at least 8 characters' }];
}
if (!/[A-Z]/ .test (value)) {
return [{ keyword : 'uppercase' , message : 'Password must contain uppercase letter' }];
}
return [];
}
}
},
confirmPassword : {
type : 'string' ,
title : 'Confirm Password' ,
ui : {
type : 'password' ,
validator : (value : string , formProperty : any , form : any ) => {
if (value !== form.value .password ) {
return [{ keyword : 'match' , message : 'Passwords must match' }];
}
return [];
}
}
}
}
};
Multi-Step Forms (Wizards) import { Component , signal } from '@angular/core' ;
import { SFSchema } from '@delon/form' ;
@Component ({
selector : 'app-wizard-form' ,
template : `
<nz-steps [nzCurrent]="currentStep()">
<nz-step nzTitle="Basic Info" />
<nz-step nzTitle="Address" />
<nz-step nzTitle="Confirmation" />
</nz-steps>
@switch (currentStep()) {
@case (0) {
<sf [schema]="basicInfoSchema" (formSubmit)="nextStep($event)" />
}
@case (1) {
<sf [schema]="addressSchema" (formSubmit)="nextStep($event)" />
}
@case (2) {
<div class="confirmation">
<h3>Review Your Information</h3>
<pre>{{ formData() | json }}</pre>
<button nz-button nzType="primary" (click)="submit()">Submit</button>
</div>
}
}
`
})
export class WizardFormComponent {
currentStep = signal (0 );
formData = signal<any >({});
basicInfoSchema : SFSchema = {
properties : {
name : { type : 'string' , title : 'Name' },
email : { type : 'string' , title : 'Email' , format : 'email' }
},
required : ['name' , 'email' ]
};
addressSchema : SFSchema = {
properties : {
street : { type : 'string' , title : 'Street' },
city : { type : 'string' , title : 'City' },
zipCode : { type : 'string' , title : 'Zip Code' }
},
required : ['street' , 'city' ]
};
nextStep (value : any ): void {
this .formData .update (data => ({ ...data, ...value }));
this .currentStep .update (step => step + 1 );
}
submit (): void {
console .log ('Final data:' , this .formData ());
}
}
Grid Layout ui : SFUISchema = {
'*' : {
spanLabel : 4 ,
spanControl : 20 ,
grid : { span : 12 }
},
$description : {
grid : { span : 24 }
}
};
Responsive Layout ui : SFUISchema = {
'*' : {
grid : {
xs : 24 ,
sm : 12 ,
md : 8 ,
lg : 6
}
}
};
Form Actions @Component ({
template : `
<sf [schema]="schema" [button]="button">
<ng-template sf-template="button" let-btn>
<button
nz-button
[nzType]="btn.submit ? 'primary' : 'default'"
(click)="btn.submit ? handleSubmit() : handleReset()"
>
{{ btn.submit ? 'Submit' : 'Reset' }}
</button>
</ng-template>
</sf>
`
})
export class CustomButtonFormComponent {
button = {
submit_text : 'Submit' ,
reset_text : 'Reset' ,
submit_type : 'primary' as const ,
reset_type : 'default' as const
};
}
Checklist
References