Great! To start this, I made a few changes to your original set up. Instead of using Shape elements to create the white square titles, I used the Group element to create the same effect. Then I placed the circular Button and Title within that Group.
Then, I created a new Data Type called “Project” (shown below):
In your app, you have 6 Project data entries (if you count ‘Other’ as the sixth data entry). Here are those in the App Data tab:
I created the Title field for each Project’s title (“Title”, Type: Text, List: No), and the Initial field for the Circular Button Letter (“Initial”, Type: Text, List: No).
Then I went back to the UI editor and created the repeating group with 3 rows and 2 columns (for the 6 Projects).
In the above screenshot, the white Group element (discussed at the beginning) is repeated within each Cell of the Repeating Group. Repeating Groups have to have a Type of Content, and Groups also need a Type of Content (since you’re usually using Repeating Groups or Groups to display data in an app). In our case, we want the white Group to display the data of the cell that it is in, which is why the data source of the white Group is: Current Cell’s Project.
Within the white group, are our two elements (the circular Button, and the title Text). Our data source for the text and button must begin with “Parent Group’s Project”; “Current Cell” is not a dynamic option to select because the button and title are technically housed within the white Group. Regardless, the button and the title are dynamically displaying the Current Cell’s data, it’s just called 'Parent Group’s data since they’re in a group. Since the white Group’s data source is Current Cell, that’s why the button and the title are displaying the same data they would if they were directly housed within the Current Cell, instead of the Group.
So, then we set the dynamic data of the button to be “Parent Group’s Project’s Initial” (shown below):
And then the title Text’s dynamic data is “Parent Group’s Project’s Title” (shown below):
Ok, now we’ve got the repeating group set up, and it’s displaying the correct data in preview mode
The next step is to create the functionality where a User can easily click any Project, and ‘select’ it, causing the selected Item’s circular Button’s background color to become light blue (or any color).
The first thing we’re going to do is to create a completely transparent Group element, around the size of one cell:
I named this Group element “Clickable Group Selector”. This makes everything easier on us so that, instead of creating identical workflows on the white Group, the circular button and the title (tedious), we can just create one workflow for this Group and place it over the top over all three of those elements. That way, the User can click anywhere in the cell and select the Project. So I just dragged that Clickable Group Selector into the first cell of the Repeating Group (shown below):
And then set the data source of the Clickable Group Selector to be “Current Cell’s Project”:
Now we need the workflows and custom states to create the selected, and unselected functionality, since we’re not using checkbox elements it’s a little tricky, but will definitely make more sense after you do this a few more times.
Custom states are great to use because we’re not making any changes to our database using custom states. Our list of Projects that the User selected are stored within the custom state, not our database - which means that we’re not making any changes to the database, and therefore we aren’t charged any workflows using custom states. When the page is refreshed, the data within a custom state is cleared. There are a lot of examples in the forum which explain custom states more in detail, but for this example, we’re going to create one custom state on the page “project_clone” (since that’s the page name). Here’s how to do this:
The workflow I first set up is: When “Clickable Group Selector” is clicked --> Element Actions --> Set State --> Element: project_clone, Custom State: create a new custom state…
Since our repeating group’s Data Type is Project, we need the data type of this Selected Projects list to be Project. And then we tell Bubble it is a list (by checking the box), since a User can select more than one Project cell at a time. If a User could only select one at a time before proceeding, it would not be a list and we wouldn’t check that box. In the workflow, the event will then look like this:
Now we need to set the “value” of the custom state. Right now, we only have a list, and we need to specify when to add a Project to that Selected_Projects list. We want all Projects that are clicked by the User to be added to this Selected_Projects list. So we’re going to say the value of this list is the following:
project_clone’sSelected_Projects(our list, which is empty on every initial page load):plus itemCurrent Cell’s Project.
So if we were just to leave things as they are:
Then every time a User clicks a Project, it will be added to our Selected_Projects list. That’s great and that’s getting closer to what we need, but we also need to allow a User to deselect that Project (or ‘remove’ it from our Selected_Projects list). In our first workflow, we used the “:plusitem” option, but there isn’t a “:minusitem” or “:removeitem” option in Bubble. This is where things get a little trickier!
As a workaround, we are going to tell Bubble that when the Clickable Group Selector is clicked AND when project_clone’sSelected_Project’s [already] contains Current Cell’s Project (the User is trying to deselect a Project they previously selected), then we need to set the value of the our custom state to be this:
The difference here is that we’re using “filtered” as a way to remove an item from our Selected_Projects list. We are ‘filtering’ out Projects that are deselected by the User. If you click on filtered you’ll see the following:
Here we’re just telling Bubble that if a User clicked an already selected Project, our Project_Clone list must be filtered, in that it can’t contain any Projects with the unique ID of the Current Cell’s Project which was just deselected by the User. It’s a little difficult to explain this, but if you can just remember that this is the only way to tell Bubble to ‘deselect’ the Project from our Selected_Projects list, since we don’t have a “:minus” option.
Now we have our two workflows (almost there!):
Our add this Project to our Selected_Projects list, Workflow:
And our remove this Project if it is clicked, and already within our Select_Projects list, Workflow:
So our last step is to create a few more conditions to our workflow when a Project is clicked for the first time, or if it’s been deselected and clicked again. First, we need to specify to Bubble that we only want to add Projects to our Selected Projects list during the following times:
- When that Project isn’t already within our Selected_Projects list
- When that Project was selected, deselected, and selected again
So for that second item, we need to tell Bubble to re-add the Project to our Selected_Projects list if the Selected_Projects:filtered list contains them (our ‘Removed’ list of Projects contains them).
For example, if a User clicked Windows, it’s added or ':plus’ed to Selected_Projects. Then if the User clicks on Windows again (after it’s already in the Selected_Projects list), it’s now within (Selected_Projects:filtered) - meaning the User wants to ‘deselect it’. Then the User changes their mind again, and wants to actually select Windows after all, so Bubble knows to then ‘move’ the Windows Project from Selected_Projects:filtered, back to Selected_Projects.
The complete workflow is set up like this:
To make sure everything is selected/deselected as it should be, I created the repeating group to the side with the following data structure:
The data source is our project_cloneSelected_Project’s list of Projects. The repeating group is going to display only the Projects the User has selected.
Last but not least, we need to change the color of the Button to notify the User that they have selected a Project. So we’ll go to the Conditional Formatting of the circular Button and set up the following statement:
The statement there is pretty straightforward, when project_clone’sSelected_Projects contains Current Cell’s Project, the background color of this button is a light blue.
Now we’ve done the hard part of selecting and deselecting projects using custom states. How do we save that? To do this, I created a new data type called “Estimate” (though it could be anything you want).
When a User has successfully selected all of the Projects they need, the User clicks next, and this workflow occurs:
Here we’re doing --> Data --> Create a New Thing --> Type: Estimate --> Field to change: Projects List add list project_clone’sSelectedProjects. Of course there’s more functionality, and data structuring to be done, but this is how you could start to collect the information that a User chooses from that Select a Project screen.
And those are the steps! I’m sorry I didn’t realize there were so many steps, and I hope this isn’t too overwhelming. Custom states are very tricky at first, but definitely become easier as time goes on. If any of this was confusing or if I can re-explain anything that didn’t make sense, please feel free to let me know.