Appearance
x:switch Directive
The x:switch directive is used to render one of several conditions by selecting from multiple options.
Basic Usage
Syntax
html
<div x:switch="expression">
<div x:switch:case="value1">Content 1</div>
<div x:switch:case="value2">Content 2</div>
<div x:switch:default>Default content</div>
</div>String Values
typescript
@Widget({
selector: '.string-switch',
template: `
<div x:switch="userType">
<div x:switch:case="'admin'">Admin Panel</div>
<div x:switch:case="'user'">User Panel</div>
<div x:switch:case="'guest'">Guest View</div>
<div x:switch:default>Invalid user type</div>
</div>
`
})
export class StringSwitchWidget {
@xproperty()
userType: string = 'user';
}Number Values
typescript
@Widget({
selector: '.number-switch',
template: `
<div x:switch="score">
<div x:switch:case="100">Perfect!</div>
<div x:switch:case="90">Very good</div>
<div x:switch:case="80">Good</div>
<div x:switch:case="70">Average</div>
<div x:switch:default>Invalid score</div>
</div>
`
})
export class NumberSwitchWidget {
@xproperty()
score: number = 90;
}Boolean Values
typescript
@Widget({
selector: '.boolean-switch',
template: `
<div x:switch="isActive">
<div x:switch:case="true">Active State</div>
<div x:switch:case="false">Inactive State</div>
</div>
`
})
export class BooleanSwitchWidget {
@xproperty()
isActive: boolean = true;
}Computed Properties
typescript
@Widget({
selector: '.computed-switch',
template: `
<div x:switch="userStatus">
<div x:switch:case="'premium'">Premium Features</div>
<div x:switch:case="'trial'">Trial Version</div>
<div x:switch:case="'expired'">Expired</div>
<div x:switch:default>Standard User</div>
</div>
`
})
export class ComputedSwitchWidget {
@xproperty()
user = {
isPremium: true,
trialEnded: false,
subscriptionActive: true
};
@xcomputed({ dependencies: ['user.isPremium', 'user.trialEnded', 'user.subscriptionActive'] })
get userStatus(): string {
if (this.user.isPremium && this.user.subscriptionActive) {
return 'premium';
}
if (!this.user.trialEnded) {
return 'trial';
}
if (!this.user.subscriptionActive) {
return 'expired';
}
return 'standard';
}
}HTTP Status Codes
typescript
@Widget({
selector: '.http-status',
template: `
<div x:switch="httpStatus">
<div x:switch:case="200">Request successful</div>
<div x:switch:case="201">Record created</div>
<div x:switch:case="400">Invalid request</div>
<div x:switch:case="401">Unauthorized access</div>
<div x:switch:case="404">Not found</div>
<div x:switch:case="500">Server error</div>
<div x:switch:default>Unknown status code</div>
</div>
`
})
export class HttpStatusWidget {
@xproperty()
httpStatus: number = 200;
}Nested Switch
typescript
@Widget({
selector: '.nested-switch',
template: `
<div x:switch="category">
<div x:switch:case="'electronics'">
<div x:switch="subcategory">
<div x:switch:case="'phone'">Phone Category</div>
<div x:switch:case="'laptop'">Laptop Category</div>
<div x:switch:default>Other Electronics</div>
</div>
</div>
<div x:switch:case="'clothing'">
<div x:switch="subcategory">
<div x:switch:case="'shirt'">Shirt Category</div>
<div x:switch:case="'pants'">Pants Category</div>
<div x:switch:default>Other Clothing</div>
</div>
</div>
<div x:switch:default>Main category not selected</div>
</div>
`
})
export class NestedSwitchWidget {
@xproperty()
category: string = 'electronics';
@xproperty()
subcategory: string = 'phone';
}Dynamic Change
typescript
@Widget({
selector: '.dynamic-switch',
template: `
<div>
<button x:on:click="setStatus('loading')">Loading</button>
<button x:on:click="setStatus('success')">Success</button>
<button x:on:click="setStatus('error')">Error</button>
<div x:switch="currentStatus">
<div x:switch:case="'loading'">
<p>Loading data...</p>
</div>
<div x:switch:case="'success'">
<p>Operation completed successfully!</p>
</div>
<div x:switch:case="'error'">
<p>An error occurred. Please try again.</p>
</div>
</div>
</div>
`
})
export class DynamicSwitchWidget {
@xproperty()
currentStatus: string = 'loading';
setStatus(status: string): void {
this.currentStatus = status;
}
}API State Management
typescript
@Widget({
selector: '.api-state',
template: `
<div>
<button x:on:click="fetchData">Fetch Data</button>
<div x:switch="apiState">
<div x:switch:case="'idle'">
<p>Click the button to fetch data</p>
</div>
<div x:switch:case="'loading'">
<p>Loading data...</p>
</div>
<div x:switch:case="'success'">
<p>Data loaded successfully</p>
<div x:text="responseData"></div>
</div>
<div x:switch:case="'error'">
<p class="error">Error: <span x:text="errorMessage"></span></p>
<button x:on:click="fetchData">Retry</button>
</div>
</div>
</div>
`
})
export class ApiStateWidget {
@xproperty()
apiState: 'idle' | 'loading' | 'success' | 'error' = 'idle';
@xproperty()
responseData: string = '';
@xproperty()
errorMessage: string = '';
async fetchData(): Promise<void> {
this.apiState = 'loading';
try {
await new Promise(resolve => setTimeout(resolve, 1000));
this.responseData = 'API data received successfully';
this.apiState = 'success';
} catch (error) {
this.errorMessage = 'Failed to fetch data';
this.apiState = 'error';
}
}
}Form Step Navigation
typescript
@Widget({
selector: '.form-steps',
template: `
<div>
<div x:switch="currentStep">
<div x:switch:case="1">
<h3>Step 1: Personal Information</h3>
<input x:model="personalInfo.name" placeholder="Name">
<input x:model="personalInfo.email" placeholder="Email">
<button x:on:click="nextStep">Next</button>
</div>
<div x:switch:case="2">
<h3>Step 2: Address Information</h3>
<input x:model="address.city" placeholder="City">
<input x:model="address.street" placeholder="Street">
<button x:on:click="prevStep">Back</button>
<button x:on:click="nextStep">Next</button>
</div>
<div x:switch:case="3">
<h3>Step 3: Confirmation</h3>
<p>Review your information</p>
<button x:on:click="prevStep">Back</button>
<button x:on:click="submit">Submit</button>
</div>
</div>
</div>
`
})
export class FormStepsWidget {
@xproperty()
currentStep: number = 1;
@xproperty()
personalInfo = { name: '', email: '' };
@xproperty()
address = { city: '', street: '' };
nextStep(): void {
if (this.currentStep < 3) {
this.currentStep++;
}
}
prevStep(): void {
if (this.currentStep > 1) {
this.currentStep--;
}
}
submit(): void {
console.log('Submitting form:', {
personalInfo: this.personalInfo,
address: this.address
});
}
}Summary
- Multiple conditions: Selection between multiple states
- Case matching: String, number, boolean values
- Default: Fallback for unmatched cases
- Nested switch: Nested switch structures
- Dynamic: Automatic update when property changes
- State management: API states, form steps
- Type-safe: Type safety with TypeScript