Bubble Crash Course for Beginners (2022)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys so this is the tutorial that i wish i had when i was starting out my bubble journey what we're going to be doing today is building a marketplace at from scratch in a way that just teaches you the fundamentals of bubble so this is really geared towards people who are completely new to bubble non-technical people maybe you've got an app idea that you want to get off the ground that's how i started that's how many people in this community started so that's what we're going to focus on today so if you want to jump straight into building jump to the next chapter you can find the timestamp in the description otherwise i just want to have a quick word on sort of bubble in general and the right mindset that you should have going in to bubble so bubble of course as you know already is a visual programming language what that really means ultimately is that it's giving you this visual interface which is manipulating the code base so to speak of your app underneath so in the same way as you're familiar with a program like photoshop right where you're using a visual interface with your mouse to sort of change the look and feel of an image what's actually happening there underneath is that there is code that's being manipulated every time that you're making changes in photoshop the code of the image file itself is being manipulated and you could of course just go straight into that image file and just change the code right just change a few letters here and there but that's going to be a really tedious and non-intuitive way of editing a photo so photoshop gives you this layer of abstraction above that and bubble is exactly the same thing just for web applications so giving you this layer of abstraction that's way more intuitive for people especially non-technical people to interact with but in saying that what bubble still forces you to do is program so i want to talk a little bit about the distinction between coding and programming because even though yeah you're not writing lines of code right that's syntax based code that we're all familiar with even though you're not coding what you are doing is programming whether you're writing code in javascript or you're bubbling you're still programming and what i mean by programming is that you're giving commands to a machine right you're writing a program that is going to tell a machine in this case your bubble application what to do so the bubble application rather is the program and it's running on a machine or rather multiple machines and what you have to do is tell it exactly what to do okay you can't take anything for granted you can't assume that the application is just going to do something in a particular way because you find that intuitive and just to show you what i mean for a second i've got this button here on a page that i created okay all that's going to happen is it's going to create an object create an object in my database and we'll of course talk about databases in in just a little bit so i'm going to click this button right and we'll create the object well i just clicked the button and it doesn't really look like anything happened but of course it did there there was an object that was just created it's just that as the user of this site just doesn't seem like anything was created like you'd expect that you'd see some kind of indicator right the button would change color or there'd be an alert or something but that kind of stuff wasn't programmed so if we just jump into the bubble editor for a second i can show you here's the command right this is what bubble would call a workflow and we'll get into all the details of how this works but i basically got a command here that says when this button is clicked okay create a new object but i don't have any other commands after that i'm not saying show an alert to the user or change the color of the button or anything that would give the user a visual cue that there has in fact just been an object created so that's what i mean by don't take anything for granted every little step every little bit of behavior that you want your application to follow more or less there is some built-in kind of commands around users but more or less um you have to create everything so just getting into that programming mindset is really the most important thing when you're starting out bubbling because yeah even though you're not writing code okay you should still think of yourself as a developer it doesn't really matter what tool you're using whether it's python or javascript or whether you're writing some code in something like an sql database if you're familiar with those or whether you're using bubble ultimately what you are doing across all of those tools is using them to write programs and that means thinking in a very logical analytical way about what you want your application to actually do so with that little preamble out of the way let's actually jump into editing and creating our first app all right so when you first log into your bubble account okay you're gonna see this page you may have already dabbled and you may already know about this so what we want to do is create a new application now from scratch so we click the new app button and now we're going to sort of call it something so i'm going to call this the mega tutorial 2022 let's say and here is just basically some forms that bubble wants you to fill out to give some information to them about what you're building for their own analytics so in our case i'm just going to skim through all of this it is not important for our purposes all right now our bubble app opens for the first place and what bubble does is it gives you this sort of template right out of the box if you want we don't want that so we're going to click start with a blank page and then we're going to close this assistant so this is the bubble editor okay so what you're seeing here is the canvas the design canvas where you actually will place the elements that will appear to your users in your website but you have other columns here on the left hand side to the workflow tab and the data tab and some of these other tabs as well which we're going to go into for now we're just going to focus on the design tab so basically what we what we've got here on up on the left hand corner is this is telling us the current page of the application that we're editing is the index page and actually i can actually click here and i can see some other pages here as well so that index page is what we are currently editing and if i was to double click on this canvas i actually bring up what bubble calls the element inspector so this is basically like a properties panel that lets you change certain things about the page or the element that you are inspecting so in this case we're actually changing the properties for the page itself so what i could do is i could actually come down here and change this to a flat color and then change the background color to maybe a light gray and by the way just quickly um your bubble editor might look slightly different than mine at this point so you can see that i've got this sort of grid here you can toggle off that kind of grid or toggle it on rather by just clicking up here grids and borders and then you can toggle to sort of show a grid and you can change the size of those grid boxes as well and change some other properties here so i encourage you to kind of play around with that when you are editing so there's one other little small thing that i just want to address before we kind of dig into the meat here and that is this responsive tab over here so bubble is actually right in the middle now of rolling out a new responsive engine by responsive all i'm talking about is the behavior of how your app is going to look depending on the size of your user's screen so how your application might kind of shrink or expand or have certain elements drop out depending on the size of the screen that your users are using so if you're watching this when this responsive engine is out of beta it's currently at the moment of recording in beta then you won't see this option at all but for us who are watching this sort of at this moment while the responsive engine the new responsive engine is still in beta we just need to come over to this responsive tab and click upgrade responsive if you've made some changes you might see this kind of thing but if you haven't made any changes then you won't say it at all we don't need to copy this so we're just going to upgrade that page and so this kind of upgrade is done on a page by page basis but as i said if you're watching this a few months from now when the responsive engine is out of beta then you won't see that option to upgrade you'll just be on the new responsive engine by default and um you do want to do this for every page you do want to be using this new responsive engine because it is vastly superior to what was there before in saying that i don't want us to actually deal with responsiveness at all today because it's sort of another topic on its own i want to suggest sort of deal with the fundamental building blocks of programming in bubble today so what i actually want us to do is if we open up that element inspector again for our index page and we go over to this layout tab okay i just want to make sure that your container layout is set to be fixed and what that means is that it doesn't matter what size screen your users are viewing your application on it will always stay the same size it won't shrink or expand or have any other kind of responsive behavior so right out of the gate okay let's just actually see what our application looks like we've given it this kind of background color what we can do is come over to this preview button over here click preview and that will open in a new tab our application as it appears to our users so you can see here that we actually do have a fixed width page you know like this is the the size of our canvas i'll just jump out of full screen mode here for you um you can see that you know this is the size of our canvas here technically it's 1080 pixels wide and this is 1080 pixels wide so my laptop screen is a little bit wider than that which is why you're seeing the sort of white space on either side so this is good this is what we actually want right now this is not how you would build applications in practice you would always want them to be responsive but let's leave responsiveness for now and i'll deal with that in a separate video so now let's actually add some elements to our page right let's actually make it look like something so over on the left hand side here you have all of the different elements as bubble calls them objects things that you can add to a page so the simplest one is this category visual elements so for example i can just drag drag a text box on here we all know what text does so what i want to do here is in this box up here i'm actually going to define what this text actually says so let's go with you know the old programming convention and you know i can change the size of this box right here i can also do some other things like change the style so how this text actually looks so you know bubble comes with a whole bunch of pre-configured styles like this i actually have to drag it a little bit bigger um but what you can also do is just click up here to not choose any style whatsoever and then you kind of have more granular control over the particular text properties that you like and you can actually create your own styles too right so your own um pre-configured templates for how elements like this text should look and we'll get into that in a little while for now we just won't choose any style at all so i'm gonna click preview again and that's going to reload this preview page for us and here you can see okay this is exactly how we've defined our app so there you go your app is actually out there in the world like if i sent you this url right now and made sure that this application was public you would see this as well it is live on the inter web so that's text right and you also have other kind of visual elements that you can add here so you know you can add a button you could add an image and you can upload whatever you want to actually be displayed within that image element here right so i'll upload an image here bubble will upload that and then it will display the image and there's sort of some properties that you can use here about the way that this image is displayed but this will sort of do for now so let's go back and and preview what this looks like so i could click as i said i can click this preview button or i can just come right over to that tab as it existed before and just click up on that top bar to see the new page and see what i'm doing here is i'm i'm more or less kind of like making a change right making a small change to the the application and then i'm previewing it to just see like you know did that work and that's a really good habit to be into obviously right now you know we're only changing the appearance of tech so there's not much writing on on changing lots of things but when you get into actually programming some complex logic you always want to sort of change one small thing and then test it just to see if everything still works as opposed to changing a whole bunch of things all at once and then previewing them all at once because then if there's a bug if something's not working as you expected you've got no way of knowing what sort of action or change that you made in the application actually led to that bug it could have been any of the changes that you made it could be an interrelation of the changes that you made so always good practice is to test as you go make a small change test make a small change test um that's just a good sort of meta programming workflow okay so those are basically like some basic visual elements but let's think for a second here about what application we're actually trying to build so it's a second-hand goods marketplace where people can upload goods that they're selling and then get in contact with people who might want to buy that from kind of similar to how facebook marketplace works if you ever use that so we obviously need some way for a user to actually input the information about the products that they're selling right to tell our application hey i've got something to sell please display it to other people in the community to add that kind of interactivity to our application we want to come down to input forms okay input being the operative word here because we're taking some value from a user they are inputting that information into our application so i'm just going to delete these elements right here by clicking them and then clicking delete on my keyboard and i'm just going to add a simple input over here if i just preview the page here just to show you how this input kind of works out of the box right here's the input side kind of has this hover behavior we can customize this kind of behavior as well by the way and then i can click into it and sort of start typing something and you notice how that sort of initial type here text disappeared as soon as i started typing so this type here takes us what we call placeholder tags so it's text that's only going to be displayed when this input actually has nothing in it and we can actually modify that ourselves so we could say something like you know add your product name to kind of give a bit more of a specific prompt to the user right so then i could add you know my product name maybe i'm selling you know some nike shoes right and what i also might want to do just to make this kind of a little bit more usable is just add a text box up here which is just a label it's just basically a label for this for this input okay and i have snap to grid turned on so i'm kind of that's how i'm able to kind of adjust this text to be fitting right here okay and now we could add some sort of other inputs too right like other things that we have we have like a multi-line input which is for adding like longer sections or longer paragraphs of text we also have a drop down where you can have your user select from a predefined list of options in our case right i think the next thing that we want to take is the price for this product so i've added another input here what i might just do is i might just copy this this label up here and use it again down here so what i can do is i can just do the old control or command c and then v to create a duplicate or what i can do and i'm using ctrl z by the way there to undo you also have the undo redo buttons at the top there what you can also do is just hold down control or command on a mac and just drag on a particular element and that will make a copy of it so here we might say price right and i might just rename this to be name and another good habit that we want to do at this point is actually name our inputs too so that we can easily identify them later so this input here is at the moment called input add your product name it's just kind of taken that from the placeholder text so we might just want to call that input product name so i would click up the top here to change that and this as i said this is going to be really important later on when we need to actually reference these inputs when we need to find them so i'll do the same thing here i'll call it input price should be input product price if i'm following the same naming convention there and the last thing that we might want to add is a photo right allow users to upload a photo of the thing that they're selling so here i can use the picture uploader element and drag that down here and then i'll give it a label as well right which just says photo okay and our users can now click this to upload an image following our good workflow we should preview that and we can see okay here's all these things as they're appearing now this price one we might want to change a little bit because this is of course taking um not necessarily text like we don't necessarily want to say type here we sort of want to kind of configure this in a way that's expecting you know a currency a dollar input in in this particular case so we can actually change the content format of this inbox here which is basically saying telling the input what type of value what type of information should it expect so we can change this from text down to an integer and if i reload the page then i won't actually be able to type in text here i'll only be able to type in numbers and that's really important because that's going to allow us later on to actually manipulate this data okay we can't necessarily add five dollars to a text value but we can add five dollars to a number value so we can do this kind of manipulation that's dependent on the type of value but we can actually go one step further bubble gives us sort of an extra option here which is called currency and that lets us kind of have this prefix dollar sign if i reload the page here you can see the input when it's focused gets that dollar sign then we can add our our value there so it's just sort of a helpful formatting but this is still ultimately a number value or an integer value okay and that's important because we can't save necessarily currency values into our database that's sort of our next step but we can save number values so behind the scenes what i'm trying to say is behind the scenes even though this is currency okay this is actually just a number value bubble is just letting us configure this input to treat it for formatting purposes as if it was a currency all right so here's our sort of really basic form right i might add nike shoes i might say actually they're gonna be a hundred dollars right i might upload an image there's my nike shoes but now what right like our users now inputted this information and they obviously want that to be like saved to the app in some way so it can be displayed to another user later on so we probably need kind of a button here because if i refresh the page now that information's lost it's gone so obviously there's sort of like a next step here right we would have you know from user experience point of view we're all familiar with this i'm sure having a button like this and we might call this like add product and that would then complete this form but now we actually need a way to actually save this information right what is going to happen when the user clicks this button we need some instructions we need to program something into our application and this is sort of a moment where i want to just move away from the computer for a moment and just talk a little bit about how our database works because our database is where all of this information is going to be saved it's essentially giving our application a memory so that it can retrieve information that's been saved there and display that or do something with that data at a later time right so over here we have our app here's our app right there and in our app we obviously have this like name input right so this is a name field and we also have a price field which i'm going to draw a little differently because it's it's a number we're taking a different kind of value here and then we have an image as well so these are kind of the inputs that a user can enter information into okay and now we actually need to kind of take this information and save it somewhere so that where we save the information is the database so database is commonly kind of drawn as like a big drum a big cylinder here is our database and i want you to think about the database just like a big warehouse with all these shelving units in it so we might have like a user's shelf right and the only thing that's stored on that shelf is users we might have another shelf that's just for products right so this whole warehouse is just full of shelving units and each shelving unit is dedicated to storing a particular thing what comes to mind for me is if you ever watch you know like detective or police shows as the evidence room and in the evidence room is all these different shelves and this shelf might be for drugs and this one might contain weapons and this one might contain documents or melee weapons or or something of the sort right so it's the same concept here basically is that we have different shelving units and each of those shelving units stores different parcels or different boxes okay but all of the boxes on a particular shelving unit are for the same thing okay so we got the users one and we've got the products one so what we want to do ultimately is take this information that the user's inputting these sort of unorganized values right there's this sort of one random name text value there's another price value right if i just draw this obviously our nike shoes and this is 100 dollars and then here god i do not want to have to draw a shoe right now but here we go um there's our there's our shoe um which looks more like an insect or a flying banana but rest assured it is a shoe and this is of course a text field this is rather a text value this is a number value and this is an image value okay remember so we want to take this information and package it in our case we're just caring about products so we've got this product shelf and in our case actually there's nothing on this shelf at the moment so i'll take all of this off right and then what we want to do is sort of take all of this information and put it inside of this package this product package and then store it somewhere on our products shelf okay so if i just blow this up a little bit i've got sort of a larger version here right this is our larger version that we want to kind of put onto the shelf this parcel this box that it corresponds to a product that is a product in our database has compartments within it for each of these values right so it's got right the equivalent of a name field it's got the equivalent of a price field and it's got the equivalent of an image field right so these individual kind of compartments or slots within the package within the box itself one way to think about this is like if you buy a new device like a computer or an ipad then in the box right there's usually like little compartments for all the little pieces right little compartments for the wires and this kind of thing or if you're a board game geek like me then you know you have different compartments within the board game box for all the different pieces right for the cards and for the dice and for the little you know the little pieces everything like that it's all in little compartments so it's the same thing same concept here in essence is that for each object that we're creating in the database right we have these little compartments within it to house these different fields and that's really convenient because then when we actually go to store this what we'll do is we'll grab a new empty box off the shelf right we'll grab this empty box and we'll take the value that the user have has inputted into those input fields and we'll store it here so we'll go nike shoes hundred dollars and our image i'm not gonna draw it again but there's a there's a you know what i can do i can do like a nike text something like that so that's what happens and then we're going to put this guy right onto our product shelf so that we can find it later and we can do something with it we'll get to that part in a moment so just making this concrete for a second let's go back into the editor and i will actually create this new product in our database so what we first have to do is go to this data tab and then configure the equivalent of what this box should actually look like like what compartment should exist within a product data type or a box right a package to store on top of the shelf because we're going to define kind of the template right what all of these product data types should look like what are all the compartments that should be in every single product and then every time we need to create a new product well then we just grab a new empty box off the shelf right we grab a new empty box off the shelf and we put it onto the shelving unit we store the values in it and then we put it in the shelving unit we put it into the database so let's start talking in the database lingo now so over here i would create my new data type that new object that new thing to put on the shell so i'm going to call that obviously a product and now we have this thing called a product and over here i'm going to define the equivalent of these compartments right what are the fields what are the values that should live inside of a product so the first one i'm just going to call name so corresponding to this over here and here we have to define what the type of value is so this is really important because if i set this to a file right then i wouldn't actually be able to save the equivalent of this because this is not a file format right like different bits of information are formatted differently and that means that bubble can do different things with them it can manipulate them in different ways so it's important that we define what type of value each of these fields actually is because the compartment size or the compartment shape is going to expect a certain type of value so in this case we want to set it to be we see a text field and you can see that there's obviously a whole range of things here we've got a number one numeric range date we've got a yes no which if you've done some other programming in the past you might be familiar with as a boolean so it's just basically a true or false equivalent field and then some other stuff down here file or an image which will just be a link a url pointing to where that file or image actually lives where it's stored on the internet which may be in a database somewhere else so that's our name field okay we want to also create one for our price and that's a number and then we want to create another one for well we'll call it the photo okay and we're just dealing with a single photo for now obviously your users might want to upload multiple photos but for simplicity we will just deal with a single photo for now so that is adding that information now to our database so now we have configured our product data type in the database and now we have to do is actually do the equivalent of of actually getting the value from this input and storing it within a data type in our database so that is some kind of behavior that our application has to do and all behavior that our application has to do we're going to define here in the workflow tab well at least most of it there's some stuff that you will define here on the design tab but for stuff like this we're actually kind of taking information from our page and storing it in the database this is where we actually come to the workflow tab so remembering that i've got this product button here this add product button okay what i want to do is add what bubble calls an event which is going to be triggered whenever that button is clicked okay so i'll follow bubble's instructions here and click here to add an event and i'll come down to the elements section and choose an element is clicked and here i will now choose from the elements that i've defined on the page and choose the one that i want to attach this workflow to so of course that will be the button add product now i've actually gone a long long way to setting this up it's the slow way a much faster way if i actually remove this is from the element itself if you have the element inspector open you can just click start edit workflow and that will just create that event for you it'll just create a this element was clicked workflow for you okay so that's the event okay so now when this button is clicked this event will fire and we will now have to define what are all the things that will happen when this button is actually clicked so those are called actions so what we actually want to do here is of course create this new product in our database and save those fields to it first section that we want to add we're going to go down to data things okay so this is sort of like the category of actions that you can choose from and we're interested in data because we're saving stuff to the database and then we're going to choose create a new thing so in bubble speak a thing is just an object that you're going to now create and add to the database so create a new thing and now we're going to choose what type of thing that we want to create and the option that we have here is a product you would have noticed just by the way that when we actually defined our product here in the database right we already had a user data type here and that is just a data type that comes out of the box with every bubble application right when you create a new application in your database in your warehouse there will already be a shelving unit defined for users and that's because users are just so central to every web application that bubble has just incorporated some out of the box functionality to handle users that's what we're seeing here but now that we're creating a new thing right we're going to choose from all of the non-user objects if we were creating a new user there would be a different action that we would actually choose and it would be under account and then sign the user up that would be the action we would choose but we're gonna kind of ignore that for now so now we're choosing the type of thing that we want to create so we already have that product template sitting in our database right okay so now we're creating a new product every time that this button is clicked okay so let's just see that in action like if i click over here and i add nike shoes 100 i'll upload those shoes again and click add product okay well we didn't see anything happen and if you're watching that first sort of preamble section to this video you all know that's because we didn't set any kind of alert or indicators of the user but we have probably just executed this workflow you know we clicked the button so in theory this should have fired and we can actually see if it did we can go down to the data tab here and if we go over to app data this is basically going to let us see all of the things all of the objects that live in our database so um kind of need this to refresh for a second here and you can see so all i had to do was sort of click off of the products table or the products view and click back onto it and now you can see here we've actually got one object in our database okay this single row in this products table is corresponding to that button click that we just did if i click this again haha we've got a second object you can see there's sort of a slight difference in their created date over here so that's giving us a clue but you can see the fields are all empty right price is empty name is empty photo is empty um i can actually click on this little edit icon to open up kind of the full view here and indeed you know all of these fields are empty you may be able to guess why all we did was we created a new product all right so we did the equivalent of kind of taking an empty box right and putting it onto our products shelf but we didn't put anything into that box we didn't take any of these values and actually route them into this new product object in our database that is what we actually have to do via the set another field option here this is where we actually define what of those values should be saved into the object so what i can do is i can add sort of the option to add a field here and then i'm going to choose from the list of available fields on our product object so again here's our product object right so i what i have to choose from are those fields that i've defined already those compartments that i've defined within this product box um so i'll start with the name okay and it's gonna say name equals okay so that's a great clue name equals so now we're gonna say well what should that name value be set to right what should it be equal to and i could just type in here you know my nike shoes 2009 and if i reload our preview it doesn't really matter what i type in here right in fact just so that's clear i might even type like reebok shoes okay if i click add product now and i look into our database i'm seeing my nike shoes so i've just defined some static value here that it doesn't matter what input has been typed into these inputs here what value the user has defined okay the value of every product that i create is going to be my nike shoes 2009. so that's not obviously very useful right it's static information what we want to do is point this field to the input okay so point this field to the input so that no matter what the user types in that's what's going to be saved to the product so that's what we call a dynamic connection right it's a dynamic value the value in the product will change depending on what the user has typed into the input okay so what i want to do here i can insert dynamic data here i can first delete this and then click insert dynamic data and insert dynamic data that is just the bread and butter of bubble that is just like the magic kind of button you click that and now you can write an expression right this is where you're actually doing programming you're not writing code but you're choosing options okay so the options that you have to choose from here are um well lots of different things but what we're interested in are these inputs here so this is where it was useful that we named these inputs before because now we know exactly which ones they are so we want to set the name value in our product to be equal to whatever value is in that name input in our application okay in our form so input product name and at the moment okay if i just click off of that this red coloring here and this issue that we're seeing up the top here this issue tracker okay that's telling us that this is not a valid expression as it is okay and the reason is we can't set this name text value to be equal to an input it kind of like doesn't make sense right it's like trying to say that i know the price of my shoes is anger i guess that makes sense on a kind of metaphorical level but it wouldn't really make much sense if you're trying to go into the shop to buy some shoes and the price tag said anger so this is kind of an invalid and invalid thing i mean you might throw a tantrum and make it come true in the store but what we want to actually do is make it literal so that a machine like our well the program that is our application which is just running on a machine right which is stupid literally it doesn't actually have any intelligence of its own we have to tell it literally everything that it has to do so we're not interested in the input itself we're interested in what's inside of the input and that's what we mean by value here take whatever is inside of that input the value inside of that input so that's what we're doing there and then we're going to do the equivalent for those other fields too which is pretty self-explanatory so the price is equal to the input products prices value and then we'll do it for the image right so or rather we call it the photo so the photo is equal to that picture uploaders value there and so now in theory this should be working so let's try it out okay let's say nike shoes 2010 i'm not even really a nike shoes guy so i don't know what the brands are here let's say 150 dollars to give it something a little different and i'll upload an image here and then i'm going to click add product and we go now into the database we should see unless we do an entry here in the database which is corresponding to the values that we just typed into the form all right so we've got our content now been saved from that form into the database a couple little small ux things that we might want to do at this point okay if i go back down to workflow right here i'm just going to add another action here which is reset inputs and what that's going to do is once we've clicked this add product button here then all of the values of these inputs are just going to be erased so that the inputs are empty again and that reset relevant inputs specifically the inputs that it's going to reset are the inputs in previous actions the inputs referenced rather than previous actions so these inputs here so again we're going to follow our best practices we change one small thing so now let's now test it okay i'm going click add product and wamblam there we go um those are reset so we're getting some kind of visual indicator now right that stuff is happening and we might want to go even one step further this is albeit an element that i almost never use but for demonstration purposes it's quite handy is this alert okay so it's an alert which i can tick to position it at the top it won't be visible when the page is loaded but what we can do is add another action here which is going to show that alert and we can set in milliseconds how long it's going to kind of fade in and stay on the screen and then fade out so if we reload the page then we can see that in action what i actually want to do this time around i'm just going to add my details here t-shirt 30 i'll just add my shoes again because it doesn't really matter at this point i want to actually draw your attention to this bar down here which is the debugger which is if there's one thing more than anything else to take away from this video it is use the debugger the debugger is your best friend when things aren't going wrong the debugger is the only person the only entity i should say that you can really rely on so one thing that we can do is we can go into step-by-step mode and what this is going to do is that when i trigger an event like clicking this add product button okay then it's going to let us cycle through each one of the actions that's going to be triggered by that event one by one and we can see what's happening inside of each of those actions at the same time so right now we're seeing okay that event that button add product rather is clicked okay so now we're going to see what happens next so we run next okay it's going to do this action create a new product and you can see what the values actually are that's being set in that new product you can actually click into any of these sort of blue highlight here and you can see okay what's the expression okay what bubble here is calling the evaluator what's the expression that's actually leading to this value that's outputting this value and this is the expression here it's input product names value and i can actually click there to see what is the value of that input at this precise moment okay so you can do that for all of these and this url here this is actually a url on bubble's own servers so bubble is actually hosted on aws amazon cloud services so amazon's massive server warehouses that power a lot of the web honestly they power bubble as well that's at least where a lot of bubbles um storage lives and where your app storage lives and so this is just a link it's just a url to a precise location on one of those servers okay so when we uploaded that image here in this picture uploader okay that image was actually uploaded and saved to somewhere on amazon's or rather we should just call them somewhere on bubbles servers and this is the location here so now this product when it actually lives in the database this photo field technically behind the scene scenes is just an address to a location on the server where the image file actually lives and every time that you want to display that photo then basically your your application is going to look at that address find the photo and then download it into your user's browser so that they can view it but anyway that we're getting into the weeds a little bit there we're going to go run next now we're going to see okay reset relevant inputs that's the next step if i click that presumably the inputs have been reset now as you can see and then there's this last action here show message and the alert pop up so we're going to run that and you can see there's that alert beautiful at the top of the screen so that's all you know this workflow is doing all that any workflow is doing rather it's just a cascade of actions a certain event happens and then in order all of these actions that you define are going to trigger all right so that's all good and well we can now save data into our database but obviously what we really want to do is retrieve that data from the database so go into our application's memory and pull out some data to do something with it in our case to just display it we just want to take information that one user has saved and display it out to another user so just coming back to our trusty sketch pad here we're basically just doing the reverse of what we already just did so we've got the database here inside of our database we have a shelf full of different products and then we've got our application over here right here's our app and we basically want to now sort of take one of these items off of the shelf okay and save display its information out on the page somewhere okay so the way that we actually will do that is by routing the values through some visual elements so we'll basically have like a text element here that's going to display the value will have another text element to display the number and then we'll have an image element to display the image so that what we can ultimately do right for any of these particular items here is just pull these values through onto the page we need visual elements on the page as the conduits through which we can display information out in the database so i'm just going to jump into the bubble editor and just show you how that looks kind of in practice so i'm going to for this moment i'm going to go hold down control and just select all of these guys here and just move them over to the left hand side and we're actually able to group these as well but i'm gonna get to that in a moment okay and then just over here on the right i want us to have some way of actually displaying this data back out to the database so if i've just got a text field this is you know the simplest thing that you could do here okay this text field as you've seen before can hold static values right so you could just type in here exactly what you want it to display or you could insert some dynamic data okay so dynamic data being data that's being you're looking somewhere else as to what the data should be displayed and the main place that you're going to look very often is going to be the database so to get into the database to basically we're at the moment where we're talking about this text field here for this text field to be able to pull out an item here it basically we basically need to tell it where to look okay we need to tell it hey come over here and look into the database and find this guy and then pull this guy out and display some of its value here okay so we're doing a a request essentially to the database to retrieve some information and the way that you program that in bubble is with this do a search for action so we're going to do a search for and that's saying look in the database for a particular thing okay where do we want to look at what shelf in the warehouse do we want to go to okay we want to go to this one the products okay the product shelf that's what we're looking for okay and now we can also add some constraints we can say okay so what products should i look for okay you could say things like look only look for products that were created within the last 24 hours or only look for products that start with the letter d or you know any kind of search constraint like that only products that were created by a particular user will kind of get into that kind of stuff in a little bit as well for now no search constraints so this is just gonna look in the database and pull out all of the products that live there and then display them back out to the user so we're gonna search for all products and immediately that's going to be an invalid expression because what's happening there is we're actually pulling out like all the products right and then we're trying to display them through a text element that doesn't really make sense we just want to take one of them okay we just want one single item here so for sake of clarity we're just going to grab the first item in that list okay so we're pulling out multiple we want to grab the first item in that list of things that was returned from the database okay and then we're saying okay well what field on that object okay i'm going to replace it here which of these fields do you actually want to display in this text here because you can't display the whole product okay you've got to choose what value you actually want to display so we're going to choose the name and just before we do this okay i want to just make sure that we're cleaning up our database a little bit because we've got a couple entries here that don't have any names on them and that's going to kind of ruin my demonstration here so anyway those are all our products here with some kind of random names and i want to add a a sort by value here so i actually want to grab the most recently created item in in the database so we'll go we'll sort by create a date and then descending we will choose yes so that we're getting the most recent at the top honestly this still confuses me whether it descending should be yes or no so i hope that i've that i've got it right here um and there we go so there's our first value t-shirt so that was the last value that we created so if i was to add something else here right if i was to add basketball i don't need to add the other fields uh we're still on step-by-step mode so i'll turn that off and now basketball is being displayed right and we can use the debugger here as well to make sure that this is actually working as we expect i can go down to this inspect button here okay and that's going to let me choose any element on the screen i can also search for them here and if i click on it it's just going to pull up kind of all of the properties all of the values and settings for a particular element and anywhere there's this blue kind of clickable text that's showing you that that's some dynamic information so you can click into it to see what's the expression right what's the expression that's outputting this value and the expression is indeed the search for products and we're grabbing the the first item in that list and then just displaying the name there so you can see that that's working kind of as you would expect all right so now let's say that we want to display the price right so what i could do is i could control drag on this to create a duplicate and go first items kind of price but this is a little bit of a it's a non-convenient way of setting this up writing this exp this whole expression every time we want to be a little bit more elegant and so what i now want to introduce you to is the concept of a group okay so just going back to our sketch for a second again instead of grabbing one of these items and then individually writing an expression that's going to grab the text and then for this element it's going to grab the price and then for this image element it's going to grab the photo et cetera et cetera et cetera what we want to do is instead just put all of the elements that are corresponding to the same thing in the database right all of these elements are going to be displaying the same product we want to put them all into a group so this is a group and then instead of routing the value directly into a visual element like this text field okay we actually want to pull the entire object right this entire product into the group itself this whole group is actually holding a entire product a group in bubble is what's known as a container and containers can hold any type of value just like an element like you know just like a text element can hold text and a photo element can hold an image a container can hold all of those things too but it can also hold entire data objects so if i just delete this delete this and come down here to this container section and grab a group right and then i'm just going to format it in a way that where we can see it so i'll give it a border okay you can see up here that we can set the type of content and that type of content could indeed be you know a text or a number and there's there's times where you'd want to do that but in our case right we can actually set it to hold a product it's essentially a product shaped container it can only hold products and now we can tell it to actually look in the database find a product and then hold on to it for us when the page is loaded so the data source for this product is going to be the same thing that we did for the text do a search for a product and we want to make sure that we're doing that same sorting right and of course this is now invalid because again we're trying to grab multiple products here and put them into a group that's only programmed to hold a single product okay so we just have to grab the first item from that list or any item from that list right we also have access to the last item we also have access to a random item or a particular item from a particular place in the list but we will just grab the first item and now if we preview this and we inspect our group here well you can see that it is in fact holding a product it's holding the t-shirt product and you can jump into the data source and see why okay so that's all working perfectly we have this t-shirt product living inside of the group and all we want to do now is basically like cut little slits into it essentially so that the values the fields within it can kind of shine through right so that this stuff here the text value for the name and the price and the image basically create little windows in the group so that those values can shine through can populate uh the elements so as before we'll grab for example this text element which is going to hold the name and we'll insert dynamic data and now we have access to the super handy expression parent groups product so parent group meaning the group that i am living inside of and since we're writing this expression from the point of view of this text element okay the parent group is this group here this group product so we can grab the product that's living inside of that parent group and then we can display some value here and we're going to display the name and if i drag this down by holding down control now we can just update this to be price and i'll use an image element as well and instead of uploading a static image like we did it right in the beginning we'll insert dynamic data here for a dynamic image and again it's parent groups product and its photo and alas now our beautiful absolutely wonderfully formatted group here that should win some design awards in my opinion is now displaying all of the values that we want it to so this is working absolutely perfectly and if we wanted to kind of change which values were being shown here well now we don't actually have to go in and edit every individual expression right and change the search parameters we can just change it here at the group level so maybe we want to actually sort these by um when the first one was created so show the the earliest first and our first one actually doesn't seem to have a price field or an image field so that's why this information isn't showing up but i think you get the picture so we can kind of change the search parameters at the group level and then all of the elements inside will of course reflect whatever the new value of the group is and just while we're here because we all pretty much always want to keep our elements in groups okay because it keeps the page organized and it makes it convenient for us to have groups reference other groups and pass information between groups which we're not going to talk really about in this video but good practice is to keep yourself organized here so i'm just gonna pause for a second and look in this elements tree and you'll see this is basically a list of all of the elements that are on our page right now and you can see we've got a bunch of elements here that are all existing kind of at the same level in the in the page hierarchy and then we've got our group product which we can open up and we can see okay here's all the stuff inside so we want to keep kind of a good level of organization here otherwise things will get messy really quickly so what i can do i want to group these guys the form elements within a single group so if i hold down control and select all of these what i can do is actually right click and then group elements and depending on the structure of your responsive page you'll want to choose a particular one of these okay we're not going to go into responsive design today because it's not really worth doing when you're just getting a handle on the fundamentals of bubble but in our case we want to just put this inside of a fixed container so that's what it should look like with a fixed layout group all right so we've seen how to pull a single product into a container okay but what if we want to display like an entire list of products right so just like you know if you were going on to like the browse or the search page of this website you'd expect to see multiple products not just a single product okay so for that we need a different type of container right here we just have a standard group and a standard group can only hold one data object or one data thing at a time what we need is an object that can actually hold multiple what we need is something like this that this is sort of one formatting of it that has rows okay essentially like a table and then when we look in our products shelf when we look in the database and grab a number of different products okay well then we would basically pull a product into each of those rows okay so that we could display multiple of them to the user so the way that we do that in bubble terms is with something called a repeating group which is very aptly named okay so repeating group is just a group that repeats or rather more accurately the right way to think about it is more like a collection of groups all kind of stacked together or grouped together at the repeating group level just like for the group we define what type of content it expects right so this is a kind of an ongoing theme as you're adding elements and you're telling that element you should expect this type of value okay whether that's like a primitive value like text or an integer value or a yes no value or an image or whether it's a data type value right like a shape that you've configured an object that you've configured like a product so we always have to define that it's almost as if we're creating like a product shaped hole and it can only accept products right if you try to put you know a different object in there it just won't fit so we're expecting products and then the data source we can again do a search for products in the database and i won't add any constraints here and i won't even worry about sorting and this expression is now immediately blue because this is valid this repeating group is expecting multiple products and this expression right now is returning multiple products when i say returning what i mean is we're basically sending a request here to the database do a search for products and send me back everything that you find and so what is being sent back from the database is what is being returned that's sort of like the lingo in the programming space returned so searching for products we're getting multiple products returned and if i preview this our repeating group is down here we can't actually see anything in it yet okay but if i sort of click on one of these cells you can see okay well inside this repeating group okay we're at the repeating group level here um there's the first product there's a second product third four so there's there's definitely stuff in here okay the only thing we haven't done which you maybe have guessed already is we haven't added any elements to actually display the values within these products right we haven't added the conduits through which these products can really show themselves so we will do something here we will add a big text field up the top maybe we'll give it a little bit of formatting here as well and we'll insert some dynamic data and now we have access to this expression current cells product so any repeating group which is just like a table right just like an excel spreadsheet essentially um well a single column excel spreadsheet you have cells and those cells are just the the subgroups right in the list so current sales product what we're going to do is just define all of this at the first cell level here so i drag this text element down it's actually going to be replicated in each of these cells whatever i do up here is going to appear in every single cell so that's the really kind of convenient thing about the repeating group is it just mimics the same formatting throughout each of the rows or each of the columns depending on how your repeating group is set up so when i choose current sales product name you can see well this is sort of being mimicked across all of those groups and then if i take a look at our preview here you can see that is in fact how it is appearing so this is sort of some really fundamental stuff here is displaying stuff in lists and of course right we might want to also maybe i will bring this over to this side a little bit and call this the price maybe make it a little smaller and bring that guy over actually i'll bring him back and then add in an image here as well an image here as well insert dynamic data current sales products photo okay and there's our repeating group this guy doesn't have a a photo but all the rest are displaying information just as we would expect so that's repeating groups that's lists in bubble all right so we can now create and display these products but what if we want to let our users edit the products that they've created that's kind of like completing the picture here is most applications you know let people add information we display that information out and we also let users edit and delete the information that they've added so completing the picture here we want to let our users be able to edit products that they have created so the way to do that we basically want you know one way to do this is we've got this repeating group of products here what would be cool is if we could click on one of those and that basically like displays a form from which we can actually edit the content so we've already got a form here which is convenient what i want to do before we kind of get too ahead of ourselves i'll create a new form which we'll use to edit one of these products and then we'll actually combine that form the edit product form with the create product form because they're using the same import inputs at the end of the day we don't really need to repeat ourselves here so we can use the same form for both creating a product and for editing a product but let's just jump into an editing mindset first an editing form granted that we haven't really talked about users yet um but at the moment we're just going to let like anybody edit any product which is obviously not like a super intuitive user experience but it's just going to at least get us familiar with the edit functionality so what i might do i'm just sort of making this repeating group a little bit bigger to give ourselves a little bit more room is just add a little button here a little button that says edit okay and if we click that then we basically want to display a form that's going to let us edit the product that's in this cell and where we want this form to live okay we could have it live anywhere but just to kind of show you a little bit more about what bubble can do okay we're going to use a pop-up right so a pop-up is a very special type of container that lives kind of one layer above your page and isn't visible to your users until you show it okay so we might call this the pop-up edit product and just like any container right just like we did with our first group now and then we did with our repeating group okay we need to set the type of content here for this pop-up and because it needs to kind of house a product that we're then gonna edit we want to um set this to be a product type of container and we don't want to set the data source okay the reason why we don't want to set the data source is because we don't know yet which product we want to display in this pop-up setting the data source here is the equivalent of saying when the page is loaded what product do i want to load into this pop-up but that's not the way that we're loading content that's not the way that we're loading the product in this case we're only loading the product when a user actually clicks on that edit button in one of the cells and then we want to take the product from that cell and put it into the pop-up so that's user behavior right that's a command that's going to happen when the user takes some action okay and that's a clue for us that we actually want to use a workflow rather than this data source so we actually want to use a workflow here and if i go back onto my page and click on my edit button this is where we can actually program that initial event so when this button edit is clicked okay we want to do a couple of things well one of the things that we obviously want to do is display that pop-up so if we come down to element actions okay and we click on show and then what we want to show is that pop-up edit product okay that's kind of like one big piece that we need to do right out of the gate if i reload this and i click edit here there our pop-up is appearing okay so the next step here is actually to put something into this product so just jumping over i want to sketch this out again real quick we've got our repeating group of products here right repeating group which i'm just going to abbreviate to rg repeating group of products okay with all these individual rows and in each of those we have some different products right we have nike shoes we have a t-shirt right we have other stuff down here we want to be able to click on one of these cells and then populate i might use a different color here i'll use a green for the pop-up okay this is our pop-up all we're doing is this when one of these cells is clicked or rather when the edit button in that cell is clicked we want to take the value of that cell and push it into the pop-up okay that's all i wanted to sketch it's just really really simple what we want to do here so how do we do that in bubble what we'll do is before we show the pop-up essentially we want to display some data in it okay so that it's ready to go right off the bat we want to program this action here so how do we do this action here well we want to add another action and i want it to be before this action so what i'm going to do is right click and then click choose insert an action that's going to add an action previous to the one that i had right clicked on and then we want to come down to element actions because what we're dealing with here is an element and then we have the option here to display data and what this is asking us is what is the element that we actually want to display this data inside of okay that's what this first part here is and we want to display it in this pop-up pop-up edit product and bubble will know immediately that you need to display a product type thing in here okay you can't just display any old data because the pop-up itself is expecting a product right so i couldn't for example i couldn't just use this for example current user that doesn't make sense and we're going to get this kind of error here where the pop-up edit products content type so the type of content that it's expecting is a product but what you're trying to put in there is a user so anytime that you see these kind of like hints when you're learning bubble in the beginning it's just just read them pay heed to them they're going to tell you what's actually going on and they'll give you an option here to resolve it by changing the content type of that pop-up to a user but that's not what we want we want it to be a product we just need to change our expression so what we actually should be choosing is this current cells product and by current cell okay this is referring to the cell in which the button was clicked okay so that's kind of a critical thing to point out is that any time that you're launching a workflow by clicking on an element okay you're going to be able to have access to the parent group of that element and in this case the parent group is the cell it's the repeating group cell so that button here's the button here was clicked and it's inside of this cell okay so we can actually take the value of that cell so current sales product current cell again from the point of view of the element that was clicked which is the button in this case and then we could actually choose a field here but we don't want to because we want to display the entire product we can take one of its fields later and display it through a text element but for now we will just want just ship the entire product into that pop-up and what i'll do just so that we can see this working right off the bat is grab a text element here and dynamically display that parent group's product so the product in the pop-up display its name and now if i refresh the page i click over here nike shoes boom there it is in the pop-up nike shoes or t-shirt there we go t-shirt is now in the pop-up okay so now we could just replicate this form all right i could literally just if i delete this i'm just going to take this entire form here copy it with ctrl c and then go into my pop-up edit product and paste it and i want to actually make it horizontal so i'm going to right click center horizontally and then instead of adding this product right because this is an edit pop-up after all okay we should actually make this an edit product so now what you would expect of course is that these inputs should be pre-populated to whatever that current products values are okay so we can kind of see what was there and then change it at the moment right even if we click this and if i go inspect and look at this pop-up yeah it does have the product that we're expecting okay but we kind of want i want to see the current product's name in here i want to see nike shoes i want to see the price 100 right i want to see the image here so that i can change it i can see it and then change it so every input gives you the ability to display some initial content okay so when that input is loaded it's rendered okay what is the content that should just already be existing in there when you're creating something from scratch like we were with this original form here you don't want to set the initial content all right we're creating something from scratch it doesn't make sense to have an initial content in there but now that we're editing something okay this is where initial content is really kind of critical for the user experience so in here i can insert some dynamic data and what i'm actually seeing here is i can choose the parent groups thing and to me that's a clue okay parent group's thing that means that the parent group doesn't actually have anything set and in fact bubble is asking me to set it here so this form that i carried across right which i might just call edit inputs for clarity doesn't have a type of content itself okay so i could actually set this to be a product and then as the data source i'm going to choose the parent groups product so remembering that this group edit inputs is inside of the pop-up it is inheriting the product from that pop-up and then these inputs can then pull through the value from the group so just coming up to our diagram again here's our pop-up here's our edit group right here's our edit inputs group so what's happening is the value of one of these cells in the repeating group is being pulled through into the it's been pushed rather into the pop-up via a workflow and then this edit inputs is grabbing it from the pop-up level and then any inputs actually inside of here are grabbing it from this edit inputs group so we're just passing data from one group to another from one container rather to another all these repeating group or a group or a pop-up they're all containers right they all hold data and so um what we need to be doing is playing past the parcel with one container to another and to maintain that sort of dynamic link in our logic so this pop-up's having its value set by a workflow and then this edit inputs is just pulling that data from whatever the pop-ups value is okay so this is basically an expression that's just you can think of it as running all the time it's constantly looking here okay what's the value what's the value what's the value what's the value and if the value here changes then the value inside of this group changes so now that we have this parent group of the inputs set up now inside of the input itself we can have access to the parent groups product and then we can choose the value that we want okay so in this case the name and i can do the same thing down here the parent groups products price and then i can do the same thing here with the photo all right now if i click edit boom there we have it all of that data is loaded and i can sort of just like oh you know what i missed up the year was actually 2009 which in theory should make them even more valuable now uh so that's all that's set up now we have to set up a workflow to actually edit the stuff okay what this edit product button should do so let's go back click on edit product and this is we're going to choose start edit workflow so that we automatically attach a new event to this button and have a little think here maybe this is a good time to pause the video and just try and figure this out for yourself if you've got this far if you've been building along just try and figure this next part out for yourself what we're going to do if you are ready to go is come down to this data section because we want to make changes to a product in the database our app is pulling out some product from the database and then it's making some changes to it and then it's sending it back in essence so anytime that we're dealing with the database we want to be talking uh we want to be using this data section and then we have up an option to make changes to a thing so that's what we're going to choose make changes to a thing and what's the thing that we want to to change the parent groups product okay so parent group remember this expression is from the point of view of the element that was clicked the element that was clicked was this button edit product which is living inside of this group edit inputs okay and that group edit inputs is housing the current product that we're looking to edit so in theory right parent groups product is going to be that edit inputs group so we're going to get the product that we're trying to edit that's that is uh what we want and now we can choose okay what should we set all those fields to right what changes should we actually make so we can set all these things to be to be something new right again i could just type some new value here okay but obviously that's not what we want it's not dynamic we want dynamic data not static data so the answer here is just to point in fact we want to point this to the inputs in our group edit pop-up however we haven't renamed our inputs here so we actually have two edit product names we've got an input product name here in the edit popup and then on the page we've got an input product name so now that we're coming to do our workflow input product name input product name which one is it okay so this is a good example of why naming your elements is really important really important so pop-up edit product we might want to call this input edit product name okay input edit product price picture uploader edit okay now if we come back to our workflow okay we can actually see this is in fact the input that we want to set it to so setting the value there so that when this button is now clicked okay it's going to save the value of the input here to the product's name field so that's the way that we edit stuff so i'll do the same for the photo right picture uploader edit and i'll do the same for the price it doesn't matter what order you you put these in by the way it'll all get executed by bubble instantaneously essentially so we make changes to the product and then from a user experience point of view right we might want to then um hide the pop-up right hide the pop-up edit product and now let's see if this actually works so i'm going to click i can choose 2009 right i want them to be a bit more valuable so rather they were 2010 now we want 2009. that's going to bump up the price to 200. the photo will will keep the photo the same and then we'll click edit product okay and you can see it changed it changed here in the repeating group and it changed if you go into the database and you click refresh data down here it changed here too which is exactly what we would expect because this is where the data is kind of living actually in the database and this repeating group here on the page is just retrieving the data from the database again anytime that you are setting the data source okay like this search for products just think of this as a command that is constantly being fired so search for products search for products search for products search for products and if anything changes in what's returned from the search then it will be reflected in the container doing the search or the element doing the search so that's why we could kind of see it being updated here in real time we didn't need to do a page refresh or anything of that nature all right i want us to start to do something a little bit more ambitious here okay we don't want to be doubling up here with this pop-up edit form okay and we also have a create form and they have exactly the same inputs and this is violating something that we'll talk about a little bit more about later on but is violating what we call the dry principle the do not repeat yourself principle which is a good principle to keep in mind when you're programming if you repeat yourself then you are increasing the chances of introducing some bugs into your code and you're also making it really hard to maintain your application over time that might sound a little abstract right now but this will hopefully make it a little bit more concrete and more the more examples that we that you see over time um you'll realize the value of this so at the moment we're repeating ourselves if we wanted to change the look of one of these inputs right well we do have styles which we haven't talked about yet but if we wanted to change something here even change the the placeholder here you know then we would have to change it also in the pop-up edit product form so let's actually just use this single form for both editing and creating new products how do we do that well what i want to do just right out of the gate is i'll just delete this form because it's not super important and drag out this repeating group and now in essence what we want to do is when this edit button is clicked right instead of pushing the value of the cell into that pop-up we push it into this form okay but you might be thinking i mean that form is is for creating products so kind of how do we make it do both it is a little bit confusing the first time that you deal with this right so the first step that we could do here just to kind of get our bearings okay is actually set this group which we're going to call the group add slash edit product okay and set it to be of type product okay just like we did with the the pop-up edit form and this workflow here we now want to change so that instead of displaying the data in the pop-up we actually display it in that add edit product group instead and we can remove this as well and at this point we could also set the initial content for these inputs okay and the reason that this is going to work even for creating a new product and editing is that unless this edit button is clicked there isn't going to be any value here in this group it's going to be empty so we could easily set the initial content here to be the parent group's product's name just like we were doing on their edit form right parent groups products price and the parent groups products photo okay and if i load this right it'll actually look just the same as before right i might add here digital camera i'll just clicked tab there to go down to the next input make it 400 and upload it here and then i created a new product now it's not appearing here in my repeating group why well if we come down to our opinion group we see we've got a fixed number of rows we're only showing four rows so we don't want that actually we want many different rows and you can see that this minimum height of the row is actually giving us some issues here because this line here you can see there's sort of a bit of a weird overlap so we might just want to make this a little bit bigger 150 pixels would probably do it and now if we preview the page we're kind of giving some more space here and we can and we can scroll so that's working great we can see that we've created that digital camera so this is still working even though we set up that edit kind of functionality this is still working however now let's see what happens if we click edit boom now we've got a value in here and we could do this for any of these right boom so it works to create a new product okay and we can get a new product kind of in here but now if i click add product if we do the step by step we're creating a new product again another digital camera and i only have one of them so this is a problem because um i can't sell two things of something i only have one of so if i refresh this data in the database you can see we've got two digital cameras so this is a problem we don't actually want to create a new product every single time that button is clicked sometimes we want to edit the product that's already in there so let's just think about this for a second we've got this form here okay with a button here okay and some inputs right some inputs now at the moment when this button is clicked we're launching this workflow which is to create a new product that's fine we also want to launch a workflow where we edit a product okay and since we have the same element triggering two different things okay we need to have some conditional rules right we basically need to say the equivalent of if there is an existing product right in the form right if that's true then we want this to fire if it's not true then we want this to fire okay so in bubble how we would do that is i'm just going to delete my popup edit product because it's going to confuse things is we've got the single event to add a product and we actually want to add another action here if i insert an action and that's going to be i'll make changes to a thing action and the thing that we want to make changes to is going to be parent groups product okay and we would set this up just as we did before right to be taking the value of those inputs the inputs that the form is is also using when it creates a new product right the price okay okay only now you can imagine well this is a problem because first it's going to create a new product and then it's going to make changes to a product if it's in the form and then it's going to do these things these things are fine these things are kind of what we want however we don't want both of these to fire so what we actually want is an only when condition here that's the equivalent of writing this rule or this conditional conditional rule here so and only when rule we only want a new product to be created only when that parent group's product so the form right the container that's holding those inputs when it is empty is empty okay because of course on page load right now it is empty okay there isn't anything in here as soon as we click edit well i'll i'll click inspect here and you can see for yourself right it's empty there's no product in this container it's empty but once i click and click edit and we've pushed a value into that group well now it's no longer empty now it has a product so you can guess that the inverse condition is what we would want over here right only when the parent group's product is not empty okay in that case we actually want to make changes to the product in that group and the alert the last kind of thing is the alerts we can actually change the alert message here you know depending on whether a product was added or created i'll get to that in a minute i think let's just test this functionality out for now so let's just add a new product for example right maybe we've got a lawnmower to sell 160 dollars all right there's our lawnmower okay let's do the step-by-step i'm gonna click add product okay that button and product is clicked okay next step create a new product okay we only want that to happen when the parent groups product is empty so here's that condition that only when condition and since it's highlighted green that's telling us that the condition is true okay the answer to that condition is yes the parent group's product is in fact empty is empty is yes okay so that's all great and then if we run next the next action which is going to make changes to the product well that's highlighted red because it's not true there isn't any product in this form yes there's values in the inputs themselves right but we haven't actually pushed a product into that underlying group okay which we would have been doing by clicking this edit button okay so this make changes is not going to fire and then reset out relevant inputs and show the message that is going to um to then fire however now if we come back to our nike shoes and i've recently found out actually these are 2005 which is probably going to double the price at least to my logic and we go step by step now will we create a new product no we won't because that parent groups product right the the input form group the container for all these inputs it has a product in it is empty is equal to no all right there is a product inside of that container so then we move over to the next action which is evaluating to true because there is not um well rather there is a product in that group so is not empty is evaluating to yes okay and now you can see that we've made changes there and so the last thing here is that is that alert that i've just showed you so i actually click change the alert message so we want this alert message to display something different depending on whether there was a product being created or whether we were editing a product so we can use the same kind of only when logic i'm actually going to add in the the expression here so parent groups product is empty okay and at the moment this would just say yes like if i if i just click add product here okay it's just evaluating to the value of that expression which is yes what we actually want to do is we can come over here and go formatted as text we can actually give a value a text value to be displayed if this expression is true right so if the product is empty and we can give another one if it's no okay so if it's empty in that case right we're saying that the product was created and if it's not empty then we're saying that the product was edited okay like i said this is sort of like intermediate level bubbling here but pretty simple to get your head around and and can be really really powerful way of of adding some nice ux to your site so if i add a new product here what's another product that i can think of maybe an ipad you know it's secondhand so i know they're still pretty expensive i'm gonna upload okay and then if we click add product boom product created and let's say i want to edit my t-shirt no one's buying it so i'm going to reduce the price a little bit and let's run through this step by step we already know what's going to happen for these actions and if we come over to our show alert and we can see that the the option is product edited because we have this this formatted as text expression here where the the parent groups product is not empty and if we format that no as a larger text string then what we're getting is product edited so product edited is what we're going to see up the top all right now our page is looking a little bit crammed in most applications that you're going to build you're going to have the concept of pages right you're going to have different content that's living on different pages in your application so let's do that right now at the moment we've just got this single index page but let's actually split off some of the content here so we'll keep the index page as kind of like a home search page right where we can just sort of like list all of the goods that people have listed for sale and then we'll have sort of like a create a product page where we'll actually put this form here so if i just go up to my page drop down here this is where you can add new pages so add a new page here and i will call it the create page and i can actually choose one of my existing pages to duplicate but in this case we will just create a new page from scratch once you're on the page okay as before because at the time i'm recording this the new responsive engine is still in beta i'll have to go in and upgrade the page to the new responsive engine not that that's making a whole bunch of difference for us right in this practice app because we're only dealing with a fixed width page right so our page is fixed with so this is our new create page and now i want to go back to my index page and i actually just want to bring this across one way that you could do this is actually by going right click and copy with workflows and what that's going to do is it's not only going to let us copy and paste this content but any workflows attached to that group so this add and slash edit uh product group are also going to be moved over so this is definitely going to break our our edit functionality but that's okay this is mainly for demonstration purposes so fully okay with that so i've copied with workflows that group and over here i'm going to paste with workflows okay so that's our add product page right there and as usual we should test that this is still working so if i just add sort of another lawnmower let's say it's a cheaper model and if i now add this just check in my database all products cool we've got another lawnmower so that form is still working what we also have is an issue that we've seen to have introduced so any time that you have any illogical statements in your application or anything that's kind of broken bubble will flag them to you so right here if i click on it it'll take us to the element in question it's saying that um we can't actually show this alert product created anymore because actually we're on the create page now and that alert we didn't copy over from the index page so i actually don't have the option here so i'll just fix that by coming over back to our index page and i'll grab that alert and i'll actually cut it so i'll control x on my keyboard come over to the create page paste it back in you can see it's a different width there that's because our index page is actually 1080 and the default width for our new create page is 960. so i'll just bump that up to 1080 again i don't want us to be dealing with responsiveness if this was responsive then we would make sure that no matter what the page size was that these things would appear appropriately but as i said we're going to deal with that in another video so there's our product up the top um and it looks like it's automatically reconnected itself right there so the alert has just gone away so that is awesome and then over on our index page we can actually delete this now and move this over here and now this edit button has actually had that workflow attached to it edited so that that action that was going to be displaying data in that form pop-up rather in that form group has now been removed so let's just let's just remove that edit button for now because that's not the functionality that we're that we're looking to build so now we have two pages in our application right um the logical thing that we want to do allow our users to do rather is to move between pages right so the most common user experience that we are all used to is having some kind of header right so i'm going to drag a group up here to act as my header and i'm going to just change the style to be a group border so it kind of sticks out a little bit and what we can do is we can have some buttons up here that navigate the user to particular page so we might have a button here in the right hand side which is called create a product right create a product and in this case what we want to happen is when this button is clicked we want to actually take the user from this index page and put them over onto the create page so i'm going to start edit workflow and an action and the action that we're actually looking for is under this navigation section so anytime we're dealing with moving the users around through multiple pages then we are talking about navigation and specifically this go to page action so this is going to let us choose where in fact we want to send the user to so i'll send them to the create page these pages by the way this reset password and this 404 page are default pages that bubble gives you out of the box resetting passwords is sort of bubble has some built-in functionality for doing that that includes this reset password page we're not going to go into that today but feel free to look up in the documentation how that works and this 404 page that's what will be displayed if your users try to go to a page that doesn't actually exist they will end up on the 404 page which maybe you've done in the past and your internet wanderings ended up on a 404 page and then you'll know what i'm talking about so anyway setting the destination to the create page we can ignore all of this this would become relevant if our page had a data type because pages themselves if i go to this create page and just double click here to open up the inspector on the page pages themselves can have a type of content so pages are just another container just like we've got groups and repeating groups and pop-ups and got a couple of others here that we haven't talked about today pages also act like containers for data in our case we don't because the create page doesn't have a type of data then we don't need to worry about the data that we are sending we're just moving the user from one page to the other so now if i go and preview this okay here is our header up on the top in fact i might just make it a different color just to stand out a little bit maybe a sort of a dark blue like that right now if i click create a product here we are on the create page so obviously we want to do sort of the equivalent right on the create page if i just extend my page height here a little bit make it 800 okay and then i'll drag this form down a little bit to give us some room and center it horizontally and now i could create a new header right i can go group and put a new header here and pretty quickly i'm feeling like this is a bit tedious actually because okay well let me make sure i've got to set it to be the same color same color and then i want to get the button and i want to get it probably in exactly the same place because i want to look i want to look exactly like this so isn't there a way maybe i could just copy this right i could just copy this over and let me see okay i've just copied it over um this is the creator product i'd probably want you know another button to take the user back to the main product page so i add a browse button but now my first header on the index page now this one is out of date i know i need to create a button here so what i'm trying to do here is set the scene for the need for what bubble calls reusable elements elements that you create in one place and then you can add them to multiple parts of your application so you're basically creating like a master template that you can then distribute throughout your application so back to our trusty little sketchboard for just a moment pretty simple concept reusable elements so over here we have our browse page which in our app is called the index page right and over here we have our create page now a reusable element is something that we're going to define as if it was a page okay so we could have over here our header which is a reusable element which we basically define as if it was a page so it exists independent of any particular page and now we can add this particular reusable element to any of our particular pages but we're not really putting the original reusable element we're just putting an instance of it okay it's as if this is sort of the master template so if i was to make changes to that master template like if i was to add a button here then those changes would propagate through to all of the instances of the reusable element okay so in that way we can just make changes and maintain one element in one place and have those changes be reflected throughout our entire application so that's all really a reusable element is super super powerful concept so how does it actually look well let's jump into the bubble editor and actually create one ourselves all right i'm going to delete this header that i just created and i'm going to come up to the page and add a new reusable element so the user element is going to be called a header and i'm going to create it from scratch here again just like for pages right we need to do this upgrading to the new responsive engine which you won't need to do if you're watching this after the new engine is out of beta okay so here is our basic layout for our header i want to make sure that we're dealing with fixed width again because i don't want to worry about responsiveness and i'm just going to make this the same size as our canvas and i probably only need to make this about let's call it 80 pixels high okay so this is our reusable element and like before i can change the color to be kind of like a dark blue and i'll add a button which is going to be create a product right and maybe i'll have a different type of button here see what bubble offers me okay that light one is probably cool we probably want to define our own button styles our own button looks but for now this is this is fine now if i go to my index page and i scroll down here there's the section called reusable elements and in fact you can see there's two headers and that's because bubble actually gives you a header out of the box so this is my header this one with the lower case which i should probably rename to to matt's header let's call it just so that we can differentiate but um yeah bubble just trying to help you out it already has some predefined header formatting for you this is how the bubble one looks so you know pretty nice right out of the box it does what kind of we need it to do but let's not get ahead of ourselves let's keep things slow and drag in our own header where we know kind of how it works so we've got that here on the index page and now we can go over to the create page delete this and add our header there as well and now if you look on our create page there is that header it's a reusable element so if i try to edit this right i can't i actually have to click edit element or come over to it in this page tree here open it up and now i can kind of change and edit this actual header so just take note here we've got this one button create a product if i control drag on this button to make a new one and call this browse okay and then i refresh my preview you can see that now the header has been updated here as well so these changes will propagate through to any instance of this reusable element anywhere that we've put it within our application so then we can attach our actual uh workflows to these buttons right so we've got a navigation action here which is going to say go to page we'll go to the index page in this case for the browse button and for our create a product we're going to go to the create page the create page and this is now going to let us have this way for our users to navigate from one page to the other so we're on the create page let's go to the browse page we're on the browse page let's go to the create a product page so there you go there is reusable elements in nutshell pretty simple concept but very very powerful wherever you can you want to be building in reusable elements you want to be building things in a modular way that's going to keep your application really clean and really what we would call maintainable so it's going to be easy for you to make changes later on because there isn't this kind of convoluted spiderweb of logic you've created like this module that stands apart independent of everything else right i can define a header define all the logic for the header within this run reusable element that i know works and then put that kind of all around my application so i can kind of siphon that off as like a self-contained unit of logic so to speak that i know it is working all right now i've avoided talking about users up until this point but this is the right time to introduce them because users are such essential concept for every application that you're going to use virtually i mean you there might be some applications that you're building where you don't have your users interact at all it's just some back-end um tool that you are using but nonetheless they're sort of unavoidable in the bubble universe and most of your applications are going to have some kind of user interactivity so that's why bubble has them existing out of the box so you have this user data type here and one really cool thing about users is that any other data object that's created in your database is going to have this created by field here and that created by field is going to be populated by whatever user was logged into your application at the time that that product was created so at long last let's actually kind of get into the meat of this okay we want to have in our header okay i'm not going to use the bubble predefined header because it's kind of cheating we want to have kind of like a login button so i'm going to i'm going to drag these move these buttons over a little bit and maybe make this one a different color okay and call this sign up or log in okay this is where we would typically want to display after clicking this button display a sign up form or a login form to the user and this is something that bubble actually gives us out of the box as well we've got the sign up login pop up here got a bunch of handy logic kind of built in now you may have noticed it exists as a reusable element right the sign up login pop-up is a reusable element and i'm still in the header here i'm installing my reusable header so i've just copied one reusable element inside of another visible element and that's something that you can do too you can nest reusable elements inside of one another in our particular case we're probably not going to do something like this on our index page and put this sign up login pop-up actually on this page right and then trigger it from the page right so i've got another sign up login button here which if i go down to element actions and then show i'm showing that new signup login pop-up boom just like that so i could do that right but it obviously in this particular case doesn't make a lot of sense to do that because well one that sunup login button should live in the header and also the fact that it lives in the header will allow us to launch the signup log and pop up from multiple pages potentially that's some a user experience that you might want to have in your app we actually want to nest the sign up login reusable element inside of the header reusable element and that means that we can always just trigger the signup login reusable from within the header we don't have to trigger it independently from the pages themselves so i'm going to remove that right and so what i want to do here is just create that exact same workflow so i'm clicking the sign up login button what we want to do is create an event create an action rather that shows that sign up login pop-up just like that and so what i want us to quickly do is just actually recreate the functionality of this sign up login pop-up just so we can actually see how it functions okay so if i remove this signup login pop up completely and i just create a new pop-up on this page we're just going to create it as a normal pop-up right now not as a reusable element okay and i want to make sure it's set to be fixed width that's great i might just extend the height a little bit and let's just create two groups here okay one group is going to be for where the user can sign up and the other group is going to be for where the user can log in okay so the inputs are slightly different so this group over here i'm going to do this in the most simple way possible this group over here is going to be our group sign up okay and that means we might want to add some text to it right that just says sign up and give it some header formatting okay and i'm not going to worry about labels right now we're just going to use the placeholder text as our labels so we'll have an email input okay input email where i'll actually set the content format here to be email and what that's going to mean is that we're actually not going to let our users enter anything into this input that isn't formatted like an email address okay it'll come up as invalid all right so there's our email input and now i'm going to control drag to grab a password input and in fact i might just center these both center all of these rather horizontally and so this is going to be our input password and the placeholder is going to be password and we can actually format this to be a password as well which is going to mean that when the user types something in then it's not going to show the user what they're typing right just like you'd expect a normal password input it's just going to be a whole bunch of asterisk signs one after the other so you'll see how that works in a moment and then we'll have a button here which is going to be our sign up button when this button is clicked this is kind of where the magic needs to happen so i'm going to go start edit workflow and since we're dealing with users now user logic we're going to come over to the account page and choose this first section here sign the user up so what this is going to do is it's going to create a new user object in our database right just like how we were creating products before right we had a product straight box that we were putting onto the shelf and putting some values into it same thing here but for user objects we go through this action here because users are a a special kind of data type within bubble with some special kind of features that only apply to users and you can see what those features are under here right we have you know you can log users in and out update their credentials so their password you can send them password reset emails send a magic login link and it's good that bubble handles all of this stuff because you know a lot of the stuff is security sensitive password handling is is a topic that we wouldn't really be able to handle ourselves in terms of the encryption of the passwords and this kind of thing so it's very good that bubble kind of takes care of that stuff for us and then just exposes the sort of one action that lets us change a user's password or logs a user in with a password so um so we've got the sign the user up action and here we would just point these fields to the inputs where the user is entering in these values right just like when we were creating the product so input emails value and this one will be our input passwords value and actually i've missed about password here so i'm going to right click shortcut tip here right click on this input here the expression and click reveal the element that's going to take me right to it in the editor and i can just change the name there so signing the user up we're not going to require a password confirmation okay that would mean we're going to have another password input okay so the user has to type the password into the first input and then type exactly the same password into the second input i'm sure you're all familiar with that kind of feature we're going to keep it simple and we're not going to check remember the email either so if you're unsure about what any other stuff does if you just hover over a lot of things in bubble you have this sort of c reference okay so we can click on that and kind of say okay what does this mean to remember the email and it's telling us that if we set that to be true the user's browser will remember the email that they last entered when they went to sign up um or log in so that means if a user logged out and then logged back in their email address would already be pre-populated so but we're not worried about that in this case either so we're going to sign the user up and then the last thing that we might want to do is actually just hide that pop-up right the user's logged in now if i start typing up here then i can filter the elements on my page i'm gonna hide that pop-up which is called pop-up a at the moment we should probably call it pop-up sign up and log in let's just do this for now okay we've got some extra space down the bottom which i'm going to use for our login group functionality and then we're going to kind of show and hide these groups depending on what the user wants to do but let's just test whether this functionality itself works all right i'm trying to click this button and nothing's happening so i can go step by step and try to see okay what what is meant to happen here and doesn't look like i've got any action assigned so thank you debugger another good reason why we would use the debugger in this case so what i actually have to attach here is an action to show that sign up login pop-up that we created so element actions show that pop-up signup login okay there we are and so i'm going to enter my email address here a helpful tip if you want to you know you're testing login or sign up functionality or any kind of functionality really with a lot of different test user accounts you can keep using your own email which means that some random bugger on the internet isn't going to get your test emails and but also means that you can continue to receive them in your email box it's just by putting a plus and then putting kind of some value after the end which might just be you know test it might be a number it might be kind of today's date in some way whatever kind of makes sense for you at least in the case of gmail it will ignore everything after this plus sign this email address will still get routed to my email matineri.com but in bubble bubble will see this entire email address so it will pick up different users even though all of those users emails will still be routed to your real email address so i'll do that here okay and now we'll type some password in here and have the user sign up now the user apparently has signed up at this stage what we could do is kind of give some indicator in the header to show when the user is signed up okay so maybe what we want to do right just a really simple thing is just add some text up here and we'll make sure that it's light texture it shows up and we can say logged in as okay and then we can add i might actually make this even smaller logged in as and then insert dynamic data and we want to choose this option here current user so that will return whatever user is logged into the application at this moment so the current user and then we can grab any one of these fields from them and what we're going to do is grab the email because of course the email is a default field that we have for all users if you go into the database and click on the user you can see that this email field is what bubble is calling a built-in field so it's default it comes out of the box every user is always going to have an email now if we refresh this page you can see voila i am in fact logged in so that's awesome so kind of the next logical step here okay we're still seeing the signup logger and we want to have our users be able to log back into the application but it might make more sense for us to let our users log out and then we can kind of test that log in functionality after that so what we could do here right if i just use hold down control and select both of these guys okay and then hold down control and drag this button here and make it a bit smaller i could make this a log out button and then i could attach my logout action to this button so that's again under the account settings we've got this action called log the user out okay so that's again some bubble built-in functionality but that's not a very clean user experience of course to have one button for sign up and logging in and another button for logging out kind of makes sense that when the user isn't logged in they see this button signup login and when they are logged in then they see this button this logout and so what we could do here is use what is called a conditional statement right which is just like we were doing with our workflows when we were defining an only when statement here we can define these statements at the element level as well okay so the element will actually be sort of constantly asking itself the question is this true is this true is this true is this true and anytime that it is true it'll take subsequent actions so let's kind of see how that would work if we come over to the sign up login this is where we want our kind of first condition to live i have the option here to go to this conditional tab and this is where you define all of those rules and you can see this this button already has one it has a this button is hovered condition and if we go to our preview you can see in fact it does have a slight hover behavior you know when i'm hovering over it's going dark and that's actually a condition that's built into the style settings for this button right the style here this primary button style if i was to select off of this then that condition becomes visible for us so you can see that this is how it's defined okay we've got sort of an expression up here that says when this button is hovered and then a series of button commands essentially telling this button what to do should this condition be true and we actually want to keep all that stuff okay so i'm actually going to put us back on that primary button settings and then we're going to define our new condition here so i think what the easiest thing to do in these kind of situations where you have two different elements and you essentially want them to be visible or invisible based on some condition is to just make them both invisible by default and then to find the condition that makes them visible so the first step that we want to do here is come over to this layout section and click the element is visible on page load so we want to untick that okay and that means that when the page is actually loaded this element will not be visible at all and that's a great starting point because now we can just define a condition to tell the button when it should be visible and that's sort of a nice way of keeping behavior consistent when you have this kind of conditional show hide functionality it's just set things to be invisible by default and if you know that you've done that everywhere in your application then you know you only have to look in the conditional tab to see in what condition should it be visible so just the best practice there all right so here's where we're going to define that condition i'm going to click this button here the question that we want to ask here if we just think sort of taking a step back that's a good habit and we'll just take a step back and just and just ask yourself in plain english or whatever your native language is what do i actually want this logic to do so this button is invisible by default and we want it to be visible only when the user is logged out only when the user is not logged in do we want to show this button let's see if bubble exposes an expression that captures that i'll click here to start writing this expression and what we want to do is choose current user so that's sort of the start of this expression what is the object what is the thing that we're evaluating here and thankfully for us bubble offers this is logged out expression okay so anytime that that's true then we can set a number of properties on this button and the first one that we want to choose is if this element is visible so since our user's logged in at the moment we're not kind of seeing this behavior but we do still have our logged out action attached here log the user out so i'm just going to click that to log the user out and then in theory that signup login button should become visible there it is now it is visible and if we inspect any of these elements okay it'll actually show us the conditions as well and they'll be highlighted green whenever they are true okay so the current user is logged out so conditional behavior is super powerful you'll be using this all the time in your bubble development so we do also want to have sort of an equivalent action here on this log out button so what if i actually drag it over the top of the other button okay so they're kind of taking up the same space on the pages we're giving it the illusion of it being a single button when in fact it is two separate buttons and we could actually set this up to be a single button okay we could actually set this up using some conditional workflows right to say you know if the user's logged in then trigger this logout action and otherwise trigger the the logged in action um but you know we'll keep things simple right now and we'll just have two separate buttons here so we want to do exactly the same thing here on this button logged out we'll tick this element is visible on page load no okay so the default behavior when the page is loaded is for this to be visible and then we want to when the current user is logged in right because we're talking from the log out buttons point of view now then we want to set this element to be visible and if i click the sign up login button now and let's just say i sign up as a different user so test number two right and sign up now a logout button is appearing and if i click that to log out now i'm logged out and that signup login button is appearing okay so we've got that basic um infrastructure here set up within our header but we still have some work to do in our pop-up sign up because at the moment we're only letting users sign up we also want to let them log in so i want to set this up the same way as this default bubble sign up more or less because it deals with something called custom states which can be a little bit of a confusing concept um in the beginning um but it's worth introducing them early on and just getting getting familiar with them because there's not that much to them and you will encounter them you will use them within your bubble development so this is a great place to introduce them so what i'm going to do is i'm just going to copy this group here the sign up group and i'm going to make this group my login group okay and you might be wondering well why on earth are you doing that like you're not going to have two forms one above the other right like that looks ridiculous um and you'd be right that would look ridiculous what we actually want to do here is when one of these groups isn't visible okay then it actually collapses so from the user's point of view we're only going to see one of these groups at a time okay because the other one is going to disappear and because it's collapsed okay the size of this pop-up is going to shrink to accommodate the group that is still visible and so for that to work we are going to just touch just tinker around the edges of the responsive engine i want this pop-up to not be a fix layer okay i actually want it to be a column and a column layout in bubble is going to force any elements inside of it to be stacked on top of one another here's our column layout here right column container right if we wanted to add a group into here which we have done we've got two groups here they would automatically as they have been here kind of be stacked this is group a this is group b they'll automatically be stacked one on top of the other you can't kind of move them around in the way that we were seeing in the in the previous parts of this video whenever you're using uh a container like column or like the one other ones that we're not going to talk about today aligned to karen and roe then any elements that are inside of a container with that setting are going to have their position automatically set depending on that container type so in a column scenario it's one above the other i don't actually want this to be a responsive tutorial because there's a lot more to kind of discuss here around how this engine this responsive engine is actually behaving so even though i've set the layout here to be a container i've actually still got a fixed width and a fixed height okay so that's why we've still got this the space here on the right hand side the only thing that i might do is if i go into each one of these groups i can set the alignment of this group relative to the parent group right so i'm going to set this guy to actually be in the middle and set this guy to also be in the middle okay with that little responsive setup out of the way now what we do have on both of these groups if we click on them is this option here collapse when hidden okay and that's going to let us do what i was discussing before where we actually collapse the height of that group if we collapse the height of this group here right if if group a is visible then basically group b will move up okay group b will move up and the rest of this container will move with it so only thing that we're sort of missing here is the ability to kind of switch between both of these groups right depending on what the user wants to do so what we could do i'm going to just extend the height of this pop-up just by maybe 60 pixels and i'm going to have a button here a button which i'm going to make a different kind of look and i'm going to make this my button we'll call it switch and how this works is going to work is if the user is currently seeing the sign up form but they want to log in then they're going to click this button to see the login form instead okay so that's just basically exactly the same as the default signup login pop-up over here that bubble has created works okay so that's what we're creating here so on our pop-up all right first thing i might want to do is make this horizontally aligned okay so what we basically need here is like a rule that basically says like if the user is in sign up mode okay and they click this button then switch them to log in mode and we also want the inverse condition if they're in login mode but they want to go to sign up mode okay then this button will switch them into sign up mode okay and a common way that this is done is using something called custom states so i actually just want to pull up a new test page here okay just to demonstrate this in kind of isolation so that you get the picture a custom state is nothing more than another container right that's actually what it is like we've got a group here right and that is a container and a container holds a type of value a custom state is exactly the same okay i could define a custom state on this group right by clicking here and going add a new custom state and that custom state i would set to be let's say mode and then i would set it to be a particular value so it's sort of a container that lives on a container okay so if this is in this example here this is our group a you can think of the custom state as almost like a meta container like it's not visible on the page it's just a hidden container to hold some value okay and that can be really useful for a whole variety of different purposes one of which is just holding some information such as okay which mode should the signup login form be in right now should it be in the sign up mode or should it be in the login mode okay and then depending on what that mode is okay other elements on the page can react okay it's almost like it's a traffic light okay so let's sort of just like demonstrate that so i'm gonna delete this group and i'm gonna set the custom state here on the page level okay so you can do that you can set a custom state on any element okay but to keep things organized a good practice is to do it at the page level so you can find them easier later and i'm going to call this mode okay and we're going to make it a text value okay and we can also set a default value here for the mode i'm going to get back to that in a second now all i want to do here i'm going to drag two shapes out onto the page let's call it a shape green and we'll give it a green color and i'm going to do a shape red okay traffic light colors here okay now i want both of these guys to not be visible on page load right just as before but i want to set some condition that's going to say whether or not they should be visible okay so that condition okay is going to be looking to the custom state so if we just ignore this for a second okay we've got a custom state here okay we're going to have a custom state here living on the page and that custom state is either going to be green or it's going to be red okay depending on what it is if it's red then we want the red shape to appear if it's green then we want the green shape to appear that simple okay so the element right the equivalent of these groups here are looking to the custom state right they're looking to the custom state to know what they should do and so in this case right the cast state is green so the red one's going to disappear however if that changes to red then the green one is going to disappear okay so these shapes as before like any condition they're constantly asking themselves the question in this case what is the customs date value what is the customs date value what is the customer's data so they're asking themselves that over and over and over again and anytime it's going to change then their behavior is going to change okay so in practice that means setting a condition here which to get to the customer state we're first going to select the page okay so the page name is custom state okay in fact i'll just name it to be custom state page so it's super super clear so we're first going custom state page and now we have access to this mode option okay so that is referring to the custom state living on the page okay so the pages mode right when the pages mode when the value in that mode custom state right the custom state that we've called mode when that is equal to green okay then this element is visible and we'll have the inverse over here okay so just as a little shortcut what i'm going to do is i'm going to right click and copy this expression come over to the red guy and paste it okay and what i can actually do that's one little shortcut what i can also do is just copy the entire condition right so very very um quick way of of of changing these things and then i'll just change this to be red what i need now is a way to change the state of the page itself right so change whether or not it's going to be green or red and so i might have a button here which says red and another button over here which says green okay and this is where i actually need to set the action which changes the custom state so when button green is clicked we want to because we're dealing with an element here right the page is in a way just another element we're going to set the state so change the value inside of our custom state so the element that we want to change is the custom state page and then custom state itself right because you can have multiple custom states on an element in this case we've only got one called mode and now it's saying okay what do you want the value to be called what do you want the value to be set to so we want it to be green and then we create an equivalent for red so i'm going to copy this workflow and paste it and now i'm just going to change this to be button red okay so the element that's clicked to launch this workflow button red and then the value here is going to be red okay so let's test that out in action okay so at the moment there's no value right when the page is loaded there's no default value in that custom state you can't have one but we didn't set one okay and let's do this step by step if i click green we're going to set the state which is called mode the custom state mode to be set to green and there's the green one visible if we choose red now the red one's visible so green red green red now maybe you're asking yourself well why did you not just use a a show action right just like show that shape green in this case it's a good question um the answer is that it is a very hard to maintain way of doing this because every time that you show the shape green okay you also need to hide the shape red okay so there's now two actions where before there was just one and plus these shapes might be not the only elements that need to react to the custom state for example we've got two buttons here right but we could just as easily have one and we could have similar kind of condition here you know it essentially says when the custom state pages mode is equal to one of those values right is equal to green right maybe we just maybe we just actually set this set it to red and then if i copy this condition and paste it then we would do an opposite one for red okay now we have this button switch okay reacting to the custom state it's looking to the custom state to decide what to do based on some conditional statements but also these shapes are and we can't change the color of a button like this using workflows we can't do it so we're forced to use these conditional tabs which are reactive by nature okay they're always looking to see if some condition is true to decide what they should do and so that's where the value of a custom state comes in it's holding some temporary value okay which is um usually going to be used well is often used to tell other elements on the page what to do but you could also use it for all kinds of different things you could have a product shaped custom state that holds a product um temporarily right maybe it's just like you know in in a card in the in the header so you're saving that as a custom state the important thing about custom states by the way is that when the user refreshes the page they're lost just like any other value that's on the page right we're not storing stuff in the database it's just stored locally so a page refresh will will undo it so if i just preview this so by default we actually don't have a value here um i hope you're following along so far um this page as it is set up right now is actually broken because i deleted one of those buttons earlier remember i had two buttons up here and now i've only got one button and that one button that's remaining was the button that was setting the custom state to be red so we actually want this button to be dual purpose right so if the custom state is green then what the action that we want to fire is changing it to red and if it's red then the action that we want to fire is setting it to green okay so another only when condition is necessary here now i'm going to set this up what might be to you the intuitive way first off the bat at least it was for me and then you're gonna see why that way actually doesn't work so first thing that you think you might want to do okay button switch is clicked okay we only want this action to fire right if the value of that custom state is green okay so we could say only when custom state page right to access this custom state again when the mode is green then we set that value to be read and then if i copy this expression okay then we basically just create the inverse here right green only when it's red and at the moment none of these will fire if we reload the page here okay and click this nothing happens and that's because there's no default custom state set at the moment at the moment the custom state for the page this mode custom state is empty it doesn't have any value so that's why this is evaluating to false okay because the mode of the custom state page is empty and the same for the next one so to resolve that we can set a default custom state so i'm double clicking to open up the inspector at the page level and then i'm going to set the default value to be green and that should resolve this right so now it's green and so now if we click red hmm nothing is happening so this is a good time to check out our debugger maybe our by using the debugger we can figure out what's going on so i'm going to go into step by step mode and just see okay exactly where is this workflow breaking down so i'm clicking on red okay and okay since we are in the green mode right the mode is green we're going to set the custom state to be red that's what this first action is doing okay so that's all good that's working and then in the next action we're asking if the value is red then set it back to green so you can see what's happening there is we're just going from one state quickly to the other one um this first action is setting it to be red and then the second action is setting it back to be green and so when you look at this in real time it looks like nothing's happening so how do we resolve this well we don't want to have two actions back to back like this because actions as i said before they cascade so one fires and then the next fires and then the next fires and we don't want that we basically want when the button is clicked at that point we want it to ask itself like is it green in that case launch this workflow and if it's red then launch this workflow so those are those are two kind of independent branches of logic so to speak we actually want two events here and anytime that you have two events they'll both fire if a button is clicked if i copy this right and paste this okay anytime that the button is clicked both of these events will fire so we want one of these to be the equivalent of the red okay so i'm gonna cut this and paste it well i can just delete this over here okay so one of these is saying set the value to be green and one of these is saying set the value to be red okay so so far so good okay so now we've got so we've got two separate events okay and we've got an only win action in each okay but this is still going to lead to an issue and maybe you can kind of have a guess as to why let's debug this and one way that we can do this a little bit more easily is actually rename our events it's going to help us keep track of what's happening in the debugger so um so this action here is setting the value to be red so we want to call this event switch to red and then logic states that this one which is set in the value to be green we should call set to be green so all i'm doing there is clicking up the top of the event and then just typing in something new okay so that's going to help us keep track of what's happening if we go step by step in the debugger so let's do that step by step i'm going to click there okay so this switch to red event is now firing so this guy over here and if we go right next what it's doing okay it's looking is the custom state green okay which it is in that case switch to red okay and now the next event is firing this guy okay so both of these events are set to trigger when the button is clicked and they're just going to happen one after the other which was kind of the problem that we had before right when we had actions so you can probably guess what's going to happen here this is evaluating to see whether the state is red which it is because we just changed it to red in the previous workflow um so now we're just jumping straight back so this is not working the way that we've set this up to get this to actually work we don't want to have the only when conditions here on the action level we want them to happen on the event level so we're actually going to sort of stem the flow right at the beginning essentially means is that rather than this event firing and then checking if this is true and then this event firing and checking if this is true only one of these events is going to fire because only one of them is going to be true so what i mean by that is if i copy this expression here i'm actually going to clear it out and put it up at the event level so here i've got the event selected rather than the action the event selected and then i paste it in okay this event will only fire at all if this condition is true okay otherwise this will not happen and same thing over here i'm going to copy this right click and then clear it and then paste that expression at the event level you can see now that only one of these conditions is actually going to fire at a time it's either going to be red or it's going to be green at any at any particular time so in practice right if i click this now switch to green this guy is the action that we're firing now okay that's only gonna fire if the custom state is red which it's not at this moment the custom state is green okay so we're going to skip past this event and we're going to go to the next one that next event right this one here is then asking okay is the custom state green which it is in that case you're gonna set the value to be red so that looks like the behavior that we want and it's gonna work in the reverse as well okay so we're asking that switch to red condition now okay so this is something that bubbles kind of doing intelligently as it's changing which order of things to do these events in it's choosing the one that's going to be false first so that we don't have the same problem that we had before so now that switch to red action is being asked and it's false so then we're moving over to the switch to green action which is evaluating to true in which case we switch back to green so now this behavior is kind of working hopefully that kind of gets your head around the concept of using custom states as kind of like a routing mechanism here you could just as easily instead of using a custom state you could use a group okay you could use a group as the container for this temporary value so you could have the type of content you could have group mode instead right and as the type of content choose a text and here you would define what the default is so you would it would be green now you point everything to this group rather than the custom state so over here where you have these conditions instead of custom states mode is green you would go group modes text is green okay and you would do that for all of these you would you would change this to refer to group mode and then all of your conditions would be looking at group mode as well and so that would work exactly the same way the only value of doing it in a custom state is that it's kind of hidden okay this group here you have to decide kind of what to do with it often people will put this in a pop-up to kind of hide it if they're doing it this way and custom states do have some other benefits as well in terms of passing data between reusable elements and pages but that's a little bit more advanced we're not going to kind of get into that today so hopefully based off of this you have an idea conceptually of what's going on that we can now apply to our sign up login pop-up right so if we go back to our header element and our pop-up signup login okay now we can just apply exactly the same logic structure that we were doing on that test traffic light page to this right we want to set a custom state that's going to define whether or not either this sign up group should be visible or this login group is visible okay so let's take this one step at a time let's first deal with the setting of the custom state and then let's deal with the elements that are going to react to whatever the value of that custom state actually is so first let's actually define the custom state all right which makes sense to do that in the pop-up okay you could also do it at the header level because we're dealing with behavior that's only happening within the pop-up it's logical to also do it at the pop-up level so that custom state we can just call it mode again and make it a text value and the default value let's make that sign up and then let's actually configure this button to start with okay and then we can at least make sure that we're setting the custom state appropriately so when that button switch is clicked okay we actually want two versions of this so i'll set up one first and then make a copy of it to do the inverse so when that button switch is clicked okay let's make this our login logic so we only want this to fire when the mode is equal to sign up right because we want this to actually switch it to the login mode so the inverse of sign up and then we'll add an action here which sets the custom state of that pop-up right which sets that mode custom state to be login right and we'll rename this as well so that it's clear what the action is actually doing and then i'll just make a copy of this i'll make a copy of this event okay and this one will be switch to sign up and here we just want it to do exactly the inverse so set this to be login okay and set the value here to be sign up right so in this case only when the value is login then we want it to do the inverse which is set the state to be sign up so without dealing with um what's gonna happen um when this button is clicked we can at least just see kind of if it's working so first things first let's inspect the pop-up and just see okay what's the custom state right now and it's sign up okay so that makes sense that it's sign up because that's the default value remember at the pop-up level we defined this default value to be sign up okay so that's working so we can at least tick that off now if we go step by step and we switch modes okay well the mode is not login okay so this event is not going to fire it is sign up so this event is going to fire and what that event is doing is setting the value to be login so now if we were to inspect the pop-up again we should see there we go that the value of that custom state is login and if we were to click this again then we should see that it is back to sign up okay so we can tick that kind of bit off of setting the custom state okay we know that functionality is working this is a good practices build things in a modular way right so this part of the feature is working now we can move on to the next part which is actually getting these groups to react to whatever the custom state actually is okay so we'll start with the sign up group here first right so let's define the condition to start with so this condition is basically saying it's the equivalent of the traffic light system right like when the value is green then show me okay in this case when the value is sign up then show me the custom state that we're looking for is of course living on the pop-up right so when the pop-ups mode is equal to sign up right then show me then this element is visible okay and if we copy this condition and go over to our login group we can just paste it and then quickly change things to be the inverse right login is what we're after and then we can just test this too right testing things in a modular way we don't always have to set things up kind of in a complicated way okay now both of these elements are visible by default at the moment okay so we want to change that to begin with so on both of these i want to untick this element as visible on page load so that will at least let us see if they're basically reacting to the to the state so at the moment the signup form is is visible and that makes sense right because the default value as we showed before of this custom state in the pop-up is sign up and then if we go to switch modes voila we're seeing log in okay so that's working perfectly the only thing of course is that we want this pop-up to kind of contract to the size of these groups here so to do that if we come back over here we actually want to tick collapse when hidden okay on both of these collapse when hidden okay for this to work there's kind of one last step that we need to do because at the moment if we just if we preview the page again you'll see that yeah it's collapsed right they're both appearing in the same place at the top but we've got all this extra space down the bottom and all that extra space is there because of the size of this pop-up that we created but also because we've got a minimum height value here set i said that earlier for kind of like ease of teaching this but we actually don't want to have a minimum height here okay that's basically saying like this pop-up can be 660 pixels or higher but it cannot be less than 660 pixels so at the moment this is 660 pixels high so this is as far into the responsive design as we're gonna as we're gonna go i'm actually gonna set this to be zero and so in our editor here okay we're seeing a completely collapsed signup form but don't fret okay in reality that's not going to be the case when we preview because we're always going to have a custom state here so here we go the up form is visible it's asking us to switch modes which we can do and we could get a little bit fancy here as well we could get some more space below this switch mode i'm not going to get into that in this video because we're going to get too deep into responsive design in that case the one thing that we don't have set up here okay we've got a sign up button that's signing the user up but we haven't configured our login button okay so i'm because i can't see these groups anymore i'm actually going to use the elements tree to find them so group login button sign up in fact it's not a button sign up anymore it's a button login [Music] log in and now we can create a new workflow here to kind of finish off this whole process the action that you want predictably is under account and it is to log the user in okay and now we want to choose what input we want to point this towards and as earlier we've got duplicates here and that's because we copied the form but we didn't change the labels change the names of the inputs within those forms right so if we go back to our group login here we want to probably call this input email login and input password login and then we can do the inverse on group signup input email sign up and input password sign up so that we can keep track of what we're doing with these inputs a lot easier okay so now we'll set this to be input email login right which we know is the input living on the login section right so if i just untick this for a second right it's the this input here and this input here okay not the equivalent inputs in the sign up form so i'll just undo this so that it's collapsed again and then the password is going to be the input password login value now stay logged in again that's something that we can have a look at the reference and see what does it actually mean stay logged in and bubble is telling us that's going to keep the user logged in after 24 hours so if that's not if we set that to be no then if the user's still logged in they've logged into the app and then they've gone away or they've closed their browser or whatever and 24 hours have passed then the app will automatically log them out unless this value is set to to yes so now we should be able to switch modes and we should be able to log in right using one of those emails that we already created and there we go now we're logged in as that user that we created before and of course we could do some other things here right like we haven't hidden the pop-up here so we'd probably want to we probably want to hide this pop-up sign up login and we probably also want to reset the inputs okay but i think you get the picture right that's kind of how this works so if i log this out again there we are now we're kind of getting some nice user behavior so all of what we just kind of set up is more or less the functionality that comes in this default signup login pop-up there's some more stuff here which you can dig into like having a forgot password functionality but that basic functionality about switching between the sign up view and the login view that is exactly how the the bubble default form works so now you can go off and you can create your very own sign up form um based on that same logic all right so there's one last feature that i want us to create here and that is the ability for our users to favorite or to like certain products which then add them to a sort of a separate list a favorite products list that's going to allow us to demonstrate absolutely fundamental part of bubble which is linking data objects okay so we want to create a link between users and products in some way now right off of the bat i want to draw your attention to our app data here where you can see that all of these products that we created before have a created by field equal to that matte plus test user if you remember we weren't actually logged in when we created all of these these products but what bubble does is any time and i mentioned this earlier any time that a object is created in the database okay this created by a field is populated with whatever user was logged in at that time now in our case we didn't have any users at the time that where these products were created but what bubble was doing behind the scenes was remembering okay that all of these were created with my browser and then the first time that i logged in as a user with this browser okay it automatically made this attribution it just guessed that hey you weren't logged in before but you created all these products now that you've logged in i'm just going to assume that it's the same user and if you're interested you can actually turn off that functionality by disabling how bubble handles cookies browser cookies so look that up in the in the reference but that's essentially why that's the explanation as to why we have a creative buy field here if i was to log out and log in as our other user our test 2 and if i was to create a new product here right and then we were to look in the database okay you could see actually so this latest product here was created by a different user so that's how that created by field works it's automatically populated by bubble so that's sort of our first data connection it's built in by bubble but it creates a connection between one data object the user and another data object the product okay and that can be really really useful okay because then we could do things like if i had another repeating group over here okay and this was a repeating group of products okay i could do something like doing a search right again just doing a search for all the products but now i can add a search constraint so a filter on that list that's only going to return some entries so one of the constraints that i could put on here would be that the created by the field that corresponds to a user is equal to the current user all right and now i'm only going to see if i just add a text here that's it and make that the current sales product's name so we can actually see what's going on and if i go into the browse page you can see that that second repeating group only has one entry and that is the one that i just created there's only one product created by the current user so it's appearing over here but we can also create our own connections between data types okay not just by relying on the default created by field we could create a connection between products and carts or products and courier companies right or products and categories or products and all kinds of different things this is not going to be a deep dive into different types of data structures but just want to get you kind of familiar with the idea that we can do this in our case we're going to just we're going to stick with users and products but we're going to create a different data connection between them right to allow this kind of favorite products list okay so how this is going to actually have to kind of work so we've got a user here right that's the common rendition of a user and they've got some fields right like well they've got an email field okay that's kind of like a default field that they have but we also want them to have which is equal to you know some value but we also want them to have and i'm going to use the uk spelling here sorry guys a favorited products field how this data connection works is you remember that we have a shelf of products in our database right a table of products okay so one of these might be the headphones that we just created another one might be the shoes um the t-shirt all that kind of stuff okay and we essentially want them all to be stored the ones that our user has favorited right let's say they favorited the headphones and they favorited the t-shirt and they favorited the shoes we want them to be saved to the user okay in some way and then we can actually kind of access them later via the user now what we're not doing is we're not actually literally storing the products in the user data type okay like they still exist on their shelf all we're doing is creating a reference okay we've got a list of favorite products here okay which all these really are are addresses it's saying you know i want you to your favorite of that one and your favorite maybe that one right and i should really do this in another color and maybe you've favorited that one okay and so these are addresses it's basically where is it on the shelf like if you you know you go to the library and there's like a code system and dewey decimal system and it's telling you like this book is in this part of the library it's on this shelf you know and it's this far down and it's sort of roughly this far across it's the same thing here it's just an address it's basically saying that it's on shelf a in the position 4 or something like that behind the scenes what's really happening is we're actually storing the unique identifier for each of these products which is kind of you know without going too deeply into that every single object that's created in your database has a unique id created by bubble okay so this is sort of the equivalent of that address this is how you can create a connection between a user and a product is by storing the unique id of the product on the user and in that way okay you can always find that product later on based on its unique id okay because then you know where in the database to look right on which shelf you should go to find that particular product the key kind of takeaway here is that these products exist independently in the database right right here's our users they're on their user shelf the products is just on their product shelf but for any particular object like for any particular user okay they might store references to other objects that let us find those objects later on so in the case of our product what we also have if i just cut this over here we also have a created by field right which we've got our users over here okay it's not literally storing a user over here okay it's storing a reference to a user it's storing this long kind of string that's saying this is the user that created me so if you want to find that user then just look them up on their shelf okay look them up by that unique id how do we actually set this up in bubble right well let's get into it so we first need to make changes to our data structure to accommodate this okay so on our user data type we need to create this field here this favorited products field okay so i'll create a new field and we'll call it favorite products and the type here is going to be of type product okay but it's not a single product if it was just one single product okay then this is what we would do if the user could only select one product to be their favorite then we would just leave it like this but we actually want to store a list of products right it's multiple products it's multiple ids here right multiple of these guys and so that's why we have to tick this field is a list and then we can create that and now it's just a matter of creating some logic in our bubble application that's going to take certain products and store them on the user or technically speaking store the reference or the address of those products on the user so just before we do this i want to store the email address of the user who created this product in this repeating group and we can ostensibly say that that's so that other users can contact them about the products that they're selling so i want to insert dynamic data here what i want to do is because i've got i've got a current cell that's a product okay i'm kind of i'm grabbing the derivative fields from that product what i basically want to do is i want to open up the product this product here and then i want to pull out this created by field to grab the user so i'm going to go current cells product creator so just like i was choosing the name and the photo and stuff before i can also choose the creator and that's returning an entire user okay at this point i've got an entire user that i'm dealing with in this expression so this whole thing here but of course i can't expose an entire user through a text element because a user just like any object in your database is it just a collection of fields right it's a package of data in different formats text format image format number format whatever okay so now i need to choose okay which of these fields on the user do i actually want to propagate through this text element and so i can choose the email like that okay and since it's not appearing i'm kind of curious as to why so i'm clicking on my text element here current sales product created by is empty okay it's empty if we come over here to the creator we're getting a hint here so this is something you're going to bump up to in the beginning so we need to call it out and that's privacy rules so a quick note about privacy rules here's some products in your database here's your app okay so this is database again if you remember this diagram so inside of our database we have all kinds of different data like these products and what our application is essentially doing is asking the database to send data back to it right our application doesn't have any memory that's where the database comes in so this kind of expression of grabbing you know this repeating group of products what that's essentially doing is the application asking the database okay to return a certain amount of products right to return these guys so they all come running on their merry way and then are displayed out to the user in the application the problem with this approach when a object is returned like a single product like this all of the fields on this product are also returned all of them and that might cause a security issue okay because you may not want all of these fields to be exposed to the user with just a little bit of programming skill okay you can access all of these fields even if you're not actually displaying them in your application you can go into the in the inspect tab of your browser and you can pull out all of the fields that i returned here and so that we need to deal with privacy rules because privacy rules are going to restrict sensitive data from being returned okay so let's say that we were sending this product we didn't want to send the uh the price let's say that was sensitive information we could have a privacy rule that says unless the user is say the creator of this product then send everything to the application send all of this except the price so essentially acts like a filter at this point where price in this case would be left behind but name image you know and the created by field those would all be returned on the other side so in a nutshell really short consideration of this topic that's what privacy rules are doing and it's important that we deal with them because out of the box okay bubble is is setting some privacy rules on the user okay so even though we're getting everything from the product okay the user that we're trying to get some information from is having its email restricted and so if we go into the data tab and then we go to privacy okay this is where we can actually see what privacy rules we have set you see we've got one rule up here which is that when the user who is who you're evaluating and the expression is the current user so in this case right it would be this would be like if the creator of this product is the current user then you would show their email okay so if the current user the currently logged in user is the same user as the one that you're evaluating that you're asking the question about then this is what will happen this is what you'll allow to happen and one of them is to view all fields otherwise okay everybody else so if you're not the creator of a product in this example okay then you can't actually see any information about any other users that's what this is saying here and so what we actually do want is to expose this email field okay so that says that don't show anything else about a user but you are able to return this email field for a user like that is something that can pass through this filter i'm quite happy for you to pass through the email of any user okay and you might want to re you have some more elaborate privacy rules around where you can send these emails and probably in your application you might want to actually have some kind of in-app chat or messaging functionality so that you never expose users emails to one another but in this really simple example application that we're building this is going to be fine so now that i have updated that i'll refresh the page and now indeed you can see we are seeing those email addresses okay we are seeing all of these email addresses so with that out of the way okay and privacy rules can get quite complex so this is a really simple treatment of privacy rules let's get into our favoriting products functionality okay so the first thing we're going to decide is how is a user going to add a product to their favorite products list okay and one thing that we might want to do is add a little icon a little icon here and we might want to make this like a little plus icon and let's customize this a little bit okay let's kind of make it slightly like like grayed out and then when it is hovered okay so let's add a condition here when this icon is hovered okay then we'll make it kind of a darker a darker color something like this there we go and you know maybe we want to make this a style so we haven't talked about styles yet but based on what we've set here the values that we've set here we can create a new style so let's call this our hover icon let's say and now from the styles tab okay we actually can edit all of the values for any styles that we've created so if i filter this by icons you can see here is the the style that i just created and so any time like if i have another one of these icons over here and i set it to be the hover icon right anytime that i change something about this let's say i give it a border that's going to apply to all instances of that style any icon that has that style is going to get that same formatting so it's kind of like a reusable element in a way you know where you set the you set what the master template looks like and you make changes only to that master template but you can have many different instances of the template all around your application and they will all reflect any changes that you make to that master template so that's styles in a nutshell i'm going to undo that border and what we want to do here is attach a workflow now to this icon which is going to take the current sales product right the product that's in the cell where this icon is okay and add that product to our users favorite products okay add one of these guys to the favorite products list so we will go start and edit workflow what we want to do we actually have two options here we can make changes to the current user that's always something that bubble gives us out of the box so we can make changes to the current user who's logged in or we could make changes to a thing and the thing that we decide we're going to change we could choose make changes to lots of different things is going to be the current user now what do we want to change here we're talking about what field do we want to change right and we've got this favorite products field okay these are the two fields that we can make changes to on our user so we want to choose favorite products now okay we actually want because we're dealing with a list we have some different options here what we want to do is add an item to that list and the item that we want to add is going to be the current sales product right the cell in which this icon was clicked so if i just go step by step for a moment and i go nike shoes okay make changes to the user and we're adding that current sales product to the user maybe i'll add a t-shirt and i'll add a digital camera as well and now if we look in the database okay and we evaluate our user you'll see that there's a bunch of long number strings in here okay these are the unique ids of these products that we added right remember i said like all we're storing on the user is the address where we can find those products on the products table on the products shelf okay so that's what we're doing we're storing the id here so these are all of the addresses or the unique ids of the products that we've added okay and we probably want to give some kind of indicator that these items have been added okay so then we come back to our trusty conditional tab okay so now we can do something really clever we can say something like okay well when the um the current user's favorite products okay we're taking that list and we're now kind of we want to ask it you know is the product in this cell that we're evaluating is it inside of this list is it inside of my favorite products list so we can choose contains current sales product so does the favorite products list on me as the user okay does it contain this particular product the product inside of this particular cell so that question is going to be asked for each cell every single icon in every single cell is going to ask itself this statement okay so that means that some of these icons will have the statement evaluate to true and for some of them it will be false right for the ones that do have a favorite product in the user's favorite products list it will be true so now we could say okay well maybe maybe we say the element isn't clickable and the icon color like again will make it kind of a dark a dark blue right and now you can see okay so this item is in my favorite products list so is this one and so is this one okay so that's how we can kind of add items and just to kind of round out this picture what if we allowed users to remove items as well how do we do that well let's bring it all together now the things that we've learned in this video okay we know that we want the behavior of this icon to be different depending on whether a certain condition is true namely depending on whether the favorite products list has this product this particular product in the cell in it or not so we probably know that we're gonna have to use some kind of only when condition here right so for the one that we are click that we already have set up okay we basically want to say like only if the product isn't already in the list okay then add it into the list okay so only when okay the current user's favorite products doesn't contain the current sales product then launch this workflow but we also want the inverse okay if it is in the list then remove it if it's in here okay and i click the button then remove it or at least delete the reference to that product from my list of favorite products so i'll just copy this and change this expression here so that it's when the favorite products list contains the current sales product okay and then we have to update this as well because now we don't want to end the product i can click on this by the way and then that allows me to change it now we want to remove the product so we've got two workflows here that are both doing the inverse of one another and so if i click this now in fact i'm not able to and if we go into our debugger we might be able to get a clue as to why ha so this condition which is saying if this product the product in the cell is in my favorite products list then it's not clickable okay so the fact that it's not clickable means that we can't launch any workflows off of it that's what not clickable means so i should actually remove that condition and now if i click this see how it's been removed it's no longer blue and if i click it again it's added so kind of at whim i now have a ability to add and remove items from my favorite products list all right that is the end of this huge mega tutorial we've packed so much in so well done if you've made it this far there's obviously a ton that we haven't been able to cover here because bubble is this really complex tool there's lots of layers to it but hopefully you've got a good solid initial foundation now to sort of go out there and start exploring different avenues do let me know what you are building i want to know what challenges that you're facing let me know if this video was helpful one of the next big things that you should focus on learning would be responsive design so i'll link to a video up here somewhere where you can get a good grasp on responsive design as well otherwise best of luck with your building and happy bubbling [Music] you
Info
Channel: Matt Neary
Views: 533,672
Rating: undefined out of 5
Keywords: no code, no-code, nocode, bubble.io, bubble tutorial, bubble.io tutorial
Id: CSMx0cTa6Ls
Channel Id: undefined
Length: 185min 53sec (11153 seconds)
Published: Thu Mar 17 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.