Welcome to the third lesson in our course on building an image generation web application with PHP Laravel! In the previous lessons, we created the HTML structure for our application and styled it with CSS. We now have a polished interface with tabs, form controls, and containers for displaying generated images and image history.
At this stage, though, the application is still static. Clicking the buttons does not yet switch tabs, submit prompts, or display results. This is where JavaScript comes in. JavaScript adds the behavior that makes the interface interactive and responsive.
In this lesson, we will write the client-side code that allows users to:
- switch between the Generate Image and View History tabs,
- read values from the form,
- send requests to the backend API,
- and display generated images on the page.
Our script.js file will act as the bridge between the user interface and the Laravel backend.
Before writing the JavaScript, let’s confirm the file structure we are using in this course so it stays consistent with the earlier units.
In our Laravel project:
- the Blade template lives in
resources/views - static assets like
CSSandJavaScriptlive inpublic
Here is the structure we will use:
This matches the structure used throughout the project:
resources/views/index.blade.phpcontains theHTMLinterfacepublic/css/style.csscontains the stylingpublic/js/script.jscontains the frontend logic
Now let’s begin by implementing tab navigation.
Our application has two main tabs:
- Generate Image
- View History
We need a function that hides all tab sections and then shows only the one the user selected.
Add the following to public/js/script.js:
This function works in two steps:
- It selects all elements with the class
.tab-contentand hides them. - It selects the tab whose
idmatchestabNameand displays it.
Our Blade template already connects the buttons to this function:
That means:
- clicking Generate Image shows the
generatesection - clicking View History shows the
historysection
Because this function works with all elements using the .tab-content class, it will also support additional tabs later without needing extra logic.
Now let’s implement the main feature of the application: generating an image from a text prompt.
In earlier lessons, we added both:
- a text input with
id="prompt" - an aspect ratio dropdown with
id="aspect-ratio"
That means our JavaScript should read both values and send them to the backend.
Here is the full generateImage() function:
Now let’s break this function down step by step.
First, we retrieve the values entered or selected by the user:
This is important because our form includes both:
- the prompt text
- the selected aspect ratio
The aspect ratio dropdown was added in earlier lessons specifically so users can control the image dimensions, so we should make sure that value is included in the request.
Next, we retrieve the elements we need to update while the request is being processed:
These references allow us to:
- show a loading message,
- temporarily hide the button,
- and display the generated image when it arrives.
Before making the request, we confirm that the user actually entered a prompt:
If the prompt is empty, we stop the function early and show an alert.
Before the API call begins, we update the page so the user gets immediate feedback:
This does three things:
- shows the loading message,
- hides the generate button,
- clears any previously displayed image.
Now we send the request to the Laravel backend:
Notice that we now send both pieces of form data:
user_inputaspect_ratio
This is important because the backend route is already expecting those fields:
user_inputfor the promptaspect_ratiofor the selected dimensions
This keeps the frontend aligned with the backend API and allows the image generation service to build prompts that reflect the user’s aspect ratio choice.
Once the backend responds, we parse the JSON and restore the UI:
This code:
- hides the loading message,
- shows the generate button again,
- checks whether an error was returned,
- and displays the generated image if successful.
If the request fails entirely, we handle that in a .catch() block:
This ensures the interface remains usable even if something goes wrong.
In this lesson, we added the frontend behavior that makes our application interactive.
We:
- created the
openTab()function for tab navigation, - kept the project structure consistent with Laravel by using:
resources/views/index.blade.phppublic/js/script.js
- implemented the
generateImage()function, - retrieved both the prompt and the selected aspect ratio from the form,
- sent both values to the backend API,
- and displayed the returned image on the page.
At this point, users can:
- type a prompt,
- choose an aspect ratio,
- submit the form,
- and view the generated result.
In the next lesson, we will build the history functionality so users can load and review previously generated images.
