Creating HTMX Helper0:00
I want to spend a few minutes cleaning up the code inside of our controller because, well, it leaves a lot to be desired. And I want to keep this as simple as possible. And my first thought was, you know, for our requests. Because it would be nice to have some helper methods to determine if it's an HTMX request and things like that. I thought we could do HTMX request and then work with that object that way. But I don't necessarily want to do that now. Because that means we would need to pass this request around. Like in the case of showInvoicesByStatus, we would have to have request. And, you know, it's not that big of a deal. But we are already passing three things to that method. I don't want to pass a fourth. So I'm gonna be lazy. And we're gonna create a helper class.
of a deal. But we are already passing three things to that method. I don't want to pass a fourth. So I'm gonna be lazy. And we're gonna create a helper class. And we're gonna do so inside of the app folder. So let's start the folder inside of app will be called helpers. And then we will just have htmxhelper.php. We will start with our boilerplate stuff such as the namespace, which is app/helpers. Then we will have our class of htmxhelper. So I want this to be as easy to use as possible. So let's just have some static methods. The first will be isHtmxRequest. And this will return a boolean value. This way we can easily just check if this is an htmx request. And we don't have to dig into the request, get the headers, and all that. This will just make it a lot easier. So
just check if this is an htmx request. And we don't have to dig into the request, get the headers, and all that. This will just make it a lot easier. So if we have the HX-Request header, then yes it is an htmx request. The other method I want to write is isCurrentUrl so that we will get a provided URL. And this is going to be used basically right here where we check if the current URL is the provided URL. But remember that ideally we would normalize the URLs, but I'm not going to because I'm going to be lazy. In a real application I would do that just to make sure that either both URLs either had a trailing slash or I would take out the trailing slash. I would just try to normalize them so that I could properly compare them. And in this case we want to get the header of
would take out the trailing slash. I would just try to normalize them so that I could properly compare them. And in this case we want to get the header of hxCurrentUrl and we want to compare that to the provided URL. So that means inside of our InvoiceController we can make this a lot easier to read. So our isHtmxRequest instead of getting request has header all that stuff we can say htmx helper and we would simply use the isHtmxRequest. For our usage here we could get rid of that so that we would use the isCurrentUrl and then we could pass in routes.invoices.index. And to me that's a lot easier to write. Plus we get rid of this routeUrl variable. So great we are already cleaning things up. But then there's all of this. I don't really like any of that. So let's do this.
Refactoring Controller Flow3:03
we get rid of this route URL $variable. So great we are already cleaning things up. But then there's all of this. I don't really like any of that. So let's do this. Let's move our invoices up here. I don't even really want to do this. So what we'll do is we'll check if it is not an htmx request. Then we are going to return view. We want invoices.list and then we need our model. But our model is quite a few things. So let's do this. We will have our invoices. Then we will have our model which we will call compact to where we will have our heading invoices and then the post URL. So that will be our model so that we could pass it. And this just makes it a lot easier. If it's not an htmx request then we just return a normal view. We don't need to do anything else. Easy. But if it's not, well
this just makes it a lot easier. If it's not an htmx request then we just return a normal view. We don't need to do anything else. Easy. But if it's not, well let's just get rid of all this. And let's say that okay if we want to return some htmx specific things we can do this. We could return a new htmx response and then we could say we want to add a fragment and we could pass in the information that we would need such as the invoices.list view. That's the view. We would also need the fragment which was I think invoice-list then the model. And in that particular case that's all we would need. But you know in some cases we do need to include the index for our snapshots. So we would call ag fragment once again. And here we would have invoices.index. The fragment is
we do need to include the index for our snapshots. So we would call ag fragment once again. And here we would have invoices.index. The fragment is snapshots. But this doesn't need a model because it is automatically supplied. So we'll just pass in an empty array. But then we need to determine whether or not we include this fragment which is where we would use our other htmx helper method. isCurrentUrl and if it is the invoices.index. And that's a little long. So let's put these parameters on their own line. That'll make that a lot easier to read. And yeah I like that a lot better. It still leaves a little bit to be desired. But you know this in my opinion is a lot easier to understand what's going on. So let's create that class. Let's do this inside of the HTTP folder. So we will
Building HTMX Response5:29
But you know this in my opinion is a lot easier to understand what's going on. So let's create that class. Let's do this inside of the HTTP folder. So we will create a new folder called responses. And then we will have htmxResponse.php. And of course we need to start off with our namespace which is app\Http\responses. And then we need our class which is htmxResponse. We are going to extend the Response class from Illuminate\Http. And then we will have our public function addFragment. Let's see we had the view followed by the fragment name. So we'll just call that fragment. Then we had the model which we will have a default value of an empty array. And then we have the boolean value to determine whether or not we include that view. And let's give this a default value of true so that we could do something like this.
And then we have the boolean value to determine whether or not we include that view. And let's give this a default value of true so that we could do something like this. If include is true then we need to keep track of the views that we are creating here. So let's create a fragments array so that then we will call view, pass in the view name, the model, and then we will call fragment and pass in the fragment name. And that ought to work. I know we could not have an if statement here. And I know that we could use fragment if and then we could have include and then fragment. But I like the way that this reads a lot better. It's clear as to what's going on. We do need that protected array called fragments which is an array. So there we go there. And we need this to be chainable so we will simply return this. But then we need to build the response. And we do that by overriding the prepare method.
So there we go there. And we need this to be chainable so we will simply return this. But then we need to build the response. And we do that by overriding the prepare method. Now the prepare method of course does come from response but response is actually inheriting that from Symfony\Component\HttpFoundation\Response. And this request here is from Symfony\Component\HttpFoundation\Request. So just be aware of that. And in this particular case the first thing we want to do is set the content of the response. And all we need to do is implode our fragments. And that's going to get us what we need so that then we just call the prepare method on the parent, pass in request, and we're good to go. So that should be everything. Unless if I mistype something which is very possible. We do need to import htmx response and yeah there's a syntax error there. But I think that's it. So let's go to the browser. Let's refresh. If we click on the links
Testing Refactor in Browser8:16
something which is very possible. We do need to import htmx response and yeah there's a syntax error there. But I think that's it. So let's go to the browser. Let's refresh. If we click on the links okay it looks like that that worked. Let's scroll all the way down to the bottom. We don't see the snapshots at the bottom so that is being loaded correctly. Let's open up in another browser just the open invoices. So if we scroll down there's no snapshots. So everything looks like that that's working okay. Let's submit our form here. So let's choose this Hessel Schneider and Daughtry. Let's see veg 43. So if we submit this yes it looks like that was indeed submitted. So that looks like that that's working okay. Nothing else looks out of the ordinary. So we're good there. Let's not refresh. Let's just click on open invoices. We should see our snapshot update. Yes great. So let's approve something then and let's just approve this MANT Inc. RAG 22 is what should be going away. So we
Let's just click on open invoices. We should see our snapshot update. Yes great. So let's approve something then and let's just approve this MANT Inc. RAG 22 is what should be going away. So we submit our account changed. That invoice is gone. So great our code works. That's fantastic and not only does it work it's I'm not going to say a little this is a lot better. It is now understandable what's going on and I like it. Of course refactoring is a never-ending process. We could refactor and then refactor our refactor and then refactor our refactor our refactor. But I'm pleased with this. This is going to work fine.
