In our application boilerplate above, we added both Alpine.js and Tailwind CSS using CDN. Although there are other methods for this — like using npm, CDN satisfies our current needs.
Also, in our code above we have organized our application into two main sections namely the hero section and the footer section. Both of these are wrapped by the container div and the main div — that is the div with the class container and main.
Lastly, added responsive padding to our app container to control the padding of an element at a specific breakpoint using the utility classes below:
px-4 sm:px-8 lg:px-16 xl:px-20
With these in place, we can start building our app in the next section.
Building Our Image Searching App
Fetching data and declaring initial state
In this section, we would first declare our app state and construct our Pixabay API for fetching images.
In Alpine.js, we must declare our state in the wrapper components that encapsulates all the component we want to have access to the state. So in this application, we would declare our state in the body element using the x-data directive.
In other to keep our code clean we would return the object for x-data from the imageGallery function — which we would create later.
To fetch images from Pixabay, we need to get an API key and construct our URL.
Pixabay has a base URL — https://pixabay.com/api/ that takes many parameters. However, in this article, we only need the following:
Key: your API Key
q: A URL encoded search term, not more than 100 characters. If omitted all images are returned.
image_type: This parameter is a string used to filter results by image type. Its values include all, vector, illustration, and photo. The default value is all.
per_page: The is an integer that determines the number of images per page. It accepts values between the range of 3 - 200. The default value is 20.
page: The returned search results are paginated and this integer is used to set the page number.
This URL construct simply says search for all types of food images and returns 36 images per page.
We would use this URL with the x-init directive. The x-init directive enables us to hook into the initialization phase of a component. Hence we can run an expression when the component is initialized. It is used with the x-data directory to set the initial value of a component state.
Now add the following code to the body element — to declare our state, and create the imageGallery function as seen below:
In the code above, the x-init directive fetches data from Pixabay and stores it in the x-data directive before the component is processed. Next, we will move to create our search component in the next section.
Creating the search component
In the hero section add the add code to style the app title:
In the code above, our search component is a flex container with three flex items namely: the button component, the input component, and the select component. The search component is wrapped with two components, with the outer component having top padding of 2rem — from the class pt-8.
The custom button component — the search glass, uses the shorthand syntax — @click of the x-on directive to listen for click events. The x-on directive attaches an event listener to an element. In our code above, @click is equivalent to x-on:click. When the button is clicked, the getImages function is called and a new API call is made to Pixabay using the user input as parameters.
Alpine.js also, makes it easy to listen for keyboard events — such as keydown and keyup events, on specific keys. And we are listening for the Enter key event inside our input component by using the .enter modifier as seen below:
So when the Enter key is pressed the getImages method is called. We would create the getImages method in a moment.
The x-model directive is used in the input component to sync the value of q with the component data. Lastly, the select component uses the x-model to bind the value of the image_type to the component data.
The Tailwind utility class, outline-none is used to hide the default browser outline on focused elements throughout our search components.
Now our search component looks like this:
To create the getImages method update the imageGallery function as seen below:
The getImages method uses the same URL construct we used with the x-init directive. However, it uses the component data — user inputs as the values for the parameters. Since we can fetch data from Pixabay we can now start building our image grid.
Building the image grid
Below the code for the search component, add the following code for the image grid:
Also, we used the x-for directive to create our image grid by iterating through the images array in the component data. The x-for directive enables us to create a new DOM element by iterating through a list. In Alpine.js, the x-for directory must be declared on a template tag that has only one root element.
:href sets the image link to the value of image.largeImageURL
:src sets the image src to the value of image.largeImageURL
:alt sets the image alt to the value of image.tags
With the image grid built we can proceed to add the code for the footer.
To create the footer add the following code below the image grid — between the “Footer starts” and the “Footer ends” comments: