WEBVTT

1
00:00:00.000 --> 00:00:02.260
Hey everybody, in this video I'm going to

2
00:00:02.260 --> 00:00:05.180
show you around the reactive HTML language that

3
00:00:05.180 --> 00:00:08.020
ships with Elements. You should recognize it because

4
00:00:08.020 --> 00:00:10.940
it's just HTML with some lightweight extensions

5
00:00:10.940 --> 00:00:14.080
that make it capable of handling reactive data.

6
00:00:15.100 --> 00:00:16.740
And this has been in the making for

7
00:00:16.740 --> 00:00:19.640
many years. It started in 2012, it was

8
00:00:19.640 --> 00:00:22.520
the original purpose of the Elements toolchain was

9
00:00:22.520 --> 00:00:23.720
to build this reactive language.

10
00:00:24.280 --> 00:00:26.840
And after that it evolved into the entire

11
00:00:26.840 --> 00:00:28.220
toolchain for building applications.

12
00:00:28.220 --> 00:00:30.800
But it started as the HTML language, and

13
00:00:30.800 --> 00:00:32.240
so this has a special place in my

14
00:00:32.240 --> 00:00:33.800
heart. I can't wait to walk you through

15
00:00:33.800 --> 00:00:35.120
it. Let me give you a quick demo

16
00:00:35.120 --> 00:00:37.220
of how it works first, and then I

17
00:00:37.220 --> 00:00:38.580
can also walk you through the history of

18
00:00:38.580 --> 00:00:41.200
it and how we've done integration with TypeScript,

19
00:00:41.400 --> 00:00:44.120
how it compares to React, and why I

20
00:00:44.120 --> 00:00:46.240
think you'll find it interesting, both for human

21
00:00:46.240 --> 00:00:48.780
development and also for your agents, which I

22
00:00:48.780 --> 00:00:50.240
think will have a much easier time with

23
00:00:50.240 --> 00:00:52.460
this language. So over on the left in

24
00:00:52.460 --> 00:00:55.440
my editor, you can see that it

25
00:00:55.440 --> 00:00:56.640
should look pretty familiar.

26
00:00:56.640 --> 00:00:59.800
This is just an HTML file essentially with

27
00:00:59.800 --> 00:01:02.220
an import statement that it's a little bit

28
00:01:02.220 --> 00:01:04.260
weird because it's importing a style sheet CSS

29
00:01:04.260 --> 00:01:06.300
style sheet, but it's typescript.

30
00:01:06.340 --> 00:01:09.220
We're just writing a regular typescript import statement.

31
00:01:09.580 --> 00:01:11.320
So you can write typescript

32
00:01:12.820 --> 00:01:15.820
Right alongside the HTML inside this

33
00:01:15.820 --> 00:01:19.000
file and that is fine Now down here.

34
00:01:19.000 --> 00:01:20.880
This is an HTML tag We call this

35
00:01:20.880 --> 00:01:23.000
a template and this is a special template

36
00:01:23.000 --> 00:01:25.500
That is the HTML template and you can

37
00:01:25.500 --> 00:01:28.180
write it just like this and it will

38
00:01:28.180 --> 00:01:30.020
be exported from this file as the default

39
00:01:30.020 --> 00:01:30.820
export

40
00:01:31.840 --> 00:01:34.020
Templates are you can put any kind of

41
00:01:34.020 --> 00:01:35.620
HTML in here and right here.

42
00:01:35.620 --> 00:01:37.780
I've got a body tag and an h1

43
00:01:37.780 --> 00:01:38.580
tag and

44
00:01:39.580 --> 00:01:42.540
so far this is just Basic HTML

45
00:01:42.540 --> 00:01:44.640
if I want to create a new template

46
00:01:44.640 --> 00:01:47.380
I can create one by opening a tag

47
00:01:47.380 --> 00:01:49.180
and I'll give it a capital case to

48
00:01:49.180 --> 00:01:52.260
name. Let's just call this greeting and And

49
00:01:52.260 --> 00:01:54.620
inside of that, I can put any HTML

50
00:01:54.620 --> 00:01:55.720
I want. So why don't I go ahead

51
00:01:55.720 --> 00:01:57.920
and put this h1 tag inside of there.

52
00:01:58.420 --> 00:02:00.060
And then I can call that greeting

53
00:02:00.060 --> 00:02:03.200
child like this. And when I save

54
00:02:03.200 --> 00:02:04.780
the browser, update it automatically.

55
00:02:05.060 --> 00:02:06.560
Now you didn't see anything change because we

56
00:02:06.560 --> 00:02:07.660
didn't change the greeting.

57
00:02:09.840 --> 00:02:11.140
But it did update.

58
00:02:12.120 --> 00:02:13.360
So you can create as many templates as

59
00:02:13.360 --> 00:02:15.240
you want. You can create templates here in

60
00:02:15.240 --> 00:02:17.320
this file. You can create them in a

61
00:02:17.320 --> 00:02:20.220
different file and import them like this.

62
00:02:23.840 --> 00:02:25.000
And so it makes it very easy to

63
00:02:25.000 --> 00:02:26.700
organize and refactor your templates.

64
00:02:26.800 --> 00:02:28.380
If you're just working on a page, you

65
00:02:28.380 --> 00:02:30.260
can just put all the templates in one

66
00:02:30.260 --> 00:02:31.420
file and not worry about it.

67
00:02:31.540 --> 00:02:33.060
As the application gets bigger and bigger, you

68
00:02:33.060 --> 00:02:35.100
want to share templates across your pages.

69
00:02:35.460 --> 00:02:37.160
You can now refactor those into a shared

70
00:02:37.160 --> 00:02:39.060
folder and that will work as well.

71
00:02:39.580 --> 00:02:41.140
Okay, now let's do something a little bit

72
00:02:41.140 --> 00:02:43.640
more interesting. Let's add some reactive data.

73
00:02:43.640 --> 00:02:46.600
Now, we've added something to the

74
00:02:46.600 --> 00:02:48.700
HTML language, some lightweight extensions.

75
00:02:48.940 --> 00:02:50.760
The idea here is we want HTML to

76
00:02:50.760 --> 00:02:53.000
be primary. You should be looking at this

77
00:02:53.000 --> 00:02:55.400
file and thinking this is essentially an HTML

78
00:02:55.400 --> 00:02:58.360
file. It's not JSX, it's not Vue,

79
00:02:58.480 --> 00:03:00.860
it's not a custom language that sort of

80
00:03:00.860 --> 00:03:03.700
sprinkles in HTML. It's just HTML with a

81
00:03:03.700 --> 00:03:05.120
couple of syntax extensions.

82
00:03:05.580 --> 00:03:07.160
The first one that you need to know

83
00:03:07.160 --> 00:03:09.360
about are called constructor attributes.

84
00:03:09.360 --> 00:03:12.160
So at the opening tag for

85
00:03:12.160 --> 00:03:14.980
a template, you can use constructor

86
00:03:14.980 --> 00:03:16.660
-like syntax. Notice the parentheses.

87
00:03:16.940 --> 00:03:17.920
So it's kind of like you're building a

88
00:03:17.920 --> 00:03:20.400
constructor function or something like that.

89
00:03:21.140 --> 00:03:23.520
And inside of that, we can declare constructor

90
00:03:23.520 --> 00:03:25.640
attribute names. We can make them public.

91
00:03:26.220 --> 00:03:27.140
We can make them private.

92
00:03:28.000 --> 00:03:29.260
And by default, they will be public.

93
00:03:29.400 --> 00:03:31.920
That means that when you invoke the template

94
00:03:31.920 --> 00:03:33.280
or you call out to the template, you

95
00:03:33.280 --> 00:03:34.640
can provide a value for that.

96
00:03:34.640 --> 00:03:37.040
So, let's create one that's public by default

97
00:03:37.040 --> 00:03:39.140
called greeting and it will be of type

98
00:03:39.140 --> 00:03:41.980
string and its default value will be something

99
00:03:41.980 --> 00:03:44.080
like a holo universe that we see a

100
00:03:44.080 --> 00:03:44.880
change.

101
00:03:45.480 --> 00:03:47.440
And then I want to thread that through

102
00:03:47.440 --> 00:03:50.120
to the greeting template.

103
00:03:50.320 --> 00:03:52.400
So I can do this or for short

104
00:03:52.400 --> 00:03:54.780
you can just use the identity expression.

105
00:03:55.640 --> 00:03:57.520
And now I need to add that as

106
00:03:57.520 --> 00:04:00.040
a parameter to greeting.

107
00:04:00.180 --> 00:04:01.440
Let me actually just save this and show

108
00:04:01.440 --> 00:04:02.240
you something quickly.

109
00:04:03.400 --> 00:04:04.940
down at the bottom I've got out the

110
00:04:04.940 --> 00:04:06.580
element start program running and so you can

111
00:04:06.580 --> 00:04:08.640
see build errors down here and you can

112
00:04:08.640 --> 00:04:10.200
see that we we actually have an error

113
00:04:10.200 --> 00:04:12.120
it's telling me the template greeting has no

114
00:04:12.120 --> 00:04:14.680
attribute named greeting so the first thing to

115
00:04:14.680 --> 00:04:16.540
note about this is that these templates are

116
00:04:16.540 --> 00:04:18.600
type checked and the reason they're type checked

117
00:04:18.600 --> 00:04:21.020
is because we built the HTML language into

118
00:04:21.020 --> 00:04:23.620
directly into the TypeScript tool chain so when

119
00:04:23.620 --> 00:04:25.760
you're writing HTML code it looks like the

120
00:04:25.760 --> 00:04:28.620
HTML language but it has the symbols and

121
00:04:28.620 --> 00:04:30.640
all the type checking that would expect from

122
00:04:30.640 --> 00:04:32.740
writing regular TypeScript. So what this is telling

123
00:04:32.740 --> 00:04:35.340
us is that there's no attribute called greeting,

124
00:04:35.400 --> 00:04:37.240
so we need to define that, and we

125
00:04:37.240 --> 00:04:39.880
can create a constructor attribute here, and it'll

126
00:04:39.880 --> 00:04:40.660
just be the same.

127
00:04:40.660 --> 00:04:42.220
It's greeting. It's going to be public by

128
00:04:42.220 --> 00:04:43.820
default. In this case, I'm not going to

129
00:04:43.820 --> 00:04:46.900
give it an initializer value, so the

130
00:04:46.900 --> 00:04:48.260
caller will have to provide it.

131
00:04:48.740 --> 00:04:51.840
And then inside of the h1 tag, I'm

132
00:04:51.840 --> 00:04:54.300
going to render that out and save it.

133
00:04:54.460 --> 00:04:56.900
And you'll see that the browser over on

134
00:04:56.900 --> 00:04:58.980
the right updates almost instantly from the hot

135
00:04:58.980 --> 00:05:01.500
module reload. So we've learned a couple of

136
00:05:01.500 --> 00:05:04.300
new things here. We've got this constructor attribute

137
00:05:04.300 --> 00:05:05.800
syntax that's been added.

138
00:05:06.040 --> 00:05:08.260
You can have private or public attributes.

139
00:05:08.680 --> 00:05:11.600
Notice if I make this private, I'll now

140
00:05:11.600 --> 00:05:13.880
get a compiler error because a type checking

141
00:05:13.880 --> 00:05:15.940
error that says that the template greeting cannot

142
00:05:15.940 --> 00:05:18.200
accept the argument for private attribute greeting.

143
00:05:18.320 --> 00:05:19.940
So the attribute exists but it's private.

144
00:05:20.180 --> 00:05:21.220
I cannot pass it in.

145
00:05:21.400 --> 00:05:23.320
I can only modify it or use it

146
00:05:23.320 --> 00:05:24.700
within the template itself.

147
00:05:24.700 --> 00:05:26.060
So we'll go ahead and go ahead and

148
00:05:26.060 --> 00:05:28.180
make it public again, and now we're back

149
00:05:28.180 --> 00:05:29.100
to the green status.

150
00:05:29.100 --> 00:05:32.080
Okay a green state Okay, so we've learned

151
00:05:32.080 --> 00:05:35.040
about constructor attributes and also about

152
00:05:35.040 --> 00:05:37.820
these the expression block syntax

153
00:05:37.820 --> 00:05:40.480
whenever you see a curly brace like this,

154
00:05:40.480 --> 00:05:43.420
it means that it's an expression block and

155
00:05:43.420 --> 00:05:46.040
you can put any typescript expression in there

156
00:05:46.040 --> 00:05:46.860
the

157
00:05:48.060 --> 00:05:51.220
Constructor attributes are kind of like function parameters.

158
00:05:51.220 --> 00:05:53.500
They're lexically scoped, which means if you can

159
00:05:53.500 --> 00:05:56.380
see it inside of the structure

160
00:05:56.380 --> 00:05:58.800
it is available for you to use so

161
00:05:58.800 --> 00:06:00.620
I can see it up here that means

162
00:06:00.620 --> 00:06:03.140
I can use it here and these

163
00:06:03.140 --> 00:06:06.220
constructor attributes are reactive automatically you

164
00:06:06.220 --> 00:06:08.560
don't need to think about that so if

165
00:06:08.560 --> 00:06:10.580
you're passing in an attribute and that attribute

166
00:06:10.580 --> 00:06:13.360
changes the user interface will automatically

167
00:06:13.360 --> 00:06:15.620
update as fast as it possibly can with

168
00:06:15.620 --> 00:06:17.300
whatever the new value is.

169
00:06:18.340 --> 00:06:20.160
One of the cool things you can do

170
00:06:20.160 --> 00:06:22.340
to play around with this is go over

171
00:06:22.340 --> 00:06:24.700
into the browser And there's a special global,

172
00:06:25.420 --> 00:06:27.100
the dollar sign global, that

173
00:06:27.100 --> 00:06:30.000
is bound to the

174
00:06:30.000 --> 00:06:31.980
attributes of the top level template.

175
00:06:32.500 --> 00:06:34.880
And I can change the value of that

176
00:06:34.880 --> 00:06:37.220
constructor attribute directly in my console, which is

177
00:06:37.220 --> 00:06:39.760
super useful for debugging, or if you're building

178
00:06:39.760 --> 00:06:42.400
different states in your user interface, you can

179
00:06:42.400 --> 00:06:44.660
see those different states just by changing this

180
00:06:44.660 --> 00:06:47.800
value. So let's change it to something iconic

181
00:06:47.800 --> 00:06:49.800
like boom. And there we go.

182
00:06:49.920 --> 00:06:52.340
The user interface has updated automatically with that

183
00:06:52.340 --> 00:06:55.120
new value. So I find that that ability

184
00:06:55.120 --> 00:06:57.540
to change the data, see that the user

185
00:06:57.540 --> 00:06:59.800
interface updates right away is a much more

186
00:06:59.800 --> 00:07:01.960
effective way to work with the user interface

187
00:07:02.720 --> 00:07:05.700
than working with abstractions like runes or

188
00:07:05.700 --> 00:07:07.720
some function call you have to make that's

189
00:07:07.720 --> 00:07:09.460
not accessible and we can't really hack that

190
00:07:09.460 --> 00:07:11.460
very well. Okay, so we've got a very

191
00:07:11.460 --> 00:07:14.620
basic HTML template here with a child template

192
00:07:14.620 --> 00:07:17.280
called greeting. We've threaded through this constructor attribute.

193
00:07:17.800 --> 00:07:20.120
Now, next up, let's get rid of the

194
00:07:20.120 --> 00:07:20.820
default

195
00:07:20.820 --> 00:07:24.020
value there,

196
00:07:24.120 --> 00:07:25.660
press Save, and we're going to be back

197
00:07:25.660 --> 00:07:26.500
to an error now.

198
00:07:27.100 --> 00:07:28.500
What this is showing us is that the

199
00:07:28.500 --> 00:07:31.320
route function, if you're used to working with

200
00:07:31.320 --> 00:07:33.620
other web frameworks, you know about routes, and

201
00:07:33.620 --> 00:07:34.420
in Elements,

202
00:07:35.720 --> 00:07:37.260
the route is a function.

203
00:07:37.420 --> 00:07:38.240
It's actually in code.

204
00:07:38.320 --> 00:07:39.760
We don't use any kind of special magic

205
00:07:39.760 --> 00:07:41.940
with your file system or directory paths or

206
00:07:41.940 --> 00:07:44.700
anything like that. It's just actually a function,

207
00:07:44.900 --> 00:07:45.720
so let's go find it.

208
00:07:45.720 --> 00:07:48.780
Home index and this is what the function

209
00:07:48.780 --> 00:07:50.280
looks like. It has a request and a

210
00:07:50.280 --> 00:07:51.960
response It kind of looks like a regular

211
00:07:51.960 --> 00:07:54.420
node .js server request response

212
00:07:54.420 --> 00:07:57.580
function And we're going to return a

213
00:07:57.580 --> 00:08:00.780
new instance of this HTML You

214
00:08:00.780 --> 00:08:02.220
can think of it as a class really

215
00:08:02.220 --> 00:08:03.740
and where did that come from?

216
00:08:03.740 --> 00:08:06.200
We imported it as the default from the

217
00:08:06.200 --> 00:08:07.540
template file. So HTML

218
00:08:08.480 --> 00:08:11.460
the HTML symbol is Exported here as the

219
00:08:11.460 --> 00:08:14.160
default in any name templates will be exported

220
00:08:14.160 --> 00:08:16.080
as a name So if we wanted to

221
00:08:16.080 --> 00:08:17.780
get access to that named one, we could

222
00:08:17.780 --> 00:08:18.760
do something like this.

223
00:08:20.140 --> 00:08:22.980
But for routes, we generally just, we import

224
00:08:22.980 --> 00:08:23.780
the HTML.

225
00:08:25.120 --> 00:08:27.400
And this now needs to take an attribute.

226
00:08:27.580 --> 00:08:29.400
So what it's telling us is that the

227
00:08:29.400 --> 00:08:31.560
error is that it's expecting one argument, it

228
00:08:31.560 --> 00:08:33.040
got none. So let me give it an

229
00:08:33.040 --> 00:08:34.360
empty object. Now we have a new error

230
00:08:34.360 --> 00:08:36.140
that says, actually, it also needs greeting.

231
00:08:39.180 --> 00:08:39.900
All right, we've got to come up with

232
00:08:39.900 --> 00:08:42.320
something new now. So there we go.

233
00:08:42.680 --> 00:08:43.620
So we can see it change.

234
00:08:43.620 --> 00:08:46.160
Okay so we're passing data from the route

235
00:08:46.160 --> 00:08:47.900
into the HTML file and when I save

236
00:08:47.900 --> 00:08:50.320
it the browser over on the right is

237
00:08:50.320 --> 00:08:52.680
updated right away. Now going up one more

238
00:08:52.680 --> 00:08:54.520
level where does this route actually get used?

239
00:08:55.320 --> 00:08:56.500
This isn't supposed to be a video about

240
00:08:56.500 --> 00:08:57.660
routing but I just want to give you

241
00:08:57.660 --> 00:08:59.060
a sense of what's happening so it's not

242
00:08:59.060 --> 00:09:01.520
so magical. Notice that the route function gets

243
00:09:01.520 --> 00:09:04.700
called on the application and the URL this

244
00:09:04.700 --> 00:09:06.960
is the home URL is mapping to this

245
00:09:06.960 --> 00:09:09.940
home function which we imported up here and

246
00:09:09.940 --> 00:09:11.900
the home function is that route that we

247
00:09:11.900 --> 00:09:12.760
we're just looking at.

248
00:09:13.200 --> 00:09:14.600
All right let's go back to HTML.

249
00:09:16.440 --> 00:09:18.960
Now let's say that you want to bind

250
00:09:18.960 --> 00:09:21.800
to a form. Oftentimes when we're working with

251
00:09:21.800 --> 00:09:24.860
forms the data it's kind of complicated

252
00:09:24.860 --> 00:09:27.220
to keep the user interface in check or

253
00:09:27.220 --> 00:09:30.200
in synchronize in sync with the data but

254
00:09:30.200 --> 00:09:31.820
in Elements that happens automatically.

255
00:09:32.540 --> 00:09:35.380
So if I create a function let me

256
00:09:35.380 --> 00:09:37.480
actually just wipe this out and start fresh

257
00:09:37.480 --> 00:09:39.260
here. So let me walk through this.

258
00:09:39.380 --> 00:09:40.720
We have an interface that's just a normal

259
00:09:40.720 --> 00:09:43.060
TypeScript interface called form and it has a

260
00:09:43.060 --> 00:09:46.160
field called email and our form has

261
00:09:46.160 --> 00:09:48.560
a default initializer in the constructor attributes so

262
00:09:48.560 --> 00:09:50.200
we don't have to pass it in through

263
00:09:50.200 --> 00:09:52.500
the route. For now we just want to

264
00:09:52.500 --> 00:09:53.640
demonstrate the two -way binding.

265
00:09:54.600 --> 00:09:56.500
And then down in the input underneath the

266
00:09:56.500 --> 00:09:58.800
form tag we have a value that is

267
00:09:58.800 --> 00:10:00.020
set to form .email.

268
00:10:00.560 --> 00:10:02.740
So what we do here is the input

269
00:10:02.740 --> 00:10:05.240
is going to be bound automatically,

270
00:10:05.820 --> 00:10:08.340
it's value to form email, so if I

271
00:10:08.340 --> 00:10:10.640
were to put something like hello at Elements

272
00:10:10.640 --> 00:10:13.700
dev, that will show up in the

273
00:10:13.700 --> 00:10:16.880
form field. But it's automatically two -way bound,

274
00:10:17.120 --> 00:10:18.780
and that means that if I change this,

275
00:10:19.160 --> 00:10:20.840
let's just change it to say example,

276
00:10:22.200 --> 00:10:23.440
and let me go down into the console

277
00:10:23.440 --> 00:10:26.220
and type form email, that

278
00:10:26.220 --> 00:10:28.440
has now been automatically updated as well.

279
00:10:28.440 --> 00:10:31.100
So the data stays in sync with the

280
00:10:31.100 --> 00:10:32.900
user interface. And if I change the data

281
00:10:32.900 --> 00:10:33.700
here,

282
00:10:34.840 --> 00:10:36.280
I don't know, what do we want to

283
00:10:36.280 --> 00:10:37.080
do?

284
00:10:37.860 --> 00:10:38.920
Support, how about that?

285
00:10:39.580 --> 00:10:40.380
Elements .dev.

286
00:10:41.560 --> 00:10:43.340
Note the user interface up in the top

287
00:10:43.340 --> 00:10:44.800
updates. That's what it means to be two

288
00:10:44.800 --> 00:10:45.600
-way bound.

289
00:10:46.300 --> 00:10:47.280
And I just wanted to give you a

290
00:10:47.280 --> 00:10:48.540
quick sense of that here.

291
00:10:48.700 --> 00:10:49.760
We don't have to go through every single

292
00:10:49.760 --> 00:10:51.260
example. You can read the manual for that.

293
00:10:51.640 --> 00:10:53.800
But hopefully, this gives you a sense of

294
00:10:53.800 --> 00:10:55.440
how that works. All right, next up, let's

295
00:10:55.440 --> 00:10:58.240
look at event handlers and how we

296
00:10:58.240 --> 00:11:00.180
change state by

297
00:11:00.180 --> 00:11:02.780
responding to some kind of event.

298
00:11:02.940 --> 00:11:04.560
So let's create a toggle button.

299
00:11:05.180 --> 00:11:07.620
And the toggle button will be

300
00:11:07.620 --> 00:11:11.680
something

301
00:11:11.680 --> 00:11:12.500
like this.

302
00:11:15.220 --> 00:11:17.900
We're gonna add an event handler on click.

303
00:11:18.500 --> 00:11:19.580
And when we click this,

304
00:11:20.480 --> 00:11:23.220
I want to set this constructor attribute, which

305
00:11:23.220 --> 00:11:24.860
I'll create in a second, to the opposite

306
00:11:24.860 --> 00:11:26.480
of whatever it was before

307
00:11:26.480 --> 00:11:28.880
and what we'll do

308
00:11:28.880 --> 00:11:31.880
is if the constructor attribute active

309
00:11:31.880 --> 00:11:35.020
is true or truthy then we'll add the

310
00:11:35.020 --> 00:11:38.000
is primary class CSS class to the button

311
00:11:38.000 --> 00:11:39.860
now this is a little bit of special

312
00:11:39.860 --> 00:11:41.280
new syntax here so let me to walk

313
00:11:41.280 --> 00:11:43.060
you through it whenever you see the braces

314
00:11:43.060 --> 00:11:44.620
it means you're about to see some typescript

315
00:11:44.620 --> 00:11:46.920
expression inside of there if you put an

316
00:11:46.920 --> 00:11:49.620
array you could have multiple items here for

317
00:11:49.620 --> 00:11:51.620
example we might have something like toggle

318
00:11:51.620 --> 00:11:54.480
and then the second one and the third

319
00:11:54.480 --> 00:11:55.280
one and fourth one.

320
00:11:55.460 --> 00:11:57.380
If any of the items are false, so

321
00:11:57.380 --> 00:11:59.460
for example, let's say active is false, the

322
00:11:59.460 --> 00:12:00.860
right -hand side of this expression will not

323
00:12:00.860 --> 00:12:03.060
evaluate and this will be false and we'll

324
00:12:03.060 --> 00:12:04.380
drop that from the class list.

325
00:12:04.560 --> 00:12:06.700
So this is a nice convenient way of

326
00:12:06.700 --> 00:12:08.440
being able to string together a bunch of

327
00:12:08.440 --> 00:12:10.740
different CSS classes automatically.

328
00:12:11.340 --> 00:12:12.940
And if any of them are false, we

329
00:12:12.940 --> 00:12:15.360
just drop it rather than putting like false

330
00:12:15.360 --> 00:12:17.060
or undefined or something like that into the

331
00:12:17.060 --> 00:12:19.100
class list. Okay, so I'll leave that.

332
00:12:19.100 --> 00:12:21.220
Let's just delete it so we can see

333
00:12:21.220 --> 00:12:22.660
the full line and we're gonna get an

334
00:12:22.660 --> 00:12:25.780
error because we haven't defined active yet So

335
00:12:25.780 --> 00:12:27.800
let's create that as a private variable this

336
00:12:27.800 --> 00:12:30.940
time private constructor attribute And I'll call it

337
00:12:30.940 --> 00:12:33.300
active. It's of type boolean and by default

338
00:12:33.300 --> 00:12:34.980
by default. We'll just set it to false

339
00:12:38.220 --> 00:12:39.180
Great now

340
00:12:40.680 --> 00:12:42.600
Notice what we've done here in the on

341
00:12:42.600 --> 00:12:45.500
click event handler we've done an assignment and

342
00:12:45.500 --> 00:12:48.520
we're changing the value of this variable to

343
00:12:49.240 --> 00:12:51.200
This syntax here says, if it was true

344
00:12:51.200 --> 00:12:52.020
before, make it false.

345
00:12:52.160 --> 00:12:53.480
If it was false before, make it true.

346
00:12:53.560 --> 00:12:54.980
Make it the opposite of what it was

347
00:12:54.980 --> 00:12:57.780
before. As soon as this value changes,

348
00:12:58.540 --> 00:13:01.160
that's going to reactively update the class that

349
00:13:01.160 --> 00:13:03.240
we apply. And that will change the styling

350
00:13:03.240 --> 00:13:04.860
of this toggle button.

351
00:13:05.660 --> 00:13:07.560
All right, let me save and make sure

352
00:13:07.560 --> 00:13:08.960
that this works. So come over and we'll

353
00:13:08.960 --> 00:13:11.220
click the button. And now it gets that

354
00:13:11.220 --> 00:13:13.620
special styling for

355
00:13:13.620 --> 00:13:15.940
isPrimary. Let's open up Elements,

356
00:13:17.280 --> 00:13:19.540
different Elements. This is the HTML elements down

357
00:13:19.540 --> 00:13:20.860
here and see that we can see it

358
00:13:20.860 --> 00:13:22.240
so see the class is primary

359
00:13:23.160 --> 00:13:24.980
Now, let me click it again, and now

360
00:13:24.980 --> 00:13:25.780
it goes away

361
00:13:27.800 --> 00:13:30.700
Okay, so that's the data re the user

362
00:13:30.700 --> 00:13:31.660
interface reacting

363
00:13:32.960 --> 00:13:35.960
Automatically to the reactive data and this

364
00:13:35.960 --> 00:13:36.760
active is

365
00:13:38.120 --> 00:13:40.760
Accessible inside this callback function because it's in

366
00:13:40.760 --> 00:13:43.440
scope So we say that that's lexically scoped

367
00:13:43.440 --> 00:13:45.260
and for the uninitialized what that means is

368
00:13:45.260 --> 00:13:47.080
if you can see it it's just like

369
00:13:47.080 --> 00:13:48.380
a function. Think of it like a function

370
00:13:48.380 --> 00:13:49.180
that has parameters.

371
00:13:50.020 --> 00:13:51.140
And anywhere in the function,

372
00:13:52.320 --> 00:13:54.300
however many nested blocks you have inside the

373
00:13:54.300 --> 00:13:57.240
function, the parameters that are above are visible

374
00:13:57.240 --> 00:13:58.640
all the way down that the chain.

375
00:13:58.800 --> 00:14:00.940
So this active variable is visible here.

376
00:14:02.320 --> 00:14:03.460
Now, if you wanted to, you could also

377
00:14:03.460 --> 00:14:06.400
pass that to a function.

378
00:14:06.480 --> 00:14:09.180
So we might say on click and we're

379
00:14:09.180 --> 00:14:12.140
going to pass it a active

380
00:14:12.140 --> 00:14:14.060
and you might return

381
00:14:14.060 --> 00:14:16.280
the new value.

382
00:14:18.800 --> 00:14:20.740
And I could assign that

383
00:14:20.740 --> 00:14:23.600
to the result like

384
00:14:23.600 --> 00:14:24.400
this.

385
00:14:25.480 --> 00:14:28.180
And notice I'm passing the value and then

386
00:14:28.180 --> 00:14:30.220
I'm assigning the new value to

387
00:14:30.220 --> 00:14:33.160
the constructor attribute here.

388
00:14:33.160 --> 00:14:35.380
If I pass the value and change it

389
00:14:35.380 --> 00:14:37.020
inside of this function, it's not going to

390
00:14:37.020 --> 00:14:40.120
update properly, just for the same reason that

391
00:14:40.120 --> 00:14:43.160
you can't change any primitive values inside

392
00:14:43.160 --> 00:14:44.160
of a JavaScript function.

393
00:14:44.800 --> 00:14:45.940
And so you can either assign it as

394
00:14:45.940 --> 00:14:47.520
the return value or I can pass an

395
00:14:47.520 --> 00:14:50.500
object like the form that

396
00:14:50.500 --> 00:14:52.320
has active as a field and then you

397
00:14:52.320 --> 00:14:53.240
can update it that way.

398
00:14:53.420 --> 00:14:55.220
So let's make sure this still works.

399
00:14:56.460 --> 00:14:57.260
There we go.

400
00:14:57.720 --> 00:14:59.480
Okay, so this is just a quick tour

401
00:14:59.480 --> 00:15:02.000
of the HTML language and its syntax

402
00:15:02.640 --> 00:15:04.540
And I think it's a really, really great

403
00:15:04.540 --> 00:15:07.640
way to write sophisticated user interfaces that react

404
00:15:07.640 --> 00:15:09.920
automatically to data. This is something that's been

405
00:15:09.920 --> 00:15:11.600
proven, a concept that's been proven over the

406
00:15:11.600 --> 00:15:13.880
past decade to be a very effective way

407
00:15:13.880 --> 00:15:15.280
to write complicated applications.

408
00:15:15.540 --> 00:15:17.300
And all the applications I've written, and some

409
00:15:17.300 --> 00:15:19.760
of which are very, very large, and financial

410
00:15:19.760 --> 00:15:22.680
service applications, and healthcare services, and things like

411
00:15:22.680 --> 00:15:24.300
that, and you end up with tons and

412
00:15:24.300 --> 00:15:25.320
tons and tons of pages.

413
00:15:25.920 --> 00:15:27.440
And you need a way to organize them

414
00:15:27.440 --> 00:15:28.780
in a way so that you can just

415
00:15:28.780 --> 00:15:31.020
keep building without worrying about the structure getting

416
00:15:31.020 --> 00:15:32.960
completely out of control so you really need

417
00:15:32.960 --> 00:15:36.020
a way of organizing user interface functionality into

418
00:15:36.020 --> 00:15:38.480
essentially functions or templates

419
00:15:38.480 --> 00:15:41.020
and this

420
00:15:41.020 --> 00:15:42.760
does a really good job of that now

421
00:15:42.760 --> 00:15:44.600
why not react so when we started in

422
00:15:44.600 --> 00:15:47.760
2012 react actually didn't exist yet so

423
00:15:47.760 --> 00:15:50.840
Elements began as an HTML language

424
00:15:50.840 --> 00:15:52.260
believe it or not but the first sketches

425
00:15:52.260 --> 00:15:53.840
I wish I could show you a sketch

426
00:15:53.840 --> 00:15:55.280
but I've got it in my notebook from

427
00:15:55.280 --> 00:16:13.990
2012 and the reason I did that was

428
00:16:13.990 --> 00:16:16.450
because I thought the way to build

429
00:16:16.450 --> 00:16:18.470
user interfaces with

430
00:16:18.470 --> 00:16:21.270
reflecting a state machine or reflecting

431
00:16:21.270 --> 00:16:24.470
data that changes automatically, the user interface was

432
00:16:24.470 --> 00:16:25.650
a really, really good idea.

433
00:16:26.490 --> 00:16:27.890
But you also wanted to have things like

434
00:16:27.890 --> 00:16:29.730
server side rendering. If you look at these

435
00:16:29.730 --> 00:16:30.530
pages,

436
00:16:30.930 --> 00:16:33.650
if I do a view page source,

437
00:16:34.910 --> 00:16:35.930
might be a little hard to see, but

438
00:16:35.930 --> 00:16:39.070
you'll see that the HTML is rendered directly

439
00:16:39.070 --> 00:16:40.310
from the server first.

440
00:16:40.310 --> 00:16:43.250
So there's no blank page

441
00:16:43.250 --> 00:16:45.410
that then gets hydrated on the client.

442
00:16:45.550 --> 00:16:48.330
You always get the server side HTML

443
00:16:48.330 --> 00:16:51.310
first, and then it gets attached in the

444
00:16:51.310 --> 00:16:53.590
browser automatically. That's how HTML works, and you

445
00:16:53.590 --> 00:16:54.390
don't have to configure that.

446
00:16:54.410 --> 00:16:55.210
It just works automatically.

447
00:16:55.370 --> 00:16:58.250
There's no hydration errors that are possible by

448
00:16:58.250 --> 00:16:59.050
construction.

449
00:16:59.910 --> 00:17:00.830
The other thing we wanted to do is

450
00:17:00.830 --> 00:17:02.690
to make sure that the reactivity is pushed

451
00:17:02.690 --> 00:17:05.190
into the runtime, such that whether it's your

452
00:17:05.190 --> 00:17:07.150
agent working or you're working, when you're writing

453
00:17:07.150 --> 00:17:09.070
HTML, you don't want to be thinking about

454
00:17:09.070 --> 00:17:11.490
these abstractions,

455
00:17:12.330 --> 00:17:14.810
reactivity abstractions. That's a lot of cognitive overhead

456
00:17:14.810 --> 00:17:17.170
to think through that, and you can get

457
00:17:17.170 --> 00:17:18.690
it wrong, and you can have performance problems.

458
00:17:19.230 --> 00:17:21.090
So we really just wanted you to declare,

459
00:17:21.790 --> 00:17:24.190
using HTML, what it should look like

460
00:17:24.190 --> 00:17:26.790
and have the data very clearly

461
00:17:26.790 --> 00:17:29.270
in the attributes or in these expression blocks,

462
00:17:29.590 --> 00:17:31.830
and then the runtime and the compiler takes

463
00:17:31.830 --> 00:17:33.750
care of making sure that everything is updated

464
00:17:33.750 --> 00:17:35.790
automatically as performantly as possible.

465
00:17:50.670 --> 00:17:53.650
But TypeScript has JSX and React baked

466
00:17:53.650 --> 00:17:55.490
in, so it would be natural for us

467
00:17:55.490 --> 00:17:58.570
to support React and to just have it

468
00:17:58.570 --> 00:17:59.550
be the default.

469
00:18:00.630 --> 00:18:02.710
But what we found was that

470
00:18:02.710 --> 00:18:05.570
it's very hard for first of all beginners

471
00:18:05.570 --> 00:18:07.530
to get started with React because there's an

472
00:18:07.530 --> 00:18:09.150
insane number of abstractions.

473
00:18:10.070 --> 00:18:12.530
And the APIs change a lot.

474
00:18:13.650 --> 00:18:16.710
There's issues with the runtime being not performant

475
00:18:16.710 --> 00:18:17.590
in some cases.

476
00:18:18.910 --> 00:18:20.730
But really the hard part is just getting

477
00:18:20.730 --> 00:18:23.530
started and working your way around React and

478
00:18:23.530 --> 00:18:26.150
JSX is I found not to be a

479
00:18:26.150 --> 00:18:28.810
good user experience. And I had numerous issues

480
00:18:28.810 --> 00:18:31.610
with it. And when I was teaching back

481
00:18:31.610 --> 00:18:33.390
in the day, people would get very confused

482
00:18:33.390 --> 00:18:34.730
by what was happening.

483
00:18:34.930 --> 00:18:37.010
So I just felt like it wasn't a

484
00:18:37.010 --> 00:18:38.970
great user experience and I didn't want our

485
00:18:38.970 --> 00:18:40.230
users to have to struggle with that.

486
00:18:40.590 --> 00:18:42.630
I made that decision before AI even became

487
00:18:42.630 --> 00:18:45.670
a big deal. And once AI became a

488
00:18:45.670 --> 00:18:46.470
big deal,

489
00:18:47.070 --> 00:18:49.590
we thought, well, now it really makes sense

490
00:18:49.590 --> 00:18:51.970
to have a new HTML language because

491
00:18:51.970 --> 00:18:54.890
the React kind of lock -in effect

492
00:18:54.890 --> 00:18:57.730
from ecosystem size and all that just doesn't

493
00:18:57.730 --> 00:19:00.910
really matter anymore. So the agent obviously knows

494
00:19:00.910 --> 00:19:03.810
HTML. It has more HTML on its training

495
00:19:03.810 --> 00:19:06.030
data than it has JSX.

496
00:19:06.290 --> 00:19:07.730
And to be clear, I can write JSX

497
00:19:07.730 --> 00:19:10.010
fine. React obviously has a lot

498
00:19:10.010 --> 00:19:13.230
of

499
00:19:13.230 --> 00:19:15.350
struggle with HTML, this is not a problem.

500
00:19:15.590 --> 00:19:18.010
So the new HTML language and Elements

501
00:19:18.010 --> 00:19:20.890
works really, really well with agents.

502
00:19:21.030 --> 00:19:23.270
But what was surprising was they actually do

503
00:19:23.270 --> 00:19:26.310
better with it because the lexically

504
00:19:26.310 --> 00:19:28.750
scoped constructor attributes, the automatic

505
00:19:28.750 --> 00:19:31.710
reactivity, all of that lets the agent

506
00:19:31.710 --> 00:19:34.630
focus exclusively on the presentation and just

507
00:19:34.630 --> 00:19:37.470
writing out that presentation code and not on

508
00:19:37.470 --> 00:19:39.830
higher order abstractions. And so that saves a

509
00:19:39.830 --> 00:19:42.070
little bit on tokens, and also empirically we

510
00:19:42.070 --> 00:19:43.810
found gives you less buggy

511
00:19:43.810 --> 00:19:45.950
user interfaces.

512
00:19:46.770 --> 00:19:48.350
And it's also, as a side benefit, just

513
00:19:48.350 --> 00:19:51.070
easier, we believe, for humans to read this

514
00:19:51.070 --> 00:19:51.870
code.

515
00:19:52.390 --> 00:19:55.170
So all in all, a syntax that's

516
00:19:55.170 --> 00:19:57.930
essentially just HTML with some lightweight extensions,

517
00:19:58.690 --> 00:20:01.130
all of the reactivity and complexity is pushed

518
00:20:01.130 --> 00:20:03.470
into the runtime, so the runtime makes sure

519
00:20:03.470 --> 00:20:05.470
that it does the most performant thing every

520
00:20:05.470 --> 00:20:07.710
time by construction, or at least that's That's

521
00:20:07.710 --> 00:20:09.590
the goal. I think we achieve it in

522
00:20:09.590 --> 00:20:12.330
most cases, and we don't want the user

523
00:20:12.330 --> 00:20:14.210
to have to think about re -rendering loops

524
00:20:14.210 --> 00:20:15.050
or anything like that.

525
00:20:15.130 --> 00:20:17.990
There's no diffing trees that happen in

526
00:20:17.990 --> 00:20:21.070
Elements. It just updates surgically the specific

527
00:20:21.070 --> 00:20:23.730
piece of UI that has to be updated.

528
00:20:31.870 --> 00:20:33.810
And we wanted it to be very debuggable

529
00:20:33.810 --> 00:20:35.570
and easy to work with, hence being able

530
00:20:35.570 --> 00:20:37.150
to go into the console here and just

531
00:20:37.150 --> 00:20:38.870
update the data and see your user interface

532
00:20:38.870 --> 00:20:41.390
update. So the last part of that became,

533
00:20:42.050 --> 00:20:44.190
well, what about all the extra user interface

534
00:20:44.190 --> 00:20:46.710
templates that exist and components that exist in

535
00:20:46.710 --> 00:20:49.330
the React ecosystem. And don't we want to

536
00:20:49.330 --> 00:20:51.470
be able to use that?

537
00:20:52.450 --> 00:20:55.150
And there's two answers to that.

538
00:20:55.370 --> 00:20:58.230
So first, you'd be surprised at how effective

539
00:20:58.230 --> 00:21:01.150
an agent is at writing extremely complicated

540
00:21:01.150 --> 00:21:03.810
HTML. It can do that very, very well.

541
00:21:04.450 --> 00:21:07.090
And so even with no templating library, even

542
00:21:07.090 --> 00:21:09.850
before we built Elements UI, which I'll tell

543
00:21:09.850 --> 00:21:12.230
you about in a second, we found that

544
00:21:12.230 --> 00:21:14.990
the agents worked very, very well with HTML

545
00:21:14.990 --> 00:21:17.410
as a with Elements HTML as a primitive

546
00:21:17.410 --> 00:21:19.310
and so it could build very complicated things

547
00:21:19.310 --> 00:21:22.310
automatically but just to be sure

548
00:21:22.310 --> 00:21:25.090
and also because we don't think reinventing everything

549
00:21:25.090 --> 00:21:26.690
every single time makes a lot of sense

550
00:21:26.690 --> 00:21:29.590
there are a number of user interface

551
00:21:29.590 --> 00:21:32.770
elements that essentially every application needs and

552
00:21:32.770 --> 00:21:34.810
so we took many months to build a

553
00:21:34.810 --> 00:21:37.790
professional style system and also roughly

554
00:21:37.790 --> 00:21:40.230
between 70 80 something of the order of

555
00:21:40.230 --> 00:21:43.350
that templates that are reusable that you

556
00:21:43.350 --> 00:21:44.910
can use. So you should recognize if you're

557
00:21:44.910 --> 00:21:47.330
in the React community or any of the

558
00:21:47.330 --> 00:21:50.310
other communities, you'll tend to see these recurring

559
00:21:50.310 --> 00:21:52.610
types of templates, like button, button group.

560
00:21:53.090 --> 00:21:54.330
If you scroll down the left -hand side

561
00:21:54.330 --> 00:21:57.190
here, you'll see various types of overlays, displays.

562
00:21:58.310 --> 00:21:59.990
And we even have some complicated ones, like

563
00:21:59.990 --> 00:22:02.430
we have a data table that you can

564
00:22:02.430 --> 00:22:03.610
use to replace spreadsheets.

565
00:22:04.270 --> 00:22:05.530
So if you're trying to build an application,

566
00:22:06.590 --> 00:22:08.370
if you've built something in Retool, for example,

567
00:22:08.430 --> 00:22:09.970
or one of the low code or no

568
00:22:09.970 --> 00:22:12.950
code user interface builders, you'll recognize

569
00:22:12.950 --> 00:22:14.190
something like this data table.

570
00:22:14.210 --> 00:22:15.310
We've got a Kanban.

571
00:22:15.610 --> 00:22:16.950
I don't know if I pronounced that correctly.

572
00:22:17.550 --> 00:22:20.590
We've got charts and area

573
00:22:20.590 --> 00:22:23.650
charts, bar charts. We've got stuff for

574
00:22:23.650 --> 00:22:25.450
chat, for

575
00:22:25.450 --> 00:22:28.550
prompting. So if you're building something

576
00:22:28.550 --> 00:22:31.290
that is kind of like an AI prompt,

577
00:22:31.410 --> 00:22:32.470
you can use that.

578
00:22:32.610 --> 00:22:35.510
So we've got all kinds of reusable

579
00:22:35.510 --> 00:22:38.070
templates and a style system that lets you

580
00:22:38.070 --> 00:22:41.130
build up a beautiful user interface

581
00:22:41.130 --> 00:22:44.270
and it gets out of

582
00:22:44.270 --> 00:22:45.710
your way. So if you want to just

583
00:22:45.710 --> 00:22:47.530
use the style system directly, you can use

584
00:22:47.530 --> 00:22:49.010
that. You can build your own templates that

585
00:22:49.010 --> 00:22:50.670
way. So we try to build this so

586
00:22:50.670 --> 00:22:52.570
that the abstractions do not get in the

587
00:22:52.570 --> 00:22:55.030
way of a human or an agent, but

588
00:22:55.030 --> 00:22:58.090
we have enough of the things built such

589
00:22:58.090 --> 00:23:00.710
that you can make ferocious progress right away.

590
00:23:00.830 --> 00:23:02.390
So all in all, I believe this is

591
00:23:02.390 --> 00:23:05.430
probably the best way today to build user

592
00:23:05.430 --> 00:23:06.430
interfaces on the web.

593
00:23:06.810 --> 00:23:08.610
And it's a super exciting time for me

594
00:23:08.610 --> 00:23:10.050
to release this because I've spent so many

595
00:23:10.050 --> 00:23:11.550
years in this language.

596
00:23:11.730 --> 00:23:14.450
You would think that given the HTML language

597
00:23:14.450 --> 00:23:17.330
itself already exists, that there wouldn't be too

598
00:23:17.330 --> 00:23:18.370
much work to do, but it turns out

599
00:23:18.370 --> 00:23:19.870
there's a lot of things you have to

600
00:23:19.870 --> 00:23:20.670
think through.

601
00:23:21.190 --> 00:23:23.710
Special thanks to the Microsoft team for

602
00:23:23.710 --> 00:23:25.870
porting their TypeScript to the Golang

603
00:23:25.870 --> 00:23:28.850
language. We've made extensive

604
00:23:28.850 --> 00:23:31.970
use of that and we built

605
00:23:31.970 --> 00:23:34.690
this into the TypeScript tool chain such that

606
00:23:34.690 --> 00:23:37.190
the symbols are just TypeScript symbols.

607
00:23:37.190 --> 00:23:37.990
If you,

608
00:23:38.470 --> 00:23:39.890
in my editor here,

609
00:23:40.570 --> 00:23:43.550
try to go to the reference of

610
00:23:43.550 --> 00:23:45.870
any of these templates, it will take you

611
00:23:45.870 --> 00:23:47.150
right there. You can do a find replace.

612
00:23:48.190 --> 00:23:50.490
This is just thought of as TypeScript code

613
00:23:50.490 --> 00:23:52.870
under the hood. And that's what gives us

614
00:23:52.870 --> 00:23:55.650
these strongly typed constructor attributes and

615
00:23:55.650 --> 00:23:57.470
with a little bit of extra syntax for

616
00:23:57.470 --> 00:23:59.450
things like the constructor attribute definitions.

617
00:24:00.330 --> 00:24:03.450
But really, this is just TypeScript with

618
00:24:03.450 --> 00:24:06.330
an HTML extension to the TypeScript

619
00:24:06.330 --> 00:24:08.450
language built directly into the tool chain.

620
00:24:09.450 --> 00:24:10.430
So I hope this gives you a really,

621
00:24:11.010 --> 00:24:13.050
probably more comprehensive than I expected going into

622
00:24:13.050 --> 00:24:15.410
this overview of Elements HTML.

623
00:24:15.930 --> 00:24:17.990
And let me know if you've got any questions in the comments.
