# UI Builder

## Windows

In Anacleto each window is represented by a json object, this object contains all the info needed to render the entire window.

Below is an example

```json
{
  "id": "home",
  "windowName": "Home",
  "component": "GridContainer",
  "components": [
    {
      "id": "home_sample_form",
      "component": "Form",
      "isCard": true,
      "toggleable": false,
      "title": "Welcome form",
      "containerClassName": "col-12 md:col-6",
      "className": "mt-0 md:mt-4",
      "components": [
        {
          "component": "Label",
          "className": "col-12 font-bold text-3xl",
          "id": "title",
          "label": "ANACLETO_SAMPLE"
        },
        {
          "component": "Label",
          "className": "col-12 mt-3",
          "id": "subtitle",
          "label": "Thank you for installing Anacleto Builder! 🦉"
        },
        {
          "component": "Label",
          "className": "col-12 mt-3",
          "id": "subtitle-2",
          "label": "This is an example window created using Anacleto, use the Builder to customize it and start building your application."
        },
        {
          "component": "Button",
          "containerClassName": "col-auto mt-5",
          "className": "col-12 md:col-6",
          "id": "btnBuilder",
          "label": "Go to Builder 👷‍♂️",
          "events": {
            "onClick": {
              "body": "window.open('/admin', '_blank').focus();"
            }
          }
        },
        {
          "component": "Label",
          "className": "col-12 mt-5",
          "id": "subtitle-3",
          "label": "If you have any questions check out the Docs or contact us on GitHub. 🧐"
        },
        {
          "component": "Button",
          "containerClassName": "col-12 md:col-6 mt-5",
          "className": "col-12",
          "id": "btnDocs",
          "label": "Docs 📖",
          "events": {
            "onClick": {
              "body": "window.open('https://github.com/anacletobuilder/anacleto.wiki.git', '_blank').focus();"
            }
          }
        },
        {
          "component": "Button",
          "containerClassName": "col-12 md:col-6 mt-5",
          "className": "col-12",
          "id": "btnGit",
          "label": "GitHub 🗂",
          "events": {
            "onClick": {
              "body": "window.open('https://github.com/anacletobuilder/anacleto', '_blank').focus();"
            }
          }
        }
      ]
    },
    {
      "id": "home_sample_grid",
      "component": "DataTable",
      "store": "sample_store",
      "emptyMessage": "No owls",
      "isCard": true,
      "toggleable": false,
      "title": "Owls",
      "containerClassName": "col-12 md:col-6",
      "className": "mt-0 md:mt-4",
      "sortable": true,
      "stripedRows": true,
      "skeletonRow": 5,
      "paginator": true,
      "paginationType": "client",
      "globalFilterMode": "client",
      "globalFilterFields": ["name", "scientificName", "type"],
      "columns": [
        {
          "field": "name",
          "header": "Name",
          "sortable": true
        },
        {
          "field": "scientificName",
          "header": "Scientific Name",
          "sortable": true
        },
        {
          "field": "type",
          "header": "Owl type",
          "sortable": true,
          "pugTemplate": "return `div.flex.flex-row\n\tspan.flex-shrink-0.p-tag.surface-300\n\t\tspan.text-600.flex-shrink-0 ${data['type']}`;"
        },
        {
          "field": "dangerOfExtinction",
          "header": "Danger of extinction",
          "sortable": true,
          "pugTemplate": "let emoj = '😊';\nif(data['dangerOfExtinction']===1){emoj='😨'}\nif(data['dangerOfExtinction']===2){emoj='😱'}\nreturn `span ${emoj}`"
        }
      ],
      "events": {
        "onSelectionChange": {
          "parameters": "event",
          "body": "if(event.value){ alert(`${event.value.name} is so cute!`) } ;"
        },
        "afterRender": {
          "body": "this.load();"
        }
      }
    }
  ]
}
```

It is essential for each component to specify the `id` attribute, this will allow us to interact with the control via Javascript.

For example, suppose we want to change the label of the `title` input field inside the `home_sample_form` panel, what we need to do is:

```javascript
this.panelsContext.home_sample_form.setRecord({})
```

{% hint style="warning" %}
The id of an component is NOT the id of the html tag
{% endhint %}

### Avoid DOM manipulation with Javascript

{% hint style="danger" %}
**NEVER** use js functions such as: `document.getElementById` or `document. querySelector` to modify a window.
{% endhint %}

Anacleto was developed in React and to use its full potential we must forget the existence of these methods, in React every graphic control is linked to states and to modify it you have to act on these states.

### Layout

When creating a window you can choose between 2 types of layouts, using the `layout` property

* **grid**
* **flex**

If no property is specified, the default `grid` will be used.

#### Grid layout

```json
"layout" : "grid"
```

When using the grid layout Anacleto is completely autonomous in arranging the panels within a window, the only thing you need to do is give the panels a weight **from 1 to 12**.

{% hint style="info" %}
If a weight is not specified by default the value is 12.
{% endhint %}

The weight of a panel must be specified through the `className` property using the appropriate classes `col-1`, `col-2` ... `col-12`.

If you decide to use `col` without specifying a weight, the columns will be evenly distributed.

If you want to give a column a specific dimension use `col-fixed` and specify the desired dimension in the style.

You can define a different weight for different screens, to do this use the prefixes:

* **sm**
* **md**
* **lg**
* **xl**

Imagine the screen divided into 12 columns, in the code below the panel width will default to 12 (the full screen width). On medium sized screens the panel will occupy 8 columns (2/3 of the screen), while on large (or very large) large screens the panel will occupy 6 columns of 12 (ie half the screen).

```json
"className" : "col-12 md:col-8 lg:col-6"
```

You can use `classNames` to add the other panel class, for example `col-offset-1..col-offset-12` classes allow you to define the left margin, useful if you want to add spaces or center a panel.

{% hint style="info" %}
You can combine multiple grid layouts to create more complex layouts, an example is below.
{% endhint %}

```json
{
    "window": "home",
    "layout":"grid",
    "components": [

        {
            "id": "panel_0",
            "component": "Gridcontainer",
            "classNames" : "col-8",
            "title": "Col 8",
            "isCard": true,
            "components": [
                {
                    "id": "panel_1",
                    "component": "Form",
                    "classNames" : "col-6",
                    "title": "Col 6",
                    "isCard": true,
                    "components": [
                        {
                            "id": "button1",
                            "type": "Button",
                            "classNames" : "col-12",
                            "label": "Button 1"
                        }
                    ]
                },
                {
                    "id": "panel_2",
                    "type": "form",
                    "classNames" : "col-6",
                    "title": "Col 6",
                    "isCard": true,
                    "components": [
                        {
                            "id": "button1",
                            "component": "Button",
                            "classNames" : "col-12",
                            "label": "Button 1"
                        }
                    ]
                },
                {
                    "id": "panel_3",
                    "component": "Form",
                    "classNames" : "col-12",
                    "title": "Col 12",
                    "isCard": true,
                    "components": [
                        {
                            "id": "button1",
                            "type": "button",
                            "classNames" : "col-12"
                            "label": "Button 1"
                        }
                    ]
                }
            ]
        },
        {
            "id": "panel-4",
            "component": "Form",
            "title": "Col-4",
            "classNames" : "col-4",
            "isCard": true,
            "components": [
                {
                    "id": "button1",
                    "type": "button",
                    "classNames" : "col-12",
                    "label": "Button 1"
                }
            ]
        }
    ]
}
```

![neted grid](/files/qH9sVgo6qK2D55iezRm5)

#### Flex system

```json
"layout" : "flex"
```

Flex, flex and more flex...if you don't know what we're talking use Google 😊 below some tutorial:

