# What's New in V4

### Changes in Naming

The naming used in the Data Model XML, Views XML and some JavaScript functions are changed to be more consistent and intuitive.

For the complete list, see the [Naming Details](#naming-details) section.

{% hint style="info" %}
The data model and view XML changes are handled automatically by the migration process. However, the JavaScript changes have to be performed manually.
{% endhint %}

### No More Explicit Links

It is now longer required to define `link` elements explicitly. Instead, call the links by path with link.*link\_path*(). The same function can now also be called directly from the `on-press` attribute in the view XML, optionally passing view variables as arguments. This replaces the need for the `link` attribute on buttons.

```xml
<view title="Main Menu">
    <button label="New User" on-press="link.new_user()" />
</view>
```

```xml
<view title="Select Task">
    <var type="query:task" name="tasks" />
    <object-list label="View Task" query="tasks">
        <action on-press="link.view_task($selection)" />
    </object-list>
</view>
```

It is no longer required to use `return link.some_view()` - instead just use `link.some_view()`. The link function now throws an exception, that is used for navigation.

For details, see the [Linking Views](https://docs.journeyapps.com/reference/build/syntax/broken-reference) section.

### New ‘resume’ Callback

Instead of defining `ondismiss` actions on links, you can now define a single `resume` function per view. If defined, this is called whenever the user returns to the view, both via a dismiss call and via the back button.

```javascript
function resume(from) {
    if(from.dismissed && from.path == 'user/new') {
        dialog("New User", "A new user has been created");
    }
}
```

For details, see the [Linking Views](https://docs.journeyapps.com/reference/build/syntax/broken-reference) section.

### New Choice Types

`enum` has been renamed to `single-choice-integer`, and `enum_set` has been renamed to `multiple-choice-integer`. Additionally, these types now take explicit keys for each option.

```xml
<field name="color" type="single-choice-integer">
    <option key="2">Red</option>
    <option key="6">Green</option>
    <option key="4">Blue</option>
    <option key="5">Yellow</option>
</field>
```

There are also three new choice types:

#### single-choice

Like `single-choice-integer`, but takes string keys. This is recommended over `single-choice-integer`.

```xml
<field name="color" type="single-choice">
    <option key="red">Red</option>
    <option key="green">Green</option>
    <option key="blue">Blue</option>
    <option key="yellow">Yellow</option>
</field>
```

#### boolean

Like `single-choice-integer`, but has exactly two boolean options.

```xml
<field name="confirmed" type="boolean" />
<!-- If not specified, default options are:
    <option key="false">No</option>
    <option key="true">Yes</option>
-->

<field name="acceptance" type="boolean">
    <option key="true">Accepted</option>
    <option key="false">Not Accepted</option>
</field>
```

#### multiple-choice

Like `multiple-choice-integer`, but takes string keys. This is recommended over `multiple-choice-integer`.

```xml
<field name="colors" type="multiple-choice">
    <option key="red">Red</option>
    <option key="green">Green</option>
    <option key="blue">Blue</option>
    <option key="yellow">Yellow</option>
</field>
```

### ‘Day’ Objects

`date` fields now use a `Day` object instead of `Date` object to represent the value. The `Day` object represents only the Gregorian day, with no time or timezone.

```javascript
var today = Day.today();
var today = new Day(); // Same as Date.today()
var day = new Day("2014-01-05") // Parse some day.
var day = new Day(new Date());  // Convert Date to Day, in local timezone.
day.startOfDay();	// Start of day in local timezone, as a Date
day.endOfDay();	// End of day in local timezone, as a Date
day.toString();		// “2014-01-05”
day.toISOString();	// “2014-01-05”
day.toJSON();		// “2014-01-05”
day.valueOf();		// 1388880000000
day.getYear() // 2014
day.getMonth() // 1 (0 - 11)
day.getDay() // 5
```

### New Label Behavior

If no label is specified on an input component, it is now inferred from the Data Model. Will be blank for direct view variables, since they do not have any label. This that you can have more concise view components, for example:

```xml
<text-input bind="my_form.field1" />
<text-input bind="my_form.field2" />
<single-choice-dropdown bind="my_form.choice3" />
```

To explicitly create an input without any label, use `label=""`. This will remove it completely (no whitespace). To still have some whitespace, use `label=" "` (a single space in the label).

The placeholder text of text inputs may now be customized by specifying `placeholder="My placeholder"`. This may be used to create more compact forms, for example:

```xml
<text-input bind="address_street" label="" placeholder="Street" />
<text-input bind="address_city" label="" placeholder="City" />
<text-input bind="address_code" label="" placeholder="Postal Code" />
```

### New V4 JourneyApps API

The JourneyApps API has been upgraded significantly, and is now available in V4.

Please see the documentation for the [Backend API ](https://docs.journeyapps.com/reference/backend-api/introduction)or refer to the section about [Updating to the V4 API](https://docs.journeyapps.com/reference/build/syntax/whats-new-in-v4/updating-to-the-v4-api).

### Naming Details

#### Data Model

| Old syntax                                       | New syntax                                   |
| ------------------------------------------------ | -------------------------------------------- |
| `<schema>`                                       | `<data-model>`                               |
| `<object name="..." label="..." >`               | `<model name="..." label="..." >`            |
| `<attribute type="..." name="..." label="..." >` | `<field type="..." name="..." label="..." >` |
| `<display format="..." >`                        | `<display>...</display>`                     |

{% hint style="info" %}
These changes are automatically applied by the migration process.
{% endhint %}

For details, see the syntax section under [What is the data model?](https://docs.journeyapps.com/reference/get-started/journeyapps-fundamentals/what-is-the-data-model)

#### Field Types

| Old syntax                                | New syntax                                               |
| ----------------------------------------- | -------------------------------------------------------- |
| `type="string"`                           | `type="text"`                                            |
| `type="string" spec="text.address"`       | <p><code>type="text:address"</code><br>Text Subtypes</p> |
| `type="int"`                              | `type="integer"`                                         |
| `type="decimal"`                          | `type="number"`                                          |
| `type="date"`                             | `type="date"`                                            |
| `type="datetime"`                         | `type="datetime"`                                        |
| `type="location"`                         | `type="location"`                                        |
| `type="attachment" media="image/jpeg"`    | `type="photo"`                                           |
| `type="attachment" media="image/svg+xml"` | `type="signature"`                                       |
| `type="enum"`                             | `type="single-choice-integer"`                           |
| `type="enum_set"`                         | `type="multiple-choice-integer"`                         |
| *n/a*                                     | `type="single-choice"`                                   |
| *n/a*                                     | `type="boolean"`                                         |
| *n/a*                                     | `type="multiple-choice"`                                 |
| `type="myobject" array="true"`            | `type="query:myobject"`                                  |

{% hint style="info" %}
These changes are automatically applied by the migration process.
{% endhint %}

#### Component Names

| Old syntax                                                                   | New syntax                                                                         |
| ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `<selectbox type="radio" />`                                                 | `<single-choice-radio />`                                                          |
| `<selectbox type="dropdown" />`                                              | `<single-choice-dropdown />`                                                       |
| `<textinput />`                                                              | `<text-input />`                                                                   |
| `<date />`                                                                   | `<date-input />`                                                                   |
| `<datetime />`                                                               | `<datetime-input />`                                                               |
| `<checklist />`                                                              | `<multiple-choice-checklist />`                                                    |
| `<barcode />`                                                                | `<scan-barcode />`                                                                 |
| `<gps />`                                                                    | `<capture-coordinates />`                                                          |
| `<signature />`                                                              | `<capture-signature />`                                                            |
| *n/a*                                                                        | `<display-signature />`                                                            |
| `<picture />`                                                                | `<capture-photo />`                                                                |
| `<viewpicture />`                                                            | `<display-photo />`                                                                |
| `<list type="dropdown" />`                                                   | `<object-dropdown />`                                                              |
| `<list type="static" />`                                                     | `<object-list />`                                                                  |
| `<object-table />`                                                           | `<object-table />`                                                                 |
| `<table> <info label="...">...</info> <info label="...">...</info> </table>` | `<info-table> <row label="...">...</row> <row label="...">...</row> </info-table>` |
| `<button id="proceed" />`                                                    | `<button type="primary" />`                                                        |
| `<button link="some_link" />`                                                | `<button on-press="link.some_view()" />`                                           |

{% hint style="info" %}
These changes are automatically applied by the migration process.
{% endhint %}

#### JavaScript Functions

{% hint style="warning" %}
These changes are not automatically applied by the migration process, and have to be applied manually.
{% endhint %}

| Old syntax                                      | New syntax                              |
| ----------------------------------------------- | --------------------------------------- |
| `Query#fetch()`                                 | `Query#toArray()`                       |
| `Query#get()`                                   | `Query#first()`                         |
| `Query#destroy_all()`                           | `Query#destroyAll()`                    |
| `Query#order_by()`                              | `Query#orderBy()`                       |
| `Query#fetch().forEach(function(object) {...})` | `Query#forEach(function(object) {...})` |
| `DatabaseObject#set_all()`                      | `DatabaseObject#setAll()`               |
| `return link.some_link();`                      | `link.some_view();`                     |
