CSS & UI Component Interactivity
![Miško Hevery](https://static.frontendmasters.com/assets/teachers/hevery/thumb.webp)
![Qwik for Instant-Loading Websites & Apps](https://static.frontendmasters.com/assets/courses/2023-02-28-qwik/thumb.webp)
Check out a free preview of the full Qwik for Instant-Loading Websites & Apps course
The "CSS & UI Component Interactivity" Lesson is part of the full, Qwik for Instant-Loading Websites & Apps course featured in this preview video. Here's what you'd learn in this lesson:
Miško creates a CSS file and imports it into the contacts component. An HTML input element is added to filter the list of contacts. When the filtering logic is included in the component, Qwik sends the necessary state of the application down to the client
Transcript from the "CSS & UI Component Interactivity" Lesson
[00:00:00]
>> So let's kind of continue with this. So okay, we have this, so let's add couple of things. So lets add an image here. So source equals, and I think if I do contact.avatar, I will have pictures of us in here. Now these are obviously huge images. So let's see if we can do some styling, right?
[00:00:30]
So the next thing to do is let's add index.css, And I'm gonna put them next to each other, and we can import, let's close this. We can import the CSS by saying, import CSS from /index.css and this is little white trick. So normally when you import css in byte, sorry, byte, it actually inserts it into the head.
[00:01:00]
And so we are trying to tell ve like the, don't insert it in the head, I just want the content, right? So the question mark in line is the way you say that. And the next part is you say use styled, And you passed on the CSS. So what this has done is that it tells the system to scope the CSS to just me, just my component is the only component that should be allowed to kind of modify this data, right?
[00:01:29]
Sorry, the CSS only modifies my component nothing else, and we can put styling in here. And of course, this is gonna get loaded, so let's do that. So let's deal with the image first, so the image width, I think should be 75 pixels, height 75 pixels, border radius 50%.
[00:01:53]
Does that do the thing I want? Here we go. That's kind of big. Let's make me smaller. Here we go. So now we have images and I think we need to, what is the vertical line? Middle is that yeah, here we go. My CSS skills are horrible. So the fact that I can do this, I'm very impressed by myself.
[00:02:21]
Okay, yeah. And then we have the Li and we don't wanna dot in front of it. So I think it is Li list style now. Here we go. Okay, perfect. So now we just have a list without the items. So let's look at what actually happened in here.
[00:02:40]
So notice, everybody that is our component gets a special class. And then we inserted a style tag in the correct location and everything is scoped to just our class. So even though we're talking about an image in general, we're not, we know that it's gonna get scoped to only our component, not the whole page.
[00:02:59]
The other thing to kind of understand is that this style tag, we didn't know about the style tag until we started rendering the component. And so the style tag got inserted right at the location where the component was about to be inserted. We made sure the style tag goes first.
[00:03:14]
And then we inserted the component. And this is done because when you start streaming, you don't know which components are gonna be active, so to speak, right? And so in order to have stream ability, you wanna make sure that these styles show up at the last minute. Now, if we included the same component twice, we would only insert the style once.
[00:03:36]
And there is now another problem which is that, okay, let's say we insert it twice, but then on the client, we remove one of the components. Should we remove the style or not? I don't know. So we have logic that takes the style and actually moves it to the head.
[00:03:48]
So it gets streamed inline, but once the application starts running, the styles move to the head so that they work as you would expect. And all of this is done because we wanna make sure that streaming is something we support out of the box. Now, at this point, I wanna point out that we can only stream things in order.
[00:04:07]
But one of the features we're working on is to be able to do out of order streaming. That is, imagine coming to this location, imagine your database is slow. What if the resource was configured to wait for, I don't know, 100 milliseconds. And if the data doesn't show up for 100 milliseconds, then it says, you know what, forget it.
[00:04:24]
Let me continue. And it just renders loading and keeps going, keeps rendering the rest of the page. And then when that particular section is finally resolved, there will be a super tiny script tag inserted into your HTML that says go back to the beginning of the HTML where you skip that bit and replace it with this new HTML.
[00:04:43]
And so in this way, we're hoping to do out of order streaming, which is not something that's possible just yet. But notice how the whole system is basically set up with streaming in mind. We wanna make sure that we can do streaming from day one. It's not an afterthought.
[00:05:01]
It is fundamentally a core decision of how things are done in this particular case. So now we would like to only render some parts, we would like to implement the search. So we need to declare a state. And so we say const filter = useSignal. And initial signal is nothing.
[00:05:26]
And then in here we wanna say on is a change, Is a filtered at value equals event.target.value. So let me just print it out, so right after the input. And I'll say filter.value. No, what did I mess up? No, it works. I see. It's not Onchange, it's on.
[00:06:18]
Do you guys remember what is the input thing to change on every character, it's not Onchange cuz Onchange only does when I leave the field. There is one-
>> Oninput?
>> Oninput, thank you.
>> My God.
>> Thank you, and now this doesn't know that it is HTML input, okay.
[00:06:44]
Perfect, so as I type here, right, you can see that I'm data binding on the other location. Obviously, let me refresh this again, no JavaScript until I start typing, right? And we still don't have any data. So if I look at the qwik json, the only data we have is associated with this filter, right?
[00:07:06]
So this empty string right here talks about the fact that, there is the useSignal that was the empty state. But notice what's not showing up in here. What's not showing up over here, inside of here is the list of users, right? That gets thrown away because the system says, well, you can't modify this stuff.
[00:07:26]
There's no way to render this stuff. And so why should we include this inside of the UI? Actually, let's talk about one thing, which I think is pretty cool. If you look at the network, what downloaded is the listener, right? This is the code that I wrote right here, this input right here, so that thing downloaded, and of course, the framework had to download because that's running but nothing else.
[00:07:54]
What we didn't download is, for example, even this JSX. We can re-render this component without the JSX for the component to be even present. And I think that's kind of cool. All right, so let's do the next bit. So the next bit is this filter right here should only print if it's in there, so before we do a map, we want to do .filter.
[00:08:22]
And so the contact, and so we wanna say contact.name, that to contact.name, why is this. Filter cc, what am I doing here? Yes, so C should be Sorry, the arrow, sorry. Okay, so C.name, two lowercase, not index of filter.value.toLowerCase(). If that is greater than -1, right, then we should keep it or it goes gonna go backwards.
[00:09:12]
Here you go. Oops, let me remove this part right here, okay. So now, we have our filter, right? So if I search for my name of course, my name shows up. If I search for a in Adam and my name shows up, and so we have interactivity on the client.
[00:09:31]
Now many things just changed with that one single line of code. So first of all, notice that now when we serialize the state, the serialized state is much bigger, we now have to include, the serialization of the data, right? As a developer, you didn't have to think about this, right?
[00:09:49]
You were like, I need to search this thing, and so bam. But what the framework did, it was like, okay, well, now you are actually changing the data. You are gonna change what's listed, and so now I have no choice but to also download the data associated with it.
[00:10:05]
And this is what we mean by the data is tree-shakable, right? So if I remove, if I comment out this filter, right, the filtering doesn't work but also the data doesn't get sent. You see this data is essentially empty, there's nothing in here. If I put it back in, now it works.
[00:10:28]
But now the data is so much bigger. I have to include the stuff in there. Why is the refresh not working? Right, the data now that's being included is much, much better. And so I think it's pretty cool because you get to think about it.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops