> ## Documentation Index
> Fetch the complete documentation index at: https://platform.docs.zenoo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# State

> Global application state and methods

### Global application state and methods

#### Expressions

Expressions are a simple way to access data from the app runtime, or the response from server.
Data is accessed through an object that is internally known as **Core context** or **Expression context**.
If expression fails, it will return `undefined`. If you specify the default parameter, it will be returned when expression fails.

**Examples of expressions:**

```yaml theme={null}
property: !expression flow.export.value
```

```yaml theme={null}
property:
  !expression eval: flow.export.value
  default: Nothing
```

```yaml theme={null}
# Multiline expression
property:
  !expression: |
    const variable = 1;
    // More lines of JavaScript
    console.log('Hello', variable);
```

#### Functions

A function is another type of expression. It's useful to add some callbacks, such as a button `onClick` event.

```yaml theme={null}
- !component as: div
  onClick: !function "console.log('Click')"
  items: "Click me"
```

#### Extending Expression context

To extend expression context with custom values or methods, `globals` or `utils` configuration keys can be used:

```yaml theme={null}
# index.yml
globals:
  test: "I am a global variable"
utils:
  sum: !expression "function (a, b) { return a + b; }"
```

Then in page configuration:

```yaml theme={null}
- !component as: Heading
  items: !expression "globals.test"
- !component as: Heading
  items: !expression "utils.sum(1, 2)"
```

#### Expression context

Expression context is a global object, which is accessible from YAML expression only.

* **`analytics`** - functions for trigger analytics events

```javascript theme={null}
analytics: {
  authorization: (token) => void, // Trigger mixpanel.identify(token), GA.set({ userId: token }) and GTM dataLayer event "authorization" with parameter token (string)
  event: (name: string, params?: object) => void, // Trigger event with given event name and params
  storage: { // More info in "Analytics storage" section
    set: (name: string, value: any) => void
    get: (name: string) => any
    increment: (name: string) => void
  }
}
```

* **`api`** - information about API

```javascript theme={null}
api: {
  authToken: string,
  progress: {
    [field-name]: number // Percentage of progress in file uploading
  }
}
```

* **`app`** - information about app

```javascript theme={null}
app: {
  locale: string, // Current locale
  targetId: string, // Current target name
  waiting: {
    [tag]: boolean, // App waiting tags
  }
  wrapByLoading: (promise: Promise<any>) => Promise<any>
}
```

**Example usage of `wrapByLoading`**

```yaml theme={null}
# Element with click handler as async operation
- !component as: div
  items: "Run simple async operation"
  onClick: !function "app.wrapByLoading(simple_async_operation, 'SIMPLE_TAG')"

# Element with click handler as async operation with complex structure
- !component as: div
  items: "Run complex async operation"
  onClick: !function |
    app.wrapByLoading((async () => {
      await complex_async_operation();
    })(), 'COMPLEX_TAG')

# Displaying loader during async operation
- !component as: VisibilityWrapper
  visible: !expression "app.waiting.SIMPLE_TAG || app.waiting.COMPLEX_TAG"
  items: "Loading..."
```

* **`configuration`** - complete configuration of your target in json. This is an output from target-builder module, which parses all files inside target folder and produces large JSON that contains all settings, configurations, pages structures, etc.

* **`constants`** - list of constants, the most important ones are: `COUNTRIES_FULL`, `COUNTRIES`, `COUNTRY_CODES`, `LANGUAGES`

* **`cookie`** - methods exported from [`js-cookie`](https://github.com/js-cookie/js-cookie) module (`cookie.get`, `cookie.set`, `cookie.remove`)

* `cx` - method exported from [`classnames`](https://github.com/JedWatson/classnames#usage) module

* `device` - information about device

```javascript theme={null}
device: {
  ... // https://github.com/duskload/react-device-detect#selectors
  hasWebcam: boolean, // If device has webcamera physically
  hasWebcamPermission: boolean, // If user already granted webcamera permission to current website
}
```

* `flow` - data from server about flow and flow/route functions from server

```javascript theme={null}
flow: {
  backEnabled: boolean, // value of backEnabled from API for current page
  execution: { // information about current flow execution
    uuid: string
    token: string
  },
  export: ...any-data-from-server, // this is exported data for page in flow from server
  function: {
    [function-name]: (payload?: any, resultKey?: string) => void, // - call (in !fuction) any flow/route function by call function name (like `flow.function.search('something')`), you can also set output resultKey (default function-name)
    results: {
      [function-name or result-key]: ...any-data-from-server-function, // - here will be data from server under function-name or result-key property name (like `flow.function.results.search`)
    }
  }
  goToErrorPage: (message: string, logout?: boolean) => void // redirect user to error page (if one is specified) with some message put into `page.params.error`. Optionally logout can be performed
  refresh: () => void // refresh workflow based on current workflow status
  reload: () => void // removes authentication cookie and reloads flow
}
```

* `form` - data about form, including states of fields

```javascript theme={null}
form: {
  changeValue: (fieldName: string, value: any, callback?: () => void) => void, // change value of some field, you can use callback that will be called after data set, for example if you need to submit form
  data: {
    [field-name]: ...data-inside-field, // - data can be string, file, etc.
  },
  field: {
    [field-name]: {
      isValid: boolean,           // is field valid
      validationError: string,    // only validation erros generated by page schema
      error: string,              // all field errors including validation errors and server errors
      isFilled: boolean,          // is there any data
      isVisited: boolean,         // true, if field was visited before (focused and blur)
    }
  },
  recompileSchema: () => void, // recompile form validation schema
  clearErrors: (allErrors?: boolean) => void // clear global/validation/manually set errors
  setError: (fieldName: string, error: string) => void // manually set error to some specific field, error can be cleared by passing falsy value
  addTags: (tags: string[]) => void, // add tags to form
  removeTags: (tags: string[]) => void, // regexp as string can be also used to identify more tags
  hasTags: (tags: string | string[]) => boolean // checks if all passed tags are present
  tag: {
    [tag-name]: boolean, // form visual tags
  },
  submit: (actionName: string, params: string[]) => void, // submit form
  valid: boolean, // is form valid
  visited: {
    [field-name]: boolean // indicated if field was visited
  },
}
```

* `format` - global formats used in application

```javascript theme={null}
format: {
  formatDate: (date: string) => string
  formatCurrency: (value: number, options?: NumberFormat) => string
  formatNumber: (value: number, options?: NumberFormat) => string
  roundNumber: (value: number) => number
  dateFormat: string
  currencyUnit: string
  phoneCountryCode: string
  phoneMask: string
}
```

* `globals` - custom constants/variables, see more on how to extend expression context

* `helper` - Helper functions and 3rd party libraries

```javascript theme={null}
helper: {
  dayjs, // https://github.com/iamkun/dayjs
  getFileHolder: (file: File | Blob) => Promise<FileHolder> // Get FileHolder compatible with HUB client
}
```

* `locals` - local page variables and functions

```yaml theme={null}
# page.yml
locals:
  test: "I am a local variable"
  sum: !expression "function (a, b) { return a + b; }"
items:
- !component as: Heading
  items: !expression "globals.test"
- !component as: Heading
  items: !expression "globals.sum(1, 2)"
```

* `page` - parameters of page, which may be an error. This data is set only from the local application, not the server

```javascript theme={null}
page: {
  params: any // for example page.params.error contains informations, why you are on error page
  name: string // current page name (route URI)
  storage: { // local page storage, gets cleared on page change
    get: (name: string, defaultValue?: any) => any
    set: (name: string, value: any) => void
  }
}
```

* `translates` - function to translate a string of text, change current locale

```javascript theme={null}
changeLocale: (locale: string) => void
t: (string, params) => string
te: (string, params) => string
```

* `url` - information about locations, query params, etc.

```javascript theme={null}
url: {
  ... // - https://github.com/unshiftio/url-parse
}
```

* `utils` - custom methods, see more on how to extend expression context
