# Cluster

A Cluster is just a wrapper, a group, of two or more ActiveJS fundamental constructs, [Units](https://docs.activejs.dev/activejs/fundamentals/units), [Systems](https://docs.activejs.dev/activejs/fundamentals/systems), [Actions](https://docs.activejs.dev/activejs/fundamentals/action), or even [Clusters](https://docs.activejs.dev/activejs/fundamentals/cluster).

It creates a master Observable of the combined value of its members by merging all the provided Observable constructs. Whenever any of these wrapped constructs emits a value, Cluster emits a new combined-value.

It also provides direct access to the wrapped constructs through `items` property.\
The ideal use case would be when you need access to the combined value of some ActiveJS constructs as an Observable.

Basically,

* It creates a master Observable of the combined -value of provided members.
* Provides access to its members through the Cluster.
* Provides static access to the combined-value.

See [API reference](https://api.activejs.dev/classes/cluster) for more details.

### Initializing a Cluster:

```typescript
// a ListUnit that saves user's liked things
const userLikesUnit = new ListUnit();

// a DictUnit that saves user's preferences as key:value pairs
const userPreferencesUnit = new DictUnit({initialValue: {humor: 'dark'}});

// create a Cluster to group the above Units together
const userDataCluster = new Cluster({
    userLikesUnit, // using shorthand notation
    userPreferencesUnit
});
```

### Accessing the value:

```typescript
// subscribe for the combined-value
userDataCluster.subscribe(value => console.log(value))

// or access it directly
console.log(userDataCluster.value())

// both of these will log the following
{
    userLikesUnit: [],
    userPreferencesUnit: {humor: 'dark'}
}
```

### Accessing the members through Cluster:

Cluster members can be accessed through the `items` property.

```typescript
console.log(userDataCluster.items.userPreferencesUnit.value());
// logs {humor: 'dark'}

console.log(userDataCluster.items.userLikesUnit.value());
// logs []
```

### **Value propagation:**

Whenever a member of the Cluster emits a value, the Cluster will emit a new combined value.

```typescript
// set a preference to the userPreferencesUnit
userPreferencesUnit.set('favouriteMovie', 'Matrix');

// the Cluster will emit the following value
{
    userLikesUnit: [],
    userPreferencesUnit: {humor: 'dark', favouriteMovie: 'Matrix'}
}



// add some liked things to the userLikesUnit
userLikesUnit.push({id: 42, label: 'puppy'}, {id: 66, label: 'kitten'});

// the Cluster will emit the following value
{
    userLikesUnit: [{id: 42, label: 'puppy'}, {id: 66, label: 'kitten'}],
    userPreferencesUnit: {humor: 'dark', favouriteMovie: 'Matrix'}
}

```

Similarly, we can group any number of Units, Systems, Actions or even Clusters together.

## Notes

* Try to refrain from using the static value accessor `value()` method when the Cluster contains immutable Units because when calling the `value()` method of a Cluster, it internally calls its members' `value()` method, and if members are Immutable Units, those Units would create a clone on every call. It's not a bad thing if used intentionally, but it can add extra overhead if used too often.

## Configuration Options

The configuration options can be passed at the time of instantiation. All the configuration options are optional. Some options can also be set globally. See [Configuration](https://docs.activejs.dev/activejs/guides/configuration) for more details.