* [Docs](https://css-tricks.com/snippets/css/a-guide-to-flexbox/)
* [Video](https://www.youtube.com/watch?v=IDDK6sX003Q)
* [Video 2](https://www.youtube.com/watch?v=M1yD8GVpLnQ)

If you want to be free to draw a window as you like, set the window attribute `layout=flex`, from now on you will be free to position the panels as you wish using the classNames property

When you use the `flex` layout, Anacleto di provides some classes that can help you.

* `flex-row` set `flex-direction: row;`
* `flex-row-reverse` set `flex-direction: row-reverse;`
* `flex-column` set `flex-direction: column;`
* `flex-column-reverse` set `flex-direction: column-reverse;`
* `flex-wrap` set `flex-wrap: wrap;`
* `flex-wrap-reverse` set `flex-wrap: wrap-reverse;`
* `flex-nowrap` set `flex-wrap: nowrap;`
* `flex-auto` set `flex: 1 1 auto;`
* `flex-1` set `flex: 1 1 0% !important;` useful when you want to give weight 1 to a panel (if you put 3 panels with flex 1 all 3 will be the same width)
* `flex-2` set `flex: 2 2 0% !important;` useful when you want to give weight 2 to a panel (it will always be twice as wide as a panel with flex 1)
* `flex-grow-0` set `flex-grow: 0;`
* `flex-grow-1` set `flex-grow: 1`
* `flex-shrink-0` set `flex-shrink: 0;`
* `flex-shrink-1` set `flex-shrink: 1;`

{% hint style="info" %}
All these classes support sm, md, lg, xl use them to create proper responsive applications
{% endhint %}

### Gap

In the responsive DO NOT use margins and padding, use the gap

* `gap-0` set `gap: 0;`
* `gap-1` set `gap: 0.25rem;`
* `gap-2` set `gap: 0.5rem;`
* `gap-3` set `gap: 1rem;`
* `gap-4` set `gap: 1.5rem;`
* `gap-5` set `gap: 2rem;`
* `gap-6` set `gap: 3rem;`
* `gap-7` set `gap: 4rem;`
* `gap-8` set `gap: 5rem;`
* `row-gap-0` set `row-gap: 0;`
* `row-gap-1` set `row-gap: 0.25rem;`
* `row-gap-2` set `row-gap: 0.5rem;`
* `row-gap-3` set `row-gap: 1rem;`
* `row-gap-4` set `row-gap: 1.5rem;`
* `row-gap-5` set `row-gap: 2rem;`
* `row-gap-6` set `row-gap: 3rem;`
* `row-gap-7` set `row-gap: 4rem;`
* `row-gap-8` set `row-gap: 5rem;`
* `column-gap-0` set `column-gap: 0;`
* `column-gap-1` set `column-gap: 0.25rem;`
* `column-gap-2` set `column-gap: 0.5rem;`
* `column-gap-3` set `column-gap: 1rem;`
* `column-gap-4` set `column-gap: 1.5rem;`
* `column-gap-5` set `column-gap: 2rem;`
* `column-gap-6` set `column-gap: 3rem;`
* `column-gap-7` set `column-gap: 4rem;`
* `column-gap-8` set `column-gap: 5rem;`

## Prime flex

Anacleto is based on PrimeFlex, at this link you can find many other useful classes [PrimeFlex](https://www.primefaces.org/primeflex/flexdirection)

## Style

For each panel (or control) you can use the style property to define in-line styles. Use it with caution, in general it's always better to define a class!

Es:

```json
style: {
    "gap": "1rem"
}
```

## Translations

Anacleto allows you to translate your application and will use the browser language to show the correct translation.

[Docs](broken://pages/aKF9dkAjQMh2KqAqiTG5)

## Components

In an Anacleto window you can insert different types of component

[Components](/anacleto/anacleto-frontend/ui-builder/components.md)


---

# 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://anacleto.gitbook.io/anacleto/anacleto-frontend/ui-builder.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.
