Transcript from the "Special Elements" Lesson
>> We're coming to the end of part two of the tutorial. This section is a little bit of a mishmash, we've got a bunch of different special elements that Svelte provides to your components. And they don't really have anything in common with each other, other than the fact that they belong to the Svelte namespace.
[00:00:18] So the first of these is Svelte self, and that is something that allows a component to reference itself recursively. And it's useful things like this folder tree view, where a folder can contain another folder. So inside our folder.svelte component. We would wanna be able to do something like this, where we have the file here, we'd like to be able to add a folder that references the same component, but that's impossible because a module can't import itself.
[00:00:50] So instead, we use svelte:self here. And now, the folder is containing other folders. And we can do that to an arbitrary depth. An interesting fact about this is that, if you try and do this at the top level of a component, it will yell at you, because that would cause an infinite loop.
[00:01:20] But it's smart enough to know that that is not a thing that you should be doing. Now, a component can change its type altogether with the Svelte component element. In this exercise, we wanna show RedThing.svelte, if the value of the selected color is red. And we wanna show a green thing if it's green.
[00:01:46] And we wanna show blue thing if it's blue, and so on. Now, we could do this with a sequence of, if blocks inside of .svelte, like we started doing here. And then, if we select a different color, it would show the green thing and the blue thing. But that's a lot of code to have to write, it's more convenient to make that data driven.
[00:02:06] So we'll create a single dynamic component, get rid of that entire block. Add Svelte component. And then the attribute is called this. I'm gonna pass in the selected component. So you see up here that the value that is getting passed in is actually the constructor of the component.
[00:02:32] And now, when we change the value of that via the select, we're rendering a different component. And we can do the same thing with elements, right? In the same way, we could have, if selected = h1, we'll have a block of h1 content, if selected = h2, and so on.
[00:02:57] But that's just no fun, instead, get rid of all of that, And use Svelte element. And put some content inside. I'm a less than selected, greater than, I would like, so and then now, if we change to one of the other options, It recreates the DOM automatically And so, the value of this can be any string or it can be a falsy value, in which case no element will be rendered at all.
[00:03:49] We've already seen how you can add event listeners to DOM elements. We can also add event listeners to the window object using the special Svelte window element. In this exercise, whenever we focus the window and press a key, we would like to show what key was pressed. We're gonna assign these key and key code values, and then we're gonna show that inside the app.
[00:04:32] All right, and this is just a more convenient way of using window.addEventListener. It will automatically remove event listeners when this component is unmounted. And just like with DOM elements, you can use event modifiers like preventDefault. As well as adding events to Svelte window, we bind to certain properties of it.
[00:04:55] So here we've got a nice little piece of artwork generated by Midjourney. And we would like to bind the current scroll position to this y value. And we can do that very easily bind scroll y = y. And now when we scroll, it's reflected. Again, it's given as fractional values because my site is zoomed in.
[00:05:24] So just change that and it updates smoothly. And that's a bidirectional binding. If you change the value of y, it will also update the scroll position. So there are a few different properties that you can bind to, width, height, scroll, and also the online binding, which is an alias for window.navigator.online.
[00:05:43] This is useful for displaying a message like, you lost the Internet, you need to reconnect to WiFi or something like that. As well as the window, we have a way of adding event listeners to the body element. Which you typically are not rendering yourself because normally you would mount your cell components inside the body, you don't control the actual body.
[00:06:07] So we have svelte body to listen to events like mouseenter and mouseleave. And mouseenter, we want this hereKitty value to become true. And we'll just copy that line and reverse it on mouseleave, it becomes false. And then now, if we enter the iframe, kitty comes out to play.
[00:06:49] Similarly, we have the Svelte document element, which is useful for the selectionchange handler in particular which does not fire on the window. So we can add this on selectionchange event listener. Which is gonna get the current selection and assign it to this selection value there. You can also selects itself, which kinda gets pretty crazy, I don't recommend it.
[00:07:36] And then, we can also add a Svelte head element. Which is very useful for things like SEO, you can add a document title. You can add descriptions and things like that that will appear in search results pages. That's what it's mostly useful for, although it's not visible in the context of this tutorial.
[00:07:58] So we're gonna use something a little bit different. We're gonna use it to load a stylesheet. Add the Svelte head element. And then inside the link rel equals stylesheet. And we have a selection of stylesheets up here that we can pick from. Beginning with the Margaritaville theme, and you can pick whichever of these you must enjoy.
[00:08:49] So getting into the nuts and bolts of how the compiler works, when you invoke the Svelte compiler, which typically you're not doing, your bundler plugin is doing this for you. But when that happens, you can pass options to the compiler that control how the component is compiled. But those are for all of the components in your app.
[00:09:08] Sometimes you wanna have some compile options that are component specific, and that's where we use the Svelte options element. There's a few different options that you can pass to the compiler and we'll use the immutable option as our example. So in this app, whenever we change the value of one of these todos, all of the todos are updated simultaneously.
[00:09:35] That's because we have an afterUpdate function here, which causes the element to flash whenever the value is updated. And that's not really a problem here, that's fine because it's gonna be fast enough that it's not gonna affect the performance of your application. But you might have some situations where you have some very complex data, and you just wanna make sure that a component doesn't update unless you know for sure that its values have changed.
[00:10:04] So we can tell the to do component that it should only ever update anything when the data that has passed into it changes by reference, as opposed to when it is told that its data has changed. This isn't something that you use often, but it's a handy thing in some circumstances.
[00:10:34] So now, if I change the value of any of these todos, only the todo in question is being updated, the others are being left alone. A few other options that you can set are, accesses, controls whether or not the instance of a component exposes its props as accesses on the object that you have a reference to.
[00:11:00] You can pass in a custom namespace and you can control the tag name if you're compiling your Svelte components as custom elements. If you wanna know more about these, consult the API reference. Okay, earlier we learned about using slots to pass content into a component. In this exercise, we're making a Tic-Tac-Toe game.
[00:11:29] And we have a board component, and inside.boardcomponent, we're passing some content which is supposed to appear in each of the grid cells defined by the board. So if you look inside the board component, we are creating a grid, which has a certain number of columns and a certain number of rows.
[00:11:54] But what's happening here is because we have, a div with the slot equals game attribute, we're putting all of the buttons inside the first element and it's not being spread out into the rest of the grid. What we wanna have is these buttons as direct children of the div class = board.
[00:12:19] And we can do that by replacing that div with a Svelte fragment. All right, and so now the buttons that we're declaring here are direct children of the div class equals board.