# Arguments

Use arguments to pass data to methods.

## Argument Types

This table shows the syntax for declaring a non-literal argument with a name and type. Instead of using a combination of name and type, it's also possible to use a hardcoded (literal) value for an argument of these types.

|                           | Name/type (non literal)                         | Value/type (literal)                                      |
| ------------------------- | ----------------------------------------------- | --------------------------------------------------------- |
| **string primitive**      | `{ "name": "myArg", "type": "string" }`         | `{ "value": "myString" }`                                 |
| **integer primitive**     | `{ "name": "myArg", "type": "number" }`         | `{ "value": 1024 }`                                       |
| **boolean primitive**     | `{ "name": "myArg", "type": "boolean" }`        | `{ "value": false }`                                      |
| **locator**               | `{ "name": "myArg", "type": "locator" }`        | `{ "value": { "css": ".myClass" }, "type": "locator" }`   |
| **element reference**     | not supported                                   | `{ "type": "elementReference", "value": "myElement" }`    |
| **page object type**      | `{ "name": "myArg", "type": "pageObject" }`     | `{ "value": "my/page/object", "type": "pageObject" }`     |
| **root page object type** | `{ "name": "myArg", "type": "rootPageObject" }` | `{ "value": "my/page/object", "type": "rootPageObject" }` |
| **frame element**         | `{ "name": "myArg", "type": "frame" }`          | same as element reference                                 |
| **function**              | not supported                                   | `{ "type": "function", "predicate": [...] }`              |

## Argument Reference

To access an argument passed to a compose method in multiple statements, declare a reusable argument at the method level. The `args` property must be a sibling of the `name` property.
For example, we declare a reusable `passwordStr` argument at the method level:

```json
{
  "name": "passwordStr",
  "type": "string"
}
```

Then in each compose statement where you want to access the reusable argument, set the argument's `type` to `argumentReference`, the `name` of an argument with `"type": "argumentReference"` must match the name of one of the reusable arguments declared at the method level:

```json
{
  "name": "passwordStr",
  "type": "argumentReference"
}
```

Here's the full method declaration. The statements that apply actions to the `password` and `passwordConfirmation` elements both declare a reference to the reusable `passwordStr` argument. When test code invokes this method, the `passwordStr` argument is passed to both statements:

```json
{
  "name": "confirmPassword",
  "args": [
    {
      "name": "passwordStr",
      "type": "string"
    }
  ],
  "compose": [
    {
      "element": "password",
      "apply": "clearAndType",
      "args": [
        {
          "name": "passwordStr",
          "type": "argumentReference"
        }
      ]
    },
    {
      "element": "passwordConfirmation",
      "apply": "clearAndType",
      "args": [
        {
          "name": "passwordStr",
          "type": "argumentReference"
        }
      ]
    }
  ]
}
```

:::note
A reusable argument can't be an argument with a [hardcoded value](#argument-types), also known as a literal type.
:::

For a working example of argument references, see [this tutorial](https://utam.dev/tutorial/compose-argument-references).

## Element Reference Argument Type

The `elementReference` type in an argument allows you to reference an existing element as a parameter value. This example uses an `elementReference` to a `targetElement` element.

```json
{
  "elements": [
    {
      "name": "sourceElement",
      "selector": {
        "css": ".source"
      },
      "type": ["draggable"]
    },
    {
      "name": "targetElement",
      "selector": {
        "css": ".source"
      }
    }
  ],
  "methods": [
    {
      "name": "composeDragAndDrop",
      "compose": [
        {
          "element": "sourceElement",
          "apply": "dragAndDrop",
          "args": [
            {
              "type": "elementReference",
              "value": "targetElement"
            }
          ]
        }
      ]
    }
  ]
}
```

Generated JavaScript code:

```js
// declaration
composeDragAndDrop(): Promise<void>;

// implementation
async composeDragAndDrop() {
    const _statement0 = await this.__getSourceElement();
    await _statement0.dragAndDrop(await this.__getTargetElement());
}
```

If a referenced element has a selector or filter arguments, those values are automatically inferred and added to the method declaration.

```json
{
  "name": "target",
  "selector": {
    "css": "foo:nth-child(%d)",
    "args": [
      {
        "name": "index",
        "type": "number"
      }
    ]
  }
}
```

When the element is referenced in a compose statement, this page object hard codes the value of 1 for an index.

```json
{
  "element": "source",
  "apply": "dragAndDrop",
  "args": [
    {
      "value": "target",
      "type": "elementReference",
      "args": [
        {
          "value": 1
        }
      ]
    }
  ]
}
```
