Version and platform compatibility

  • This feature was introduced in version 4.80.0 of the JourneyApps Runtime and version 21.3.2 of the JourneyApps Container.

  • It is currently only supported on iOS and Android devices.

Photo quality

When using multiple photo capture, photos are stored at 85% quality by default. If you wish to take and display more than 5 photos at a time, please set the quality down to below 25%, which corresponds approximately with the default quality for capture-photo.

This feature allows an app user to take multiple photos in quick succession from the app.

Taking multiple photos in a single workflow works slightly different from the capture-photo UI component. The biggest difference is that there isn't an XML component and that there isn't a variable or field that the resulting photos are automatically bound to.

Instead, the developer calls a function that can be triggered from anywhere, e.g. a button or object-table, and the function returns an array of image attachments that the developer can use however they prefer.

Syntax, where options are optional:



Optional maximum number of photos to be taken. Defaults to undefined that means no limit. If the max number is reached, the camera dialog is automatically closed and the function returns.


Optional number between 1 and 100 to set the quality of the resulting images. Defaults to 85. The equivalent of medium resolution photos for capture-photo is around 25, and is recommended for most use cases.

The resulting array of attachments can be used by the developer however they prefer. If the user cancels the camera without taking any photos, the function will return an empty array.

Note: Multiple photos is currently only supported on mobile devices, and support for this feature can be evaluated for a device as follows: This will return an object:

  "supported": true | false


In this basic example, we have a button that allows a user to take 10 photos in a single flow. The photos are then added to an array that is displayed in a List component that triggers a Dialog that has a display-photo component and some buttons to delete the photo.

The user will also be able to add more photos by clicking the button again, and new photos will be added to the top of the list in this example.

Firstly, we create a new model in the app's Data Model to store the photos:

<model name="multi_photo" label="Multi Photo">
    <field name="image" label="Image" type="photo" />
    <display>Multi Photo</display>

In our view XML, we have this:

<!-- temporary placeholder to store the image for the dialog-->
<var name="dialog_photo" type="multi_photo" />

<!-- query for the list component-->
<var name="photos" type="array:multi_photo" />

<!-- Button to trigger the capture-->
<button label="Take photos" on-press="$:takePhotos()" validate="false" style="solid" />

<!-- column container list component to show a preview of photos taken-->
<list empty-message="Your photos will appear here" show-if="$:showList()">
    <list-item query="photos" on-press="$:pressed($selection)">
        <asset src="{$:getImage($object)}" />

<!-- dialog to show the selected photo and delete-->
<dialog id="edit-photos" title="Edit">
    <display-photo bind="dialog_photo.image" downloadable="true" />
        <button label="Cancel" color="negative" on-press="$:onCancel()" validate="false"/>
        <button label="Delete" on-press="$:deletePhoto()" validate="false"/>

In the corresponding JavaScript/TypeScript for the view:

function init() { = [];

function takePhotos() {
    var capabilities =;
    if (capabilities.supported != true) {
        await journey.dialog.error({ title: "Multiple photos are not supported on Desktop and Web." });
    // capture maximum 10 photos at 25% quality.
    var photos ={max: 10, quality: 25});

    for (var i = 0; i < photos.length; i++) {
        // We create a LocalDB entry in this example for each photo.
        // Note that `multi_photo` is the name we
        // used in the Data Model in this example.
        var newPhotoEntry = LocalDB.multi_photo.create();
        newPhotoEntry.image = photos[i];;
        // .unshift adds entries to the front of the array.
        // Can use .push to add to the back of the array.;
    // Since we are altering the array,
    // we force a digest just to be sure
    // that the UI is updated correctly.


// This gets the image from the model so that it can be displayed
function getImage(object) {
    return object.image;

function onCancel() {
    component.dialog({id: 'edit-photos'}).hide();

// When a photo is clicked from the List component
function pressed(element) {
    view.dialog_photo = element;
    component.dialog({id: 'edit-photos'}).show();

function deletePhoto() {
    var id =;, 1);


function showList() {
    return > 0;

Last updated