Transcript
Hello. So in episode 63, we learned how to build models with hot fire. And in episode 142, we learned how to build models using the, uh, dialog H TM L element that is now supported by all the browsers. And, uh, I thought, what if we combine the two approaches, the hot fire pod and the H ttm L dialog pod to create the perfect models? So here's what I came up with. Uh, I have an empty list of comments. I click on create new comment. I have this, uh, um, model dialogue opened. I have, uh, possibility to click on cancel to close it. I can click on escape to close it. I can click outside of the model to close it. And, uh, let's say I want to create a comment. I click on create, you see the errors have been run it correctly. I click on, uh, let's add something in the body, like, hello. You see, uh, the model has been closed on successful form submit. And, uh, the element has been added to our page. Let's say I want to show the element and I want to show it inside another model. I click, click on Show. And you see I have this comment in its own model. I can, uh, go to edit it, it navigates to the edit. I click Update, it goes back to the show page. And let's say I want to destroy it. I destroyed it. The model has been closed. In this case I wanted it to be closed. And, uh, the comment has been removed from the list. So we are going to learn how to, um, close models, how to navigate, uh, from one model to another, and, uh, how to make the work nicely with HTML dialogue plus, uh, hot wire tool. So let's start with, uh, a blank state. We're gonna start from the beginning here. I just have a basic scaffold of comments. So comments, controller comment that has validation of body presence. And, uh, a comment just has a body. Okay, so here is a blank state, and let's add, uh, uh, this kind of turbo models vitalic element. I'm going to start, uh, with episode 142. I strongly recommend you to watch, uh, both of these, uh, before, uh, going to this episode. This kind of the third part in the model series. So, um, let's go, uh, to, uh, the final code of this, uh, episode and, uh, here had this JavaScript to handle the dialogue. Uh, I'm going to copy it. So I will say rail generate stimulus dialogue. I'm going to go to this, uh, generated dialogue controller. I'm going to copy, uh, this, uh, code. Again, we discussed how all this code works in episode of 142, but basically we have some code to, uh, enable and disabled body scroll, uh, handling the opening of a model, handling the closing of the model, and handling, uh, closing of the model. If we click outside of the model, and now let's go with this, uh, UG element into our application layout. So I will go to layouts application and put it somewhere, uh, somewhere here inside the body tag. Okay, now I will go back to the page. I will click on open dialog. And you see we have a dialog that, uh, opens and we have all the default model behaviors. Looks fine. Now, we want to actually render this new comment, not in a separate page, but inside this, uh, dialogue. How can we do it? Uh, first of all, I'm going to say that, uh, this is going to be, uh, this new comment clicking on it should, uh, open that dialogue. So here, uh, I have this button with data action, click dialogue open. So click on here, opens the dialogue. I'm going to add this data action to our LinkedIn new comment. So I'm going to go to the index page, and here I'm going to say, uh, data action. Uh, and the action is click dialog open. Now let me refresh. I click on your comment and well nothing happens. Uh, maybe let's open our console to debug. Okay, I click on your comment, and again, nothing happens. Why? Because this dialog, uh, controller is not initialized. Uh, here you see the dialog starts here and ends here. So the yield, the place where the, um, where the link where this link is rendered does not, uh, contain this controller. So it wouldn't work. I would need to put the dialog controller maybe on the whole body so that we can, uh, open the dialog out of anywhere in our application. So I will remove the Steve and, uh, the dialog is on our body tag. I will, uh, refresh. Let's, uh, go back. Uh, I click, uh, on your comment and you see for a brief moment of time, it opened a model and, uh, then already it rejected to the new page. So we don't want to have a full page direct. We want to open, uh, this inside a turbo model. So, uh, here inside the body of the dialogue, uh, here, I'm going to put a tag, a turbo frame tag, I will say equals turbo frame tag. Let's give it an arbitrary name of modal, and I'm going to remove some, uh, other placeholder code that we don't need anymore. So inside the, the dialog, we just have a balance to close the model and, uh, uh, tub of frame that can render anything. So I click on new comment, and you see there's still a full page direct. So we want to say that this, uh, link opens not in new page, but inside the UBA frame model. So turbo frame model. So clicking on this button should open the HTML model and it should, uh, navigate to the new page and join this new page inside this TOBO frame model that we have in our application layout. Let's refresh and try if it to see if it works. I click on new command and you see we get this content missing. And in the GS errors we see that we had an visit, a successful visit to the new page, but it didn't find the tub frame with the idea model. So it gives us the content missing error, not have this content missing error. We're going to actually wrap this page into the tub frame tag model. So I will say equals to ball frame tag model do, and I'm going to wrap it all into this. Okay, I will refresh now, click on new comment, and you see the new comment has been rendered in the model. Let's just demonstrate again, I just click on new model here and it renders an empty model. I click on new comment here and it renders, uh, the new comment page inside the model. Now let's uh, click on create comment. You see the errors are being rendered. I will click, uh, and add something to the body, like, hello, create comment. And, uh, there has been a successful form submission, but we again, get this content missing because, uh, if we go to our controller on create, on successful Create, we go to comments URL, so tries to open the show page. And inside the show page, we don't have this store frame model. So by default it wants to navigate to the show page. Let's actually navigate to the show page inside the model. Let's do it. I will just, uh, go with this tub frame tech model and wrap it, uh, around the show page and let's see if it works. I will, uh, create a new comment full. And you see the comment has been created and we have navigated to the comment show page. Here it is, uh, let's uh, say, we'll also want to navigate to edit the comment. So at the moment, I will click edit and it gets content missing. So, uh, we are just going to do, uh, here we have this edit. We're going to say, uh, Yeah, we're just going to wrap, uh, the edit page into the to frame model also. Hmm. And, uh, let's see. So I go to show the comment, or maybe let's do it via this model. So, uh, model, create, comment, uh, we can, uh, go to edit, update. Uh, yeah, so it seems to be working. I can go to show. And you see we can do some navigation, uh, and, uh, updates inside a model Looks. Uh, okay. And, uh, what if, uh, we want to break outta the model, for example, uh, when we create a new comment, I want to not just direct, I want to actually close the model. How can we do it? Well, uh, for this, we're going to go back to episode 63. I will, uh, go to my notes and, uh, here had this, uh, to submit and, uh, action that would, uh, check if there was a successful form submission. And based on this, we could, uh, potentially, uh, close the model. Let's try again, this behavior to our current model. So, uh, I will add this, uh, these lines, Uh, somewhere here. And now let's try, uh, triggering, uh, this submit end. So, um, we have this action and uh, let's, uh, wrap this action around the new page. So, uh, let's say I will have a new div and, uh, it'll have action equals to the submit end. I'm going to put another div here. So, um, this form is going to listen to tuba submit end, and if there was a successful form submission, they're going to handle UBA model submit end. Actually, it's not tuba model controller, it is dialogue controller. And, uh, final, just have a console lock here. So, um, yeah, I think we're missing something. Okay, this should work. So let's put a console log, um, console log e detail dot success. So, uh, let's refresh. I have our console broken. I will click on create comment. Uh, nothing has been rendered. Let's, uh, create a comment actually. Okay, I don't see anything, uh, here. Uh, advise it. So action Tobo and Tobo model Submit and, uh, the new thing. Yeah, I think this should work. Interesting. Uh, okay, let's not, uh, do this console locked in. Let's try to use the hide the model directly. And in our case, it's not, uh, hide model. It is, uh, this dot close. And the model target is, uh, the whole dialogue element. So let's, uh, create a new comment, create comment, and we still have this full page navigation. So this, uh, turbo submit and Dex Submit end does not seem to be working. Hmm, obviously, uh, I should have said data action here. Div Data Action, but not just div action. Yeah, uh, okay, I'll just add this, uh, here for us, uh, to understand it better. Yeah, it should be div data Action. Okay, let's, uh, try on scan to just log it in the console. So new comment two, two, create, comment, and it is true. So detail success is true. Let's make another option with false. I will click on create and, uh, well, we get an error. So, uh, only if, uh, e digital success equals true, uh, they're going to do the close. So let's try once again, I'm going to create new comment. Let's say three. The three create comment and the model has been closed, but it has not been added. The comment has not been added to the list. Let's, uh, make it so that the comment is added to the list on top of the list. When we create a new comment, let's see, I create new comment and it's not in the list, I refresh and it is in the bottom of the list. So for this, we're going to use Tobo streams, and I'm going to the comments controller, create action, and I'm going to say format, turbo stream. Do render, turbo stream, turbo Stream. Uh, replace the command with partial comments. Local command, uh, no, actually not replace. Uh, autocomplete is not being friendly. We are going to do a pen. So add on top of the list. So we are going to add the new created comment on top of the list. Let's try, let's make, uh, this did not work. Append to the list of comments via the list of comments. If we go to index, we have this, uh, uh, div with ID comments. Okay, so, uh, 1, 2, 3. Yeah, uh, append makes on the bottom of the list, let's use pre-end. Okay, refreshing, uh, 1, 1 1. And it has been added to the top of the list and the common, uh, model has been closed, so works well. So now when we create a new comment successfully, the model is closed, uh, in the correct way, and uh, the comment is added to the top of the list. But what if we try to just open the initial H TM L model? I click on open dialogue, and you see we still have the old H TTM L that we just submitted the present here. So we closed the model, but we didn't clean the model up from the, uh, old HTML, and we'll need to do it. So to clean up this model from the HTML that we don't need, we are going to go back to our application, HTML, and uh, on this uh, tubo frame tag model, we are going to add the new target. Uh, how should we name the target, let's say frame. So data, um, dialogue target will be frame. And inside this, uh, dialog controller, I'm going to add a new target. Name the frame. And when we close the model, we we're going to clean up everything inside this frame. So we will say this dot frame target, and, uh, we're going to remove, uh, attribute, SRC, uh, let me just not do it for a moment. And let's see what happens without it. Let's just have something here like, uh, an empty submission. Let's say I click cancel, I go back to open this, and you see we still have all this stuff here. If I go to inspect element, um, so, um, inside the dialogue we have, uh, the tub of frame with the URL comments, you, and we don't want it to be with the comments, you, we want it to be just like an empty tub of frame. So now I will add this and uh, I go to new comment. I, uh, close it. I open og, we still have it, but uh, do we still have the, um, SRC? So the source URL of the tuba model? No, we do not. So it's already cleaner, but if it still open the tuba frame tag, we still have, uh, uh, all the new comment stuff. So we are also going to go and say this dot frame target, and we're going to say inner HTML is empty. So we're going to remove everything from inside this, uh, tub of frame. I'm going to refresh. Let's create a new comment. I click cancel. I open og. And you see everyone has been removed from this, uh, model. So we have our cleanup work, uh, in place. Okay? Uh, now let's, uh, try a few other behaviors. Let's say I want to click on edit and edit should lead not to this, uh, edit page. It should lead to, um, yeah, you see we have some ation broken. It should lead to the model. So the same way we did on our index page where we added the data, uh, action, click, dialogue open and to the frame model, we're going to do this same thing on the, uh, edit. So here we have link to edit comment, and I'm adding this OG open to the frame model. So whenever I click on edit, uh, no, maybe not here, let's go back to comments. This is render here inside the comment partial. So okay, I refresh and I click on edit and opens the edit. In the model, I click update. And uh, when I click update, you see in the new page, we close the model when the submit is successful. But in the added page, we do not close the model when the submit is successful. So we will have, uh, redirect within the model to the show page. I click update, we're directed to the show page. It, uh, works. And what if we want to, uh, see the show page? I click on the common show. We want to see the show page inside the model. So in a similar fashion, we are going to add this data dialogue open model to link to show this comment in model. So I refresh, I click on show this comment, you see the show, this comment inside the model looks, uh, uh, fine. Now what if want to destroy the comment? Let's say I click on Destroy, and you see we have this content missing. So actually the comment is being destroyed, but we, uh, try to redirect to basically nowhere. So this is a case where we definitely want to add, uh, this behavior to close the model, uh, on Successful Submit. So I'm going to go to this new action, and, uh, in this comment, I'm going to wrap, uh, whether we have this destroyer action visible, uh, here. So, uh, I'm going to wrap the Destroy into data to submit End. Now, let's refresh. I'm going to show a comment. I'm going to click on Destroy. And, uh, the model has been closed. Uh, it has not been removed from this, uh, comments list, but if I refresh the page, it has been removed, but has it not been removed from the comments list? Because for this, we need some two, uh, streams. So I'm going to go to Destroy, and I'm gonna say four dot two Ball stream. Do, and I will say to Stream, remove the comment from the list. So now let's say I show the comment, I, uh, click on Destroy, the model has been closed, and the comment has been removed from the list. And this way we can remove other comments from the list. Let's remove a few. We have created a real lot of them. And let's, uh, start from a blank state. So let's say I want to create a new comment. I link new comment, it opens in the model, uh, errors have been rendered. I will have something in the body create comment. The model has been, uh, uh, successfully submitted and closed, and the element has been added to the page. If I just try to open the blank model, you see it is empty. Now, let's say, say I want to go to, uh, show this model. I can see this model. Okay, let's close it. I can go to edit, I will edit it. I will click on the update, and, uh, I have a navigation that happened to the show page within the model. So it works fine. I will click on Destroy. The comment has been destroyed, the model has been closed, and it has been removed from the list of comments. So basically in this episode, we learned how to, uh, close models if we want to, how to navigate within the models and how to make the ML dialogue element work nicely with two bo uh, frames and to streams. So thanks for being with me and see you in the next one.
0