Transcript
In this lesson, we're going to be building off of the problem that we set up at the end of the previous lesson. If you need to go back and rewatch that for a refresher, please do. But in short, here was the problem: we can upload an image in our application, but unless we actually save this to a particular data type—like, let's say, a diary entry—then this image is just useless. Basically, it's what we might call orphaned. It's not attached to any data type. So it's just sort of lost in this huge warehouse of files in our file storage. Nobody knows what it's attached to or what it's for. It's the equivalent of trying to post a letter without an address on it—it ends up in the mail room, and nobody knows where it's meant to go or where it's come from.
So what we need to do instead is attach it to a particular diary entry. This is also going to set us up really well for later in the course, where we're going to set up restrictions that will mean that only those users who have created a particular diary entry can view the images for that diary entry.
We'll get into Bubble in just a minute, but let me sketch out what we're going to do. We've got our Create and Edit Diary Entry view here, and it's from this view that we are allowing a user to choose an image from their camera or their photo library. What we also need to have within this view is some kind of diary-entry-shaped container, which we can use to hold onto a diary entry so that whenever we upload an image, we can immediately attach that image to the corresponding diary entry.
Now, this compartment here, you may be able to guess, is going to be a view property. And for us to have a diary entry ready to put into this view property, we actually need to create it over here, so to speak. We need to create it before we pass it into this view. That means our first step is going to be to create a diary entry, and we will pass that diary entry into our Create/Edit Diary Entry view. That way, whenever the user chooses an image, we can immediately attach it to the corresponding diary entry. At this stage, we can more or less treat this diary entry as a draft diary entry.
As a draft, we may want to allow the user to hit Cancel, which would delete the draft diary entry. We don’t strictly have to do this step, but it helps avoid clogging up our users’ interface with diary entries that they started to create but didn’t finish. We'll discuss the pros and cons of this.
The other action we will allow the user to take is Save Diary Entry. Here, we will use the Make Changes action on the diary entry. In that action, we'll save fields such as the title, the start date, and also change the diary entry from a draft to a non-draft diary entry.
This is the concept. The first thing to do in practice is to set up this view property. On our Diary Create/Edit View, we already have a view property for a diary entry, which is helpful. I’m going to make this a required field, not optional. Why? Because we will always create a diary entry before showing this Create/Edit view, so we can push a draft diary entry into this view property to attach an image to. If this view property were empty, our create logic would break.
As soon as I do that, I’ll get an issue. Clicking on it takes me to a place where we were showing this diary entry view but not passing in a diary entry. Previously, we were hitting Create Diary Entry, so now we need to create a draft diary entry at this stage to pass into this field.
To do this, we choose Diary Entry, and we don’t need to set any fields here. There’s just one field we probably should add: a draft field, which is a yes/no field. Its value will be either yes or no. We can set the default value for all new diary entries to yes, meaning that any time we create a new diary entry in this workflow, the draft field will automatically be set to yes.
I can prove this in the web preview. Creating a new diary entry shows a draft diary entry in the database with the draft field set to yes. So, when the Create Diary Entry button is clicked, we are creating a draft diary entry. We then pass that diary entry into the diary entry view property for our Create/Edit view. The data source for the view property is set to the result of step one—the diary entry we just created.
Next, let’s add logic to attach any uploaded image to that draft diary entry. In the Create/Edit view, previously we saved the uploaded image to a custom state. We can remove that now. The draft diary entry has an image field to store the uploaded image, so we’ll use Make Changes on the draft diary entry (from the view property) and set the image field to the result of step one—the image the user just chose. Testing in the app shows the new diary entry has the uploaded image.
For images uploaded from the photo library, the same logic applies. The old action that set the custom state is removed.
We can also display the uploaded image in a group by setting the background style of the group to an image. The data source is the diary entry’s image field. Options include cropping and centering. We can hide upload buttons once an image exists by using a condition: show buttons when the diary entry’s image field is empty.
One remaining issue: draft diary entries are not appearing in the Trip Details list. This is because the diary entries have an empty trip field. We need to set the trip field when creating a diary entry to the current trip in the Trip Details view.
Next, UX improvements:
Cancel button: if the user hasn’t added any values, delete the draft diary entry.
Save/Create button text: use the draft field to conditionally display “Create” (draft) or “Save Changes” (non-draft).
For the Save button workflow:
Remove the old “Create New Diary Entry” action; we already have a diary entry in the view.
Set draft = no when the user hits Save/Create.
Cancel button workflow:
For a new draft: delete the draft diary entry.
For editing an existing diary entry: just hide the view.
Add a condition: only delete if the diary entry is a draft.
Image cleanup:
Deleting a draft diary entry doesn’t automatically delete the image in file storage.
Use Delete an Uploaded File action on the diary entry’s image field before deleting the draft diary entry.
Known limitation: swiping down from the top of the modal does not trigger the delete workflow in the mobile beta. Drafts may remain; display these as “Draft” using a default value in the title field. Allow users to manually delete these later.
This draft diary entry architecture may not be intuitive but sets up later course features well. In the next lesson, we’ll add a loading indicator for image uploads due to a slight delay.