Documentation

@if / @else

Conditionally render components based on state.

Basic Usage

var isLoading = true

@if (isLoading) {
  <CircularProgressIndicator />
} else {
  <Text>Content loaded!</Text>
}

Multiple Conditions

var status: Status = Status.Loading

@if (status == Status.Loading) {
  <CircularProgressIndicator />
} else if (status == Status.Success) {
  <Text color="#10b981">Success!</Text>
} else {
  <Text color="#ef4444">Error</Text>
}

Null Checks

var user: User? = null

@if (user != null) {
  <Text>Welcome, {user.name}!</Text>
} else {
  <Button onClick={() => $navigate("/login")} text="Login" />
}

Complex Expressions

var count = 5
var enabled = true

@if (count > 0 && enabled) {
  <Text>You have {count} items</Text>
} else if (count == 0) {
  <Text>No items</Text>
} else {
  <Text>Feature disabled</Text>
}

Data Loading Pattern

var data: List<Show>? = null
var error: String? = null
var isLoading = true

$onMount {
  launch {
    try {
      data = $fetch("https://api.example.com/shows")
    } catch (e: Exception) {
      error = e.message
    } finally {
      isLoading = false
    }
  }
}

@if (isLoading) {
  <Column align="center">
    <CircularProgressIndicator />
    <Text>Loading...</Text>
  </Column>
} else if (error != null) {
  <Column align="center">
    <Text color="#ef4444">Error: {error}</Text>
    <Button onClick={() => reload()} text="Retry" />
  </Column>
} else if (data != null) {
  <LazyColumn>
    @for (show in data) {
      <ShowCard show={show} />
    }
  </LazyColumn>
}

Feature Flags

@if ($env.FEATURE_DARK_MODE) {
  <Switch bind:checked={darkMode} label="Dark Mode" />
}

@if ($env.DEBUG) {
  <Button onClick={clearCache} text="Clear Cache" />
}

Authentication

@if (Auth.isLoggedIn) {
  <Column>
    <Text>Welcome, {Auth.user.name}!</Text>
    <Button onClick={Auth.logout} text="Logout" />
  </Column>
} else {
  <Column>
    <Text>Please log in</Text>
    <Button onClick={() => $navigate("/login")} text="Login" />
  </Column>
}

Empty States

var items: List<Item> = []

@if (items.isEmpty()) {
  <Column align="center" p={40}>
    <Icon name="inbox" size={64} color="#999" />
    <Text fontSize={20} color="#999">No items yet</Text>
    <Button text="Add Item" onClick={addItem} />
  </Column>
} else {
  <LazyColumn>
    @for (item in items) {
      <ItemCard item={item} />
    }
  </LazyColumn>
}

Nested Conditions

@if (user != null) {
  @if (user.isPremium) {
    <PremiumBadge />
    <Text>Premium features enabled</Text>
  } else {
    <Button text="Upgrade to Premium" />
  }
}

Inline Conditionals

For simple text/values, use ternary operator:

<Text>{count > 0 ? "Items: $count" : "No items"}</Text>
<Icon name={isPlaying ? "pause" : "play"} />
<Text color={status == "success" ? "#10b981" : "#ef4444"}>{status}</Text>

Behind the Scenes

Whitehall transpiles @if to Compose conditional composition:

@if (condition) {
  <ComponentA />
} else {
  <ComponentB />
}

// Becomes:
if (condition) {
  ComponentA()
} else {
  ComponentB()
}

For complex pattern matching with sealed classes, use @when instead.

With Animations

Add transitions to conditionally rendered content:

var showPanel = false

@if (showPanel) {
  <Card in:fade={{ duration: 300 }} out:fade={{ duration: 300 }}>
    <Text>Panel content</Text>
  </Card>
}

Complete Example

var searchQuery = ""
var results: List<Show> = []
var isSearching = false
var error: String? = null

suspend fun search() {
  if (searchQuery.isEmpty()) {
    results = []
    return
  }

  isSearching = true
  error = null
  try {
    results = $fetch("https://api.example.com/search?q=$searchQuery")
  } catch (e: Exception) {
    error = e.message
  } finally {
    isSearching = false
  }
}

<Column p={16} gap={16}>
  <TextField
    bind:value={searchQuery}
    label="Search shows"
    onChange={() => launch { search() }}
  />

  @if (isSearching) {
    <Column align="center">
      <CircularProgressIndicator />
    </Column>
  } else if (error != null) {
    <Text color="#ef4444">Error: {error}</Text>
  } else if (searchQuery.isEmpty()) {
    <Text color="#999">Start typing to search</Text>
  } else if (results.isEmpty()) {
    <Text color="#999">No results found</Text>
  } else {
    <LazyColumn>
      @for (show in results) {
        <ShowCard show={show} />
      }
    </LazyColumn>
  }
</Column>

See Also