# 12. Data Manipulation

### Delete an Object

Let's see what we want to add to our punch List app next:

{% hint style="info" %}
**App Design: Construction Punch List**

Sometimes our users will add incorrect punches and would need to remove them again. Therefore, we need a feature allowing us to delete punch items.
{% endhint %}

Let's add a "Delete Selected Item" button to our Main View XML similar to the "View Selected Item" button we already have. We will specify that the button should call the `deleteItem` function, implying that we'll add a JavaScript function that will delete the selected item. So, on your *Main* view in your `main.view.xml` file, add the button as follows.

```xml
<button label="View Selected Item" on-press="viewItem" validate="true" style="solid" />
<button label="Delete Selected Item" on-press="deleteItem" validate="true" style="solid" />
<button label="Add New Item" on-press="goToNew" validate="false" style="solid" />
```

Now add the `deleteItem` function to the *Main* view *JS*. Note that to destroy an object, we simply call `.destroy()` on the object:

```javascript
function deleteItem() {
    view.selected_item.destroy();
}
```

If you test this on a device, you'll see that the item is immediately deleted from the list once you press the button. Normally, it would be advisable to first get the user to confirm before deleting the item, so let's get that confirmation now using a component that is triggered from JavaScript called a[ confirm dialog](https://docs.journeyapps.com/reference/build/js-ts-apis/journey/journey.dialog). Update your `deleteItem` function to the following.

```javascript
function deleteItem() {
    var confirmed = journey.dialog.confirm({
        title: "Delete Item?",
        message: "Are you sure?",
        okButton: { text: "YES", color: "positive" },
        cancelButton: "NO"
    });
    if (confirmed) {
        view.selected_item.destroy();
    }
}
```

### Modify an Existing Object

We head on to our next requirement:

{% hint style="info" %}
**App Design: Construction Punch List**

Our app allows us to add new punch list items which have a status of "Open", but we need a feature to allow the user to mark a punch item as "Completed" or "Closed" when the punch has been taken care of.
{% endhint %}

Let's add this feature to the "View Item" screen of our app. Open up the `view_item` view and add a new button to the View XML that will allow the user to 'Mark as Closed'. To add some variety and complexity, let's navigate to a new view that we will use as a confirmation page.

```xml
<button label="Mark as Closed" on-press="markClosed" validate="false" style="solid" />
```

We specified `on-press="markClosed"` above, so let's add that function on the JavaScript side. So, on your "View Item" view, in the `view_item.js` file, add the following.

```javascript
function markClosed() {
    view.item.status = "Closed";
    view.item.save();
    notification.success("Item marked as closed");
    navigate.link('completed_item', view.item);
}
```

At this point, your *View Item* code should look like this

**XML**

```xml
<?xml version="1.0" encoding="UTF-8"?>
<view title="View Punch Item">
    <!-- Parameters go here: -->
    <param name="item" type="item" />

    <!-- Variables go here: -->

    <!-- Components go here: -->
    <heading>{item.comments}</heading>
    <info-table>
        <row label="Item Comments" bind="item.comments" />
        <row label="Item Status" bind="item.status" />
        <row label="Current Time" value="{$:showTime()}" />
    </info-table>

    <display-photo bind="item.photo" />
    
    <button label="Mark as Closed" on-press="markClosed" validate="false" style="solid" />
    <button label="Go back" on-press="dismiss" validate="false" style="solid" />

</view>
```

**JS**

```javascript
// This function is called when the app navigates to this view (using a link)
function init() {
    // initialize any data here that should be available when the view is shown
}

// This function is called when the user returns to this view from another view
function resume(from) {
    // from.back       (true/false) if true, the user pressed the "Back" button to return to this view
    // from.dismissed  (true/false) if true, the app dismissed to return to this view
    // from.path       contains the path of the view that the user returned from
    // if any data needs to be refreshed when the user returns to this view, you can do that here:
}

function showTime() {
    var now = new Date(); // standard JS function to get the current date and time
    return now.toLocaleString(); // changes the DateTime object into a string according to local conventions
}

function markClosed() {
    view.item.status = "Closed";
    view.item.save();
    notification.success("Item marked as closed");
    navigate.link('completed_item', view.item);
}
```

Let's create the *Completed Item* view, remember the name of the view should be `completed_item` and once created update the title of the view to "Completed Punch Item". Then we will also add some components to use for the confirmation.

```xml
<?xml version="1.0" encoding="UTF-8"?>
<view title="Completed Punch Item">
    <!-- Parameters go here: -->
    <param name="item" type="item" />
    <!-- Variables go here: -->

    <!-- Components go here: -->
    <heading>Item Completed!</heading>
    <info>This item is now completed and will no longer show up in the list of Open Snags</info>    

    <button label="Go Home" on-press="goHome" validate="false" style="solid" />
</view>
```

Finally, we need to create the *JS* function `goHome` to take us all the way back to the *Main* view. Up to now we have been using the `discard` and `dismiss` navigation actions to pop the current view off of the view stack and return to the previous one. But this will not work for the *Completed Punch Item* view, as we will have more than one view to "pop" off the stack to get to back to the *main* view. To do this, we need to `dismiss` or `discard` all the way back to a specific view currently on the view stack.

So, to do this we simply pass the name of the view we want to dismiss/discard to as an argument to the `navigate.dismiss` (or `navigate.discard`) action. Note: This will dismiss/discard views until it reaches the specified view. If the specified view is not on the stack then the operation will error. Therefore, in your `completed_item.js` file define the following function.

```javascript
function goHome() {
    navigate.dismiss("main");
}
```

So, the code on your `completed_item` view should now look like this.

**XML**

{% code title="completed\_item.xml" %}

```xml
<?xml version="1.0" encoding="UTF-8"?>
<view title="Completed Punch Item">
    <!-- Parameters go here: -->
    <param name="item" type="item" />
    <!-- Variables go here: -->

    <!-- Components go here: -->
    <heading>Item Completed!</heading>
    <info>This item is now completed and will no longer show up in the list of Open Snags</info>    

    <button label="Go Home" on-press="goHome" validate="false" style="solid" />
</view>
```

{% endcode %}

**JS**

{% code title="" %}

```javascript
// This function is called when the app navigates to this view (using a link)
function init() {
    // initialize any data here that should be available when the view is shown
}

// This function is called when the user returns to this view from another view
function resume(from) {
    // from.back       (true/false) if true, the user pressed the "Back" button to return to this view
    // from.dismissed  (true/false) if true, the app dismissed to return to this view
    // from.path       contains the path of the view that the user returned from
    // if any data needs to be refreshed when the user returns to this view, you can do that here:
}

function goHome() {
    navigate.dismiss("main");
}
```

{% endcode %}

### Test on Device

Let's test it out. Your app should now look like this.

{% tabs %}
{% tab title="Desktop" %}
![](https://2865107717-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9TCHLR67eLHBOjPvHhud%2Fuploads%2Fgit-blob-80b187afd4ef092224a4c4649716b6a03adde644%2Fdesktop-pl-no-columns-main.png?alt=media)

![](https://2865107717-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9TCHLR67eLHBOjPvHhud%2Fuploads%2Fgit-blob-a90cfdeef9647b251d9aad3683046260d6c284ef%2Fdesktop-pl-no-columns-closed.png?alt=media)
{% endtab %}

{% tab title="Mobile" %}
![](https://2865107717-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9TCHLR67eLHBOjPvHhud%2Fuploads%2Fgit-blob-deef06b3fc942ac0c066e82174386a5272b6a721%2Fmobile-pl-no-columns-main.png?alt=media)

![](https://2865107717-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9TCHLR67eLHBOjPvHhud%2Fuploads%2Fgit-blob-c318b70c1fc730891713ca947562ec6726d2af29%2Fmobile-pl-no-columns-delete.png?alt=media)

![](https://2865107717-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9TCHLR67eLHBOjPvHhud%2Fuploads%2Fgit-blob-e925949b207a19c080bdd32ecd30c772d8200cb4%2Fmobile-pl-no-columns-view.png?alt=media)

![](https://2865107717-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9TCHLR67eLHBOjPvHhud%2Fuploads%2Fgit-blob-91d5e290836fe69549efc0f710f1eacb8bfaf48c%2Fmobile-pl-no-columns-closed.png?alt=media)
{% endtab %}
{% endtabs %}

**Good Work!** The first part of the Punch List App is all done. Next up we are going to make the app more user friendly for tablet, desktop and web users.
