---
title: Setting Constant Values
editUrl: https://github.com/Cratis/Chronicle/edit/main/Documentation/projections/model-bound/set-value.mdx
description: The SetValue attribute sets a property to a compile-time constant whenever an event of a specified type occurs. Use it when a property should take a fixed…
---

import { Tabs, TabItem } from '@astrojs/starlight/components';

The `SetValue` attribute sets a property to a compile-time constant whenever an event of a specified type occurs. Use it when a property should take a fixed value in response to an event — for example, setting a status flag, assigning a default category, or recording a fixed version number.

## Basic Usage

<Tabs syncKey="chronicle-client">
<TabItem label="C#">

```csharp
using Cratis.Chronicle.Events;
using Cratis.Chronicle.Keys;
using Cratis.Chronicle.Projections.ModelBound;

[EventType]
public record MbSetValueOrderPlaced(string CustomerName);

[EventType]
public record MbSetValueOrderCanceled;

public record MbSetValueOrder(
    [Key]
    Guid Id,

    [SetFrom<MbSetValueOrderPlaced>(nameof(MbSetValueOrderPlaced.CustomerName))]
    string CustomerName,

    [SetValue<MbSetValueOrderPlaced>("active")]
    [SetValue<MbSetValueOrderCanceled>("canceled")]
    string Status);
```

