# SelectorFor

### Single Field Selector

`SelectorFor` allows to select specific fields in a object and trigger a callback when those fields change (by reference or by value).&#x20;

`SelectorFor` is used together with [BlocSelector](blocselector) , to choose the data from a [Bloc ](../bloc-and-cubit-overview/bloc)state that we want to use as state that should trigger recomposition.

More precisely, with `SelectorFor` we can build an `AbstractSelector` object that we can pass as argument to `BlocSelector`. Let's see some examples on how this is done.

Let us assume that the state object from which we want to select data is the following:

```kotlin
class StateABC(val a:Int, val b:Int, val c:Int)
```

For example if we are interested in the `a` field, we can write:

```kotlin
//sel_a is of type AbstractSelector<StateABC>
val sel_a = SelectorFor<StateABC>.withSingleField { a }
```

### Selector for Multiple Fields

With a selector we can also check for changes of multiple fields in an object and combine them in a computed value:

```kotlin
//sel_sum_ab is of type AbstractSelector<StateABC>
val sel_sum_ab =
 SelectorFor<StateABC>
    .withField{a}
    .withField{b}
    .compute {a,b -> a+b}
```

`sel_sum_ab` will keep track when the class field `a` and `b` change and automatically recompute their sum and trigger a state change with the value of the sum.

### Equality Check by Reference or by Value

Let's say now that we the following state object:

```kotlin
data class StateABCStrings(val astr:String="", val bstr:String="", val cstr:String="")
```

Again, if we are interested in the `a` field, we can write

```kotlin
//sel_astr  is of type AbstractSelector<StateABCStrings>
val sel_astr = SelectorFor<StateABCStrings>.withSingleField { astr }
```

But what happens when the state change? The selector `sel_astr` we have built is able to identify changes to the `astr` field. By default changes are checked _**by reference .**_ In other words if we have the two states:

```kotlin
val state1 = StateABCStrings(astr="aa")
val state2 = StateAbcStrings.copy(astr="a"+a")
```

the two states `state1` and `state2` are considered different by the selector `sel_astr` . This is not always the desired behaviour. Sometimes we want to check if the "value", not the "reference" of a field has changed. If this is what we want then we must use `withSingleFieldByValue`

```kotlin
//sel_astr_by_val  is of type AbstractSelector<StateABCStrings>
val sel_astr_by_val = SelectorFor<StateABCStrings>.withSingleFieldByValue { astr }
```

With this definition of the selector `state1` and `state2` above will be considered equal and will not considered a state change.

We can choose equality check by value also for selectors based on multiple fields:

```kotlin
//sel_sum_ab_str  is of type AbstractSelector<StateABCStrings>
val sel_sum_ab_str =
 SelectorFor<StateABCStrings>
    .withFieldByValue{ astr }
    .withFieldByValue{ bstr }
    .compute {astr, bstr  -> astr+bstr }
```

### Building multiple selectors for the same state

`SelectorFor` is can be used to build multiple `AbstractSelector`  _**at once**,_ as we can see in the following example:

```kotlin
val sel = SelectorFor<StateABC>

val sel_a = sel.withSingleField { a } //this is an AbstractSelector<StateABC>
val sel_b = sel.withSingleField { b } //this is an AbstractSelector<StateABC>
val sel_for_a = sel.withField { a } //this is still a BUILDER for an AbstractSelector
val sel_sum_ab = sel_for_a.withField { b }.compute {a,b->a+b} //this is an AbstractSelector<StateABC>
val sel_sum_ac = sel_for_a.withField { c }.compute {a,c->a+c}  //this is an AbstractSelector<StateABC>
```
