Skip to content

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