[View C# snippet source on GitHub](https://github.com/Cratis/Chronicle/blob/main/Documentation/client-snippets/projections/model-bound/set-value/order.md)

</TabItem>
<TabItem label="Kotlin">

```kotlin
import io.cratis.chronicle.events.EventType
import io.cratis.chronicle.projections.FromEvent
import io.cratis.chronicle.projections.SetFrom
import io.cratis.chronicle.projections.SetValue
import io.cratis.chronicle.readModels.ReadModel

@EventType
data class MbSetValueOrderPlaced(val customerName: String)

@EventType
data class MbSetValueOrderCanceled(val placeholder: Boolean = true)

@ReadModel
@FromEvent(MbSetValueOrderPlaced::class)
@FromEvent(MbSetValueOrderCanceled::class)
data class MbSetValueOrder(
    @SetFrom("customerName", MbSetValueOrderPlaced::class)
    val customerName: String = "",

    @SetValue(MbSetValueOrderPlaced::class, value = "active")
    @SetValue(MbSetValueOrderCanceled::class, value = "canceled")
    val status: String = ""
)
```

[View Kotlin snippet source on GitHub](https://github.com/Cratis/Chronicle.Kotlin/blob/main/Documentation/client-snippets/projections/model-bound/set-value/order.md)

</TabItem>
<TabItem label="Java">

```java
import io.cratis.chronicle.events.EventType;
import io.cratis.chronicle.projections.FromEvent;
import io.cratis.chronicle.projections.SetFrom;
import io.cratis.chronicle.projections.SetValue;
import io.cratis.chronicle.readModels.ReadModel;

@EventType
record MbSetValueOrderPlaced(String customerName) {}

@EventType
record MbSetValueOrderCanceled() {}

@ReadModel
@FromEvent(eventType = MbSetValueOrderPlaced.class)
@FromEvent(eventType = MbSetValueOrderCanceled.class)
class MbSetValueOrder {
    @SetFrom(propertyPath = "customerName", eventType = MbSetValueOrderPlaced.class)
    public String customerName = "";

    @SetValue(eventType = MbSetValueOrderPlaced.class, value = "active")
    @SetValue(eventType = MbSetValueOrderCanceled.class, value = "canceled")
    public String status = "";
}
```

[View Java snippet source on GitHub](https://github.com/Cratis/Chronicle.Kotlin/blob/main/Documentation/client-snippets-java/projections/model-bound/set-value/order.md)

</TabItem>
<TabItem label="Elixir">

```elixir
defmodule MyApp.Events.SetValueOrderPlaced do
  use Chronicle.Events.EventType, id: "set-value-order-placed-v1"

  defstruct [:customer_name]
end

defmodule MyApp.Events.SetValueOrderCanceled do
  use Chronicle.Events.EventType, id: "set-value-order-canceled-v1"

  defstruct []
end

defmodule MyApp.ReadModels.SetValueOrder do
  use Chronicle.ReadModels.ReadModel

  alias MyApp.Events.{SetValueOrderPlaced, SetValueOrderCanceled}

  defstruct [:id, :customer_name, :status]

  # A `$value(...)` expression sets a literal constant rather than reading a
  # property off the event.
  from SetValueOrderPlaced,
    set: [id: :event_source_id, customer_name: :customer_name, status: "$value(active)"]

  from SetValueOrderCanceled,
    set: [status: "$value(canceled)"]
end
```

[View Elixir snippet source on GitHub](https://github.com/Cratis/Chronicle.Elixir/blob/main/Documentation/client-snippets/projections/model-bound/set-value/order.md)

</TabItem>
<TabItem label="TypeScript">

```typescript
import { eventType, fromEvent, Guid, setFrom, setValue } from '@cratis/chronicle';

@eventType()
export class MbSetValueOrderPlaced {
    customerName = '';
}

@eventType()
export class MbSetValueOrderCanceled {
}

@fromEvent(MbSetValueOrderPlaced)
@fromEvent(MbSetValueOrderCanceled)
export class MbSetValueOrder {
    id: Guid = Guid.empty;

    @setFrom(MbSetValueOrderPlaced, 'customerName')
    customerName = '';

    @setValue(MbSetValueOrderPlaced, 'active')
    @setValue(MbSetValueOrderCanceled, 'canceled')
    status = '';
}
```

[View TypeScript snippet source on GitHub](https://github.com/Cratis/Chronicle.TypeScript/blob/main/Documentation/client-snippets/projections/model-bound/set-value/order.md)

</TabItem>
</Tabs>

When an `OrderPlaced` event occurs, `Status` is set to `"active"`. When an `OrderCanceled` event occurs, `Status` is set to `"canceled"`.

## Supported Value Types

`SetValue` accepts any compile-time constant: strings, integers, longs, doubles, booleans, and enum values.

<Tabs syncKey="chronicle-client">
<TabItem label="C#">

```csharp
[EventType]
public record MbSetValueThingHappened;

public record MbSetValueThing(
    [Key]
    Guid Id,

    [SetValue<MbSetValueThingHappened>("pending")]
    string StatusLabel,

    [SetValue<MbSetValueThingHappened>(42)]
    int Priority,

    [SetValue<MbSetValueThingHappened>(true)]
    bool IsActive,

    [SetValue<MbSetValueThingHappened>(3.14)]
    double Score);
```

[View C# snippet source on GitHub](https://github.com/Cratis/Chronicle/blob/main/Documentation/client-snippets/projections/model-bound/set-value/thing.md)

</TabItem>
<TabItem label="Kotlin">

```kotlin
import io.cratis.chronicle.events.EventType
import io.cratis.chronicle.projections.FromEvent
import io.cratis.chronicle.projections.SetValue
import io.cratis.chronicle.readModels.ReadModel

@EventType
data class MbSetValueThingHappened(val placeholder: Boolean = true)

@ReadModel
@FromEvent(MbSetValueThingHappened::class)
data class MbSetValueThing(
    @SetValue(MbSetValueThingHappened::class, value = "pending")
    val statusLabel: String = "",

    // Kotlin annotation parameters can only be compile-time constants of a fixed set of types, so
    // SetValue always carries its constant as a string - a numeric or boolean value is written out
    // as its literal text and interpreted against the property's declared type.
    @SetValue(MbSetValueThingHappened::class, value = "42")
    val priority: Int = 0,

    @SetValue(MbSetValueThingHappened::class, value = "true")
    val isActive: Boolean = false,

    @SetValue(MbSetValueThingHappened::class, value = "3.14")
    val score: Double = 0.0
)
```

[View Kotlin snippet source on GitHub](https://github.com/Cratis/Chronicle.Kotlin/blob/main/Documentation/client-snippets/projections/model-bound/set-value/thing.md)

</TabItem>
<TabItem label="Java">

```java
import io.cratis.chronicle.events.EventType;
import io.cratis.chronicle.projections.FromEvent;
import io.cratis.chronicle.projections.SetValue;
import io.cratis.chronicle.readModels.ReadModel;

@EventType
record MbSetValueThingHappened() {}

@ReadModel
@FromEvent(eventType = MbSetValueThingHappened.class)
class MbSetValueThing {
    @SetValue(eventType = MbSetValueThingHappened.class, value = "pending")
    public String statusLabel = "";

    // Kotlin annotation parameters can only be compile-time constants of a fixed set of types, so
    // SetValue always carries its constant as a string - a numeric or boolean value is written out
    // as its literal text and interpreted against the field's declared type.
    @SetValue(eventType = MbSetValueThingHappened.class, value = "42")
    public int priority = 0;

    @SetValue(eventType = MbSetValueThingHappened.class, value = "true")
    public boolean isActive = false;

    @SetValue(eventType = MbSetValueThingHappened.class, value = "3.14")
    public double score = 0.0;
}
```

[View Java snippet source on GitHub](https://github.com/Cratis/Chronicle.Kotlin/blob/main/Documentation/client-snippets-java/projections/model-bound/set-value/thing.md)

</TabItem>
<TabItem label="Elixir">

```elixir
defmodule MyApp.Events.SetValueThingHappened do
  use Chronicle.Events.EventType, id: "set-value-thing-happened-v1"

  defstruct []
end

defmodule MyApp.ReadModels.SetValueThing do
  use Chronicle.ReadModels.ReadModel

  alias MyApp.Events.SetValueThingHappened

  defstruct [:id, status_label: "", priority: 0, is_active: false, score: 0.0]

  from SetValueThingHappened,
    set: [
      id: :event_source_id,
      status_label: "$value(pending)",
      priority: 42,
      is_active: true,
      score: "$value(3.14)"
    ]
end
```

[View Elixir snippet source on GitHub](https://github.com/Cratis/Chronicle.Elixir/blob/main/Documentation/client-snippets/projections/model-bound/set-value/thing.md)

</TabItem>
<TabItem label="TypeScript">

```typescript
import { eventType, fromEvent, Guid, setValue } from '@cratis/chronicle';

@eventType()
export class MbSetValueThingHappened {
}

@fromEvent(MbSetValueThingHappened)
export class MbSetValueThing {
    id: Guid = Guid.empty;

    @setValue(MbSetValueThingHappened, 'pending')
    statusLabel = '';

    @setValue(MbSetValueThingHappened, 42)
    priority = 0;

    @setValue(MbSetValueThingHappened, true)
    isActive = false;

    @setValue(MbSetValueThingHappened, 3.14)
    score = 0;
}
```

[View TypeScript snippet source on GitHub](https://github.com/Cratis/Chronicle.TypeScript/blob/main/Documentation/client-snippets/projections/model-bound/set-value/thing.md)

</TabItem>
</Tabs>

## Multiple Events

Apply the attribute more than once to respond to multiple event types:

<Tabs syncKey="chronicle-client">
<TabItem label="C#">

```csharp
[EventType]
public record MbSetValueSubscriptionStarted;

[EventType]
public record MbSetValueSubscriptionPaused;

[EventType]
public record MbSetValueSubscriptionCanceled;

public record MbSetValueSubscription(
    [Key]
    Guid Id,

    [SetValue<MbSetValueSubscriptionStarted>("active")]
    [SetValue<MbSetValueSubscriptionPaused>("paused")]
    [SetValue<MbSetValueSubscriptionCanceled>("canceled")]
    string State);
```

[View C# snippet source on GitHub](https://github.com/Cratis/Chronicle/blob/main/Documentation/client-snippets/projections/model-bound/set-value/subscription.md)

</TabItem>
<TabItem label="Kotlin">

```kotlin
import io.cratis.chronicle.events.EventType
import io.cratis.chronicle.projections.FromEvent
import io.cratis.chronicle.projections.SetValue
import io.cratis.chronicle.readModels.ReadModel

@EventType
data class MbSetValueSubscriptionStarted(val placeholder: Boolean = true)

@EventType
data class MbSetValueSubscriptionPaused(val placeholder: Boolean = true)

@EventType
data class MbSetValueSubscriptionCanceled(val placeholder: Boolean = true)

@ReadModel
@FromEvent(MbSetValueSubscriptionStarted::class)
@FromEvent(MbSetValueSubscriptionPaused::class)
@FromEvent(MbSetValueSubscriptionCanceled::class)
data class MbSetValueSubscription(
    @SetValue(MbSetValueSubscriptionStarted::class, value = "active")
    @SetValue(MbSetValueSubscriptionPaused::class, value = "paused")
    @SetValue(MbSetValueSubscriptionCanceled::class, value = "canceled")
    val state: String = ""
)
```

[View Kotlin snippet source on GitHub](https://github.com/Cratis/Chronicle.Kotlin/blob/main/Documentation/client-snippets/projections/model-bound/set-value/subscription.md)

</TabItem>
<TabItem label="Java">

```java
import io.cratis.chronicle.events.EventType;
import io.cratis.chronicle.projections.FromEvent;
import io.cratis.chronicle.projections.SetValue;
import io.cratis.chronicle.readModels.ReadModel;

@EventType
record MbSetValueSubscriptionStarted() {}

@EventType
record MbSetValueSubscriptionPaused() {}

@EventType
record MbSetValueSubscriptionCanceled() {}

@ReadModel
@FromEvent(eventType = MbSetValueSubscriptionStarted.class)
@FromEvent(eventType = MbSetValueSubscriptionPaused.class)
@FromEvent(eventType = MbSetValueSubscriptionCanceled.class)
class MbSetValueSubscription {
    @SetValue(eventType = MbSetValueSubscriptionStarted.class, value = "active")
    @SetValue(eventType = MbSetValueSubscriptionPaused.class, value = "paused")
    @SetValue(eventType = MbSetValueSubscriptionCanceled.class, value = "canceled")
    public String state = "";
}
```

[View Java snippet source on GitHub](https://github.com/Cratis/Chronicle.Kotlin/blob/main/Documentation/client-snippets-java/projections/model-bound/set-value/subscription.md)

</TabItem>
<TabItem label="Elixir">

```elixir
defmodule MyApp.Events.SetValueSubscriptionStarted do
  use Chronicle.Events.EventType, id: "set-value-subscription-started-v1"

  defstruct []
end

defmodule MyApp.Events.SetValueSubscriptionPaused do
  use Chronicle.Events.EventType, id: "set-value-subscription-paused-v1"

  defstruct []
end

defmodule MyApp.Events.SetValueSubscriptionCanceled do
  use Chronicle.Events.EventType, id: "set-value-subscription-canceled-v1"

  defstruct []
end

defmodule MyApp.ReadModels.SetValueSubscription do
  use Chronicle.ReadModels.ReadModel

  alias MyApp.Events.{
    SetValueSubscriptionStarted,
    SetValueSubscriptionPaused,
    SetValueSubscriptionCanceled
  }

  defstruct [:id, state: ""]

  from SetValueSubscriptionStarted,
    set: [id: :event_source_id, state: "$value(active)"]

  from SetValueSubscriptionPaused,
    set: [state: "$value(paused)"]

  from SetValueSubscriptionCanceled,
    set: [state: "$value(canceled)"]
end
```

[View Elixir snippet source on GitHub](https://github.com/Cratis/Chronicle.Elixir/blob/main/Documentation/client-snippets/projections/model-bound/set-value/subscription.md)

</TabItem>
<TabItem label="TypeScript">

```typescript
import { eventType, fromEvent, Guid, setValue } from '@cratis/chronicle';

@eventType()
export class MbSetValueSubscriptionStarted {
}

@eventType()
export class MbSetValueSubscriptionPaused {
}

@eventType()
export class MbSetValueSubscriptionCanceled {
}

@fromEvent(MbSetValueSubscriptionStarted)
@fromEvent(MbSetValueSubscriptionPaused)
@fromEvent(MbSetValueSubscriptionCanceled)
export class MbSetValueSubscription {
    id: Guid = Guid.empty;

    @setValue(MbSetValueSubscriptionStarted, 'active')
    @setValue(MbSetValueSubscriptionPaused, 'paused')
    @setValue(MbSetValueSubscriptionCanceled, 'canceled')
    state = '';
}
```

[View TypeScript snippet source on GitHub](https://github.com/Cratis/Chronicle.TypeScript/blob/main/Documentation/client-snippets/projections/model-bound/set-value/subscription.md)

</TabItem>
</Tabs>

## Clearing a Value

Passing `null` clears the member instead of setting it — the projection writes it back to no value every time the event occurs. `ClearWith` says the same thing and reads better (as does the fluent `Clear`); all of them are covered in [Clearing Values](/chronicle/projections/model-bound/clearing/).

The member has to be nullable. Clearing a non-nullable member raises [CHR0048](/chronicle/code-analysis/chr0048/) and is refused when the projection is built, because the only value that could be written is the type default, which is a different fact from "not set".

## SetValue vs SetFrom vs ClearWith

| Attribute | Source | When to use |
| --- | --- | --- |
| `SetValue<TEvent>(value)` | Compile-time constant | The value does not come from the event payload |
| `SetFrom<TEvent>(property)` | Event property | The value comes from a property on the event |
| `ClearWith<TEvent>` | No value | The event takes the value away without putting one in its place |

Combine both on the same read model when different properties come from different sources:

<Tabs syncKey="chronicle-client">
<TabItem label="C#">

```csharp
[EventType]
public record MbSetValueInvoiceIssued(decimal Amount);

[EventType]
public record MbSetValueInvoicePaid;

public record MbSetValueInvoice(
    [Key]
    Guid Id,

    [SetFrom<MbSetValueInvoiceIssued>(nameof(MbSetValueInvoiceIssued.Amount))]
    decimal Amount,

    [SetValue<MbSetValueInvoiceIssued>("issued")]
    [SetValue<MbSetValueInvoicePaid>("paid")]
    string Status);
```

[View C# snippet source on GitHub](https://github.com/Cratis/Chronicle/blob/main/Documentation/client-snippets/projections/model-bound/set-value/invoice.md)

</TabItem>
<TabItem label="Kotlin">

```kotlin
import io.cratis.chronicle.events.EventType
import io.cratis.chronicle.projections.FromEvent
import io.cratis.chronicle.projections.SetFrom
import io.cratis.chronicle.projections.SetValue
import io.cratis.chronicle.readModels.ReadModel

@EventType
data class MbSetValueInvoiceIssued(val amount: Double)

@EventType
data class MbSetValueInvoicePaid(val placeholder: Boolean = true)

@ReadModel
@FromEvent(MbSetValueInvoiceIssued::class)
@FromEvent(MbSetValueInvoicePaid::class)
data class MbSetValueInvoice(
    @SetFrom("amount", MbSetValueInvoiceIssued::class)
    val amount: Double = 0.0,

    @SetValue(MbSetValueInvoiceIssued::class, value = "issued")
    @SetValue(MbSetValueInvoicePaid::class, value = "paid")
    val status: String = ""
)
```

[View Kotlin snippet source on GitHub](https://github.com/Cratis/Chronicle.Kotlin/blob/main/Documentation/client-snippets/projections/model-bound/set-value/invoice.md)

</TabItem>
<TabItem label="Java">

```java
import io.cratis.chronicle.events.EventType;
import io.cratis.chronicle.projections.FromEvent;
import io.cratis.chronicle.projections.SetFrom;
import io.cratis.chronicle.projections.SetValue;
import io.cratis.chronicle.readModels.ReadModel;

@EventType
record MbSetValueInvoiceIssued(double amount) {}

@EventType
record MbSetValueInvoicePaid() {}

@ReadModel
@FromEvent(eventType = MbSetValueInvoiceIssued.class)
@FromEvent(eventType = MbSetValueInvoicePaid.class)
class MbSetValueInvoice {
    @SetFrom(propertyPath = "amount", eventType = MbSetValueInvoiceIssued.class)
    public double amount = 0.0;

    @SetValue(eventType = MbSetValueInvoiceIssued.class, value = "issued")
    @SetValue(eventType = MbSetValueInvoicePaid.class, value = "paid")
    public String status = "";
}
```

[View Java snippet source on GitHub](https://github.com/Cratis/Chronicle.Kotlin/blob/main/Documentation/client-snippets-java/projections/model-bound/set-value/invoice.md)

</TabItem>
<TabItem label="Elixir">

```elixir
defmodule MyApp.Events.SetValueInvoiceIssued do
  use Chronicle.Events.EventType, id: "set-value-invoice-issued-v1"

  defstruct [:amount]
end

defmodule MyApp.Events.SetValueInvoicePaid do
  use Chronicle.Events.EventType, id: "set-value-invoice-paid-v1"

  defstruct []
end

defmodule MyApp.ReadModels.SetValueInvoice do
  use Chronicle.ReadModels.ReadModel

  alias MyApp.Events.{SetValueInvoiceIssued, SetValueInvoicePaid}

  defstruct [:id, amount: 0, status: ""]

  from SetValueInvoiceIssued,
    set: [id: :event_source_id, amount: :amount, status: "$value(issued)"]

  from SetValueInvoicePaid,
    set: [status: "$value(paid)"]
end
```

[View Elixir snippet source on GitHub](https://github.com/Cratis/Chronicle.Elixir/blob/main/Documentation/client-snippets/projections/model-bound/set-value/invoice.md)

</TabItem>
<TabItem label="TypeScript">

```typescript
import { eventType, fromEvent, Guid, setFrom, setValue } from '@cratis/chronicle';

@eventType()
export class MbSetValueInvoiceIssued {
    amount = 0;
}

@eventType()
export class MbSetValueInvoicePaid {
}

@fromEvent(MbSetValueInvoiceIssued)
@fromEvent(MbSetValueInvoicePaid)
export class MbSetValueInvoice {
    id: Guid = Guid.empty;

    @setFrom(MbSetValueInvoiceIssued, 'amount')
    amount = 0;

    @setValue(MbSetValueInvoiceIssued, 'issued')
    @setValue(MbSetValueInvoicePaid, 'paid')
    status = '';
}
```

[View TypeScript snippet source on GitHub](https://github.com/Cratis/Chronicle.TypeScript/blob/main/Documentation/client-snippets/projections/model-bound/set-value/invoice.md)

</TabItem>
</Tabs>
