# Store by decorators

### State

First of all, let\`s create a State. For example, we have some items which we want to display in a window by pages.

```typescript
interface PagingModel {
    pages: number;
    currentPage: number;
    total: number;
}

type State = {
    items: Item[];
    pageSize: number;
    itemsOnDisplay: Item[];
    paging: PagingModel;
}

const InitState: State = {
    items: [],
    pageSize: 5,
    itemsOnDisplay: [],
    paging: {
        pages: 0,
        currentPage: 0,
        total: 0,
    }
}


```

After that we can design our Event Scheme. Let\`s begin from Event Scope - which Events do we need?

```typescript
enum Events {
    LoadItems = 'LoadItems',
    ItemsLoaded = 'ItemsLoaded',
    PageChanged = 'PageChanged',
}
```

It is not nessesary to use Enum, but it is good practice to keep strings in constants of enums to easily modify them. Now, prepare your handers.

### Handlers

If we want to use decorators, for binding store and events we should create Store class that extends ProtoStore class and then, using decorators, describe its methods as handlers

To shorten our event-handlers list I use a `writeAs` option and pass an output-event key. It creates simple reducer under the cover and save our time.

Also, I use an order option that allows me to control by which order handlers would apply.&#x20;

```typescript

class Store extends ProtoStore<State> {
    constructor() {
        super(InitState, {}, DefaultStoreOptions);
    }

    @Action(Events.LoadItems, {
        writeAs: 'items',
    }, Events.ItemsLoaded)
    loadItems() {
        return new FoxEvent(Events.ItemsLoaded, someService.loadItems());
    }

    @Reducer(Events.ItemsLoaded, { order: 1 })
    setPagingModel(
        items: Item[],
        state: State,
    ): Partial<State> {
        return {
            paging: {
                pages: Math.round(items.length / state.pageSize),
                currentPage: 1,
                total: items.length,
            },
        }
    }

    @Reducer(Events.ItemsLoaded, { order: 2 })
    private setDisplayingItems(
        items: Item[],
        state: State,
    ): Partial<State> {
        return {
            itemsOnDisplay: (items || state.items).slice(
                state.paging?.currentPage * state.pageSize - 1,
                state.pageSize,
            ),
        };
    }

    @Action(Events.UpdatePage, {
        writeAs: 'paging',
    }, Events.PagingChanged)
    changePage(page: number, state: State): FoxEvent<PagingModel | string> {
        return state.paging.pages >= page
            ? new FoxEvent(Events.PagingChanged, {
                ...state.paging,
                currentPage: page,
            })
            : new FoxEvent('Error', 'Page number is not correct');
    }

    @Reducer(Events.PagingChanged)
    updateDisplayItemsOnPageChange(paging: PagingModel, state: State) {
        return this.setDisplayingItems(state.items, {
            ...state,
            paging,
        })
    }
}
```

So, here we have no type checking, cause decorators can not collect data about types using Reflect. But this way is more familiar for Angular-users, OOP-adepts and someone who likes big classes.  Of course, we can't separate class for parts that's why you should be ready to growing up your Store-file. You can move some logic to helpers and organize code as you wish to optimise it.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://angkira.gitbook.io/foxstore/using-store/store-by-decorators.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
