Fullstack Svelte with SvelteKit

Populating the Results Page

Fullstack Svelte with SvelteKit

Check out a free preview of the full Fullstack Svelte with SvelteKit course

The "Populating the Results Page" Lesson is part of the full, Fullstack Svelte with SvelteKit course featured in this preview video. Here's what you'd learn in this lesson:

Rich walks through implementing the data loading to populate the movies for each page view. Starting to configure infinite data loading for browsers without JavaScript and styling the returned movies into a grid is also covered in this segment.


Transcript from the "Populating the Results Page" Lesson

>> All right, so the first thing that we're gonna do in order to build this page is we're gonna implement our data loading. We're gonna add a load function, which should be very familiar by now, export async function load. And we're gonna grab the params so that we know what view we're dealing with.

We're also gonna use the URL and the fetch functions. Inside here we're gonna get hold of the view object that relates to the current page. And again, because we've got that matcher on the root, we can guarantee that this view object is in fact one of the views that we defined earlier.

Ane we're gonna get the data using the API helper, so we'll import * as api from lib/api. await api.get, again, we're gonna pass in fetch. And we're gonna use the endpoint of the view that we defined earlier. And we're gonna tell TypeScript what kind of thing we're dealing with, which is a MovieList.

We're gonna return some data from this load function. We've got the title, there's gonna be the view.title. We're gonna end up using the endpoint, as well. Most importantly, the movies themselves, data.results. And that'll do for now, we can start building it and we'll come back to the rest later.

Let's create a script tag, lang = ts, so that we can add our data prop. The first thing that we'll do, we'll create a wrapper element. We're gonna give it a column class. And inside there we'll add an h1 with the title of the current page. Okay, so if we visit trending, we get the trending title, if we visit now playing, we get an now playing title.

Basically all of the things that are defined in our view.ts file that correspond to the slug in question. Now, here's where things are gonna get interesting because on each of these pages we wanna have infinite pagination, we wanna have infinite loading. But on browsers that don't have JavaScript for whatever reasons, we want it to continue working.

So if I going to my dev tools and disabled JavaScript. What we'll see is that when we scroll down instead of triggering infinite loading, we're gonna see a next page link, click on that. It's gonna take us to the next page of movies. And so back in our data loading function, We wanna get the current page from the query parameters that were passed in.

And this URL, because it's a URL object with a search params map, we can get page, and that's gonna default to 1. And we can just pass that directly to our API like that. And from our load function, we're gonna tell the page whether there is a next page or not, because eventually you'll get to the end of the list.

And we can know that if the page that was returned from the API is less than the number of total pages, which were returned from the API. If it is, then we'll do data.page + 1. Otherwise, we're gonna return null, which will mean don't render a next page link at all.

So it's time to start building the component that is gonna render that grid of movies, and enable the infinite loading functionality that we saw on the deployed version. Inside our lib directory, inside components we'll create a new component, let's just call it ResultsPage.svelte And like the carousel, this is gonna have a movies prop.

Which is gonna be an array of MovieListResult, I forgot to add lang = ts here, so let me do that real quick and fix that import. And we're also gonna have a next prop, which is gonna be a string or a null. That's gonna correspond to the next page link that we got back from our data So it'll take us a minute to build up to the infinite loading.

For now we're just gonna render essentially a grid of all of the data at once. Create a div class = results. And inside there we're just gonna iterate over the entire movies array. And for each of them we're gonna create a link. And we're gonna direct that to our as yet non-existent movie page.

And inside there we're gonna put an image, which is gonna be the movie's poster. Give it an alt attribute of the movie title. And the source is gonna use that media helper that we've seen already. We'll pass in the movie poster path, With a width of 500. And then, back in the root, we'll invoke that results page component, and pass in our movies.

We need to add that next prop as well. And that's gonna be the current view, Data.view. With a page parameter. It looks like we're not returning that from our load function. Let's just fix that, pass the parameter back into the page. And then the page is gonna be whatever the next page is, data.next page.

Although, of course, we don't want to do this if there is no next page, so we're gonna make this whole thing a ternary. If data.next page is true, then, We're passing that whole thing, otherwise that's gonna be null, in which case we won't render n next page link. So we now have some movies rendering on our results page.

Again, they're kinda ginormous, this is not what we want. So let's go into that component and start adding some CSS. Our results div is gonna have a display of grid. And for now we'll give a grid template columns of 4, And we're gonna make sure that the width doesn't exceed the space available.

And we happen to know that all of the posters that we get from the movie database have an aspect ratio of 2/3, which we can use it to prevent any layout shift. Okay, I need to figure out why that's not doing what we expect. I think it's because the image also needs some CSS.

Add some CSS to the image. Okay, so for this to fit on the page we need to make a small change to that column class in our global styles, this width here should in fact be a max width. We want the width to be a 100% up until that point.

And so now we have this nice pleasing grid that's showing all of the data.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now