All language subtitles for 15. Working with localStorage

af Afrikaans
ak Akan
sq Albanian
am Amharic
ar Arabic
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bem Bemba
bn Bengali
bh Bihari
bs Bosnian
br Breton
bg Bulgarian
km Cambodian
ca Catalan
ceb Cebuano
chr Cherokee
ny Chichewa
zh-CN Chinese (Simplified)
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
ee Ewe
fo Faroese
tl Filipino
fi Finnish
fr French
fy Frisian
gaa Ga
gl Galician
ka Georgian
de German
el Greek
gn Guarani
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
hu Hungarian
is Icelandic
ig Igbo
id Indonesian
ia Interlingua
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
rw Kinyarwanda
rn Kirundi
kg Kongo
ko Korean
kri Krio (Sierra Leone)
ku Kurdish
ckb Kurdish (Soranรฎ)
ky Kyrgyz
lo Laothian
la Latin
lv Latvian
ln Lingala
lt Lithuanian
loz Lozi
lg Luganda
ach Luo
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mfe Mauritian Creole
mo Moldavian
mn Mongolian
my Myanmar (Burmese)
sr-ME Montenegrin
ne Nepali
pcm Nigerian Pidgin
nso Northern Sotho
no Norwegian
nn Norwegian (Nynorsk)
oc Occitan
or Oriya
om Oromo
ps Pashto
pl Polish
pt-BR Portuguese (Brazil)
pt Portuguese (Portugal)
pa Punjabi
qu Quechua
ro Romanian
rm Romansh
nyn Runyakitara
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
sh Serbo-Croatian
st Sesotho
tn Setswana
crs Seychellois Creole
sn Shona
sd Sindhi
si Sinhalese
sk Slovak
sl Slovenian
so Somali
es Spanish
es-419 Spanish (Latin American)
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
tt Tatar
te Telugu
th Thai
ti Tigrinya
to Tonga
lua Tshiluba
tum Tumbuka
tr Turkish
tk Turkmen
tw Twi
ug Uighur
uk Ukrainian
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
wo Wolof
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu

Original subtitles

1 1

Let's now use the local storage API 2

2

in order to make the workout data 3

3

persist across multiple page reloads. 4

4

And let's start with a look at our flowchart 5

5

so that we can see exactly what we have to implement. 6

6

So basically the idea is that 7

7

whenever a new workout is added, 8

8

then all the workouts will be added to local storage. 9

9

And so local storage is basically a place in the browser, 10

10

where we can store data that will stay there 11

11

even after we close the page. 12

12

So basically the data is basically linked to the URL 13

13

on which we are using the application. 14

14

So, again whenever there is a new workout, 15

15

we will take the entire workouts array 16

16

and store it in local storage. 17

17

And then whenever the page loads, 18

18

so up here in this event, 19

19

then we will load all the workouts from the local storage, 20

20

and render them on the map and also on the list. 21

21

So just like we do it when a user submits a new workout. 22

22

And so like this, when you reload the page, 23

23

it will then appear 24

24

as if all the workouts you had previously 25

25

are still in the same place. 26

26

And hopefully this makes sense, 27

27

and so let's now get started, 28

28

and we will start with this part here. 29

29

So storing all the workouts in local storage, 30

30

and remember that happens 31

31

whenever the user creates a new workout. 32

32

And so we have to get started in the new workout method. 33

33

So down here, we need to add yet another point. 34

34

So set local storage to all workouts. 35

35

And here I'm actually gonna create yet another method, 36

36

so that we can keep this method here, 37

37

basically nice and clean. 38

38

So as you see, this new workout method here 39

39

is basically a bit of a method that does delegation. 40

40

So we do some stuff here, of course, 41

41

but then once we're done creating the actual object, 42

42

then down here, we delegate all kinds of functionality 43

43

to other methods like these ones. 44

44

And now I'll also create setLocalStorage. 45

45

So here I'm of course calling it already, 46

46

but now I will create it afterwards. 47

47

So setLocalStorage and once again, 48

48

let's add it here at the end. 49

49

And this one doesn't need any parameters 50

50

because we will simply get the workouts 51

51

from the workout property. 52

52

And so this is how we use the local storage API. 53

53

And I say API because local storage is, once again, 54

54

an API that the browser provides for us 55

55

and that we can use. 56

56

So localStorage.setItem, 57

57

and then we have to give it a name, so workouts, 58

58

and then the second argument 59

59

needs to be a string that we want to store 60

60

and which will be associated with this key here. 61

61

So basically local storage is a simple key value store, 62

62

and so we need a key which is this one here, 63

63

and we need a simple value, 64

64

which must also be a string. 65

65

But we can convert an object to a string 66

66

by doing this. 67

67

So JSON.stringify. 68

68

So this is another new one, all right. 69

69

But we can use this method here 70

70

to convert any object in JavaScript to a string. 71

71

And so what we want to convert 72

72

is this.workouts, like this. 73

73

And that's actually it already. 74

74

With this, we are setting all the workouts to local storage. 75

75

Now, I just want to mention that local storage 76

76

is a very simple API. 77

77

And so it is only advised to use 78

78

for small amounts of data, all right. 79

79

That's because local storage is blocking, 80

80

and for now you don't know what blocking actually means 81

81

but it is something that's very bad, 82

82

and we will learn why that is 83

83

actually in the next section. 84

84

But for now, what matters here is 85

85

that you shouldn't use local storage 86

86

to store large amounts of data, 87

87

because that will surely slow down your application. 88

88

But anyway, let's already test this out, 89

89

because we actually have a way 90

90

of seeing this data in the browser. 91

91

So let's add something here. 92

92

Okay. 93

93

So everything worked fine. 94

94

So now let's go here to this application tab, 95

95

and then here on the left side 96

96

you have this local storage tab, all right. 97

97

And if we click this arrow here, and then here, 98

98

well, then actually it should be here already. 99

99

Well, let's see if we have everything correctly set up. 100

100

So we have setLocalStorage, then setItem 101

101

and here everything looks correct. 102

102

And here, I believe we're also correctly calling it, 103

103

setLocalStorage. 104

104

So this should work. 105

105

So let's simply try it again here. 106

106

(clicking) 107

107

(typing) Okay. 108

108

Ah, and now you saw it appearing here, right. 109

109

So we have the key of workout and then the value. 110

110

And the value is basically now this string here. 111

111

So, actually here it looks like an object, 112

112

because apparently JavaScript 113

113

somehow then converts it back to an object, 114

114

but actually it is stored as a string, 115

115

here in this workouts key. 116

116

So you see that we have this single workout 117

117

that we currently have, 118

118

but of course, if we add another one, 119

119

then now we got this bigger string here. 120

120

And so it now contains these two objects. 121

121

And so like this, the local storage 122

122

always is gonna be updated. 123

123

So it's up to date, according to the data 124

124

that we have in our application. 125

125

Great. 126

126

And now all we have to do 127

127

is to then actually show the data back here 128

128

on the list and the map once we reload the page. 129

129

So let me actually show that to you 130

130

because here in the application, 131

131

as you see the local storage is still there. 132

132

And so now we will make use of this 133

133

by then displaying that data back in our application. 134

134

So remember when we want to do that, 135

135

it is right here in the constructor, right. 136

136

Because this is where we have all the code 137

137

that is executed right when the application loads. 138

138

So let's add that here. 139

139

And I'm gonna start with some comments here. 140

140

(typing) 141

141

Handlers, 142

142

then get user's position, 143

143

and then get data from local storage. 144

144

And so again, 145

145

I will now call a method that I'm going to create later. 146

146

So getLocalStorage. 147

147

And so let's now go ahead and create this method 148

148

down here in the end. 149

149

(clicking) (typing) 150

150

And so now, here we do the opposite. 151

151

So localStorage.getItem. 152

152

And now we simply have to pass in the key. 153

153

So basically the identifier of our local storage item, 154

154

because we could set multiple items. 155

155

So we could set everything all for application. 156

156

So for example, if we wanted, 157

157

we could store everything that's in the application 158

158

in local storage. 159

159

We would just have to define one key for each of them, 160

160

and then we could use that key 161

161

to basically retrieve it back. 162

162

(clicking) (typing) 163

163

Alright, so let's now store this data. 164

164

And so here, we can then see it for the first time. 165

165

So now as the page loads, 166

166

it should display this data to us 167

167

in the console. 168

168

And, well, it's nowhere to be found. 169

169

Let's reload here maybe again. 170

170

So something must be wrong, now, 171

171

and it's called workouts. 172

172

And here you go, all right. 173

173

So you see that indeed, it is this big string. 174

174

And so now we want to convert this string 175

175

back to the objects. 176

176

And so, basically we need to use the opposite 177

177

of JSON.stringify which is JSON.parse. 178

178

So let's try that again. 179

179

And now indeed we get an array 180

180

with some real objects in there, all right. 181

181

Now there's still a problem with this, 182

182

but more about that a little bit later, 183

183

because all the relevant data 184

184

that we need for now is actually in there. 185

185

So now let's do something with that data. 186

186

And the first thing that we should actually do 187

187

is to check if there is actually some data. 188

188

So when there is nothing in local storage, 189

189

then of course the data will be, like undefined. 190

190

So in that case, we don't want to do anything. 191

191

So let's use another guard clause here and say, 192

192

if there is no data then simply return. 193

193

But anyway, let's keep going. 194

194

And so what we want to do with this data, 195

195

which is basically our array of workouts, 196

196

is to restore our workouts array. 197

197

So we can say, this.workouts 198

198

should be equal to the data that we just read. 199

199

So, keep in mind that this method here 200

200

is gonna be executed right in the very beginning. 201

201

And so at that point, 202

202

the workouts array is always gonna be empty. 203

203

But if we already had some data in the local storage, 204

204

then, we will simply set that workouts array 205

205

to the data that we had before. 206

206

And so essentially we are restoring the data here 207

207

across multiple reloads of the page. 208

208

Okay, and so now let's take all these workouts 209

209

and render them in the list. 210

210

So this.workouts, 211

211

and so we want to do something 212

212

for each of the workouts. 213

213

And so we loop over this array, 214

214

but we don't want to create a new array. 215

215

And so forEach is perfect for this. 216

216

Then now, I'm gonna call each of them work. 217

217

And so, now I can do this.renderWorkout 218

218

the current workout. 219

219

And so now it becomes really, really helpful 220

220

that we have all the logic 221

221

of rendering a workout in the sidebar 222

222

here nicely inside of this method, right. 223

223

Because, imagine that we had all this code here, 224

224

inside of this method here, 225

225

so the new workout method, right. 226

226

So if we did all of that here, 227

227

then now we would have to copy that code 228

228

or we would have to refactor it. 229

229

But instead, you can start to get into the habit 230

230

of exporting functionality into its own methods 231

231

or its own functions. 232

232

And so then it is very easy to reuse them, 233

233

such as we are doing now with renderWorkout. 234

234

Right. 235

235

So here, all we do is to call renderWorkout 236

236

that we already had written before. 237

237

So let's now test this, 238

238

and right now, 239

239

we should already get the two workouts there, 240

240

and indeed, here they are. 241

241

So these are the two ones that we had created previously. 242

242

And so we see that it did indeed now persist across loads. 243

243

Now, we also need to add them here on the map. 244

244

And so for that, 245

245

we are going to use our renderWorkout marker method 246

246

that we also already have. 247

247

And let's start by actually putting it here, 248

248

just so I can show you 249

249

that it's actually not gonna work. 250

250

But then it becomes easier to explain 251

251

why it doesn't work. 252

252

So let's see. 253

253

And so here we get, 254

254

"Cannot read property 'addlayer' of undefined." 255

255

So indeed, we get an error 256

256

when we try to add this first workout 257

257

also to the map. 258

258

So let's go back and think why that is. 259

259

Well, once again, remember that this method here 260

260

is executed right at the beginning, 261

261

so right after the page loaded. 262

262

And so we are trying to add this marker to the map 263

263

right at the beginning. 264

264

However, at this point, 265

265

the map has actually not yet been loaded. 266

266

And so essentially, 267

267

we are trying to add a marker, 268

268

let's say where that is. 269

269

So we are trying to add this marker to the map, 270

270

which is this one here, 271

271

which isn't yet defined at this point. 272

272

And so once again, this is a first glimpse 273

273

into the nature of asynchronous JavaScript, 274

274

which we will talk about in the next section. 275

275

But what matters here is that you grasp this idea 276

276

that the map is not yet created 277

277

right at the beginning 278

278

when the application is first loaded, right. 279

279

It takes some time. 280

280

So, first the position of the user 281

281

needs to beget using geolocation, 282

282

so this one here. 283

283

And then after that, 284

284

the map has also to be loaded. 285

285

So there's a lot of stuff that has to happen 286

286

before we can actually render any markers on the map. 287

287

So instead of trying to render the markers, 288

288

right at the very beginning, 289

289

we should only do that 290

290

once the map has been loaded. 291

291

And so we can put that logic 292

292

right here in this method of load map, okay. 293

293

So here at the very end, basically. 294

294

So let's get the code from down here. 295

295

So I will get all of this, 296

296

but I will then only keep this part, all right. 297

297

So let's copy this. 298

298

And so here we will not render the markers, 299

299

so only the workout on the sidebar list. 300

300

And then it is here. 301

301

So, yeah. 302

302

Right here in load map, 303

303

this is where we will then render the markers, 304

304

because at this point, 305

305

the map is, of course, already available. 306

306

And so with this, it should be working, okay. 307

307

But make sure that you really understand 308

308

why we have to call this method here 309

309

and not right in the beginning. 310

310

So, let's see what happens now, 311

311

and we didn't get any error and yeah. 312

312

So now we have the two markers 313

313

right where I had put them previously. 314

314

And now let's just add another one right here. 315

315

All right. 316

316

And now if I reload the page, 317

317

then indeed, there is the marker, 318

318

and this one and, of course, all the other ones as well. 319

319

Beautiful. 320

320

So this is great. 321

321

And our application is now essentially finished. 322

322

I just want to show you one problem that we have now. 323

323

And that has to do with local storage. 324

324

So, remember that when I click here 325

325

on one of these workouts, 326

326

it will move the map to the workout, 327

327

and so that's gonna be fine, 328

328

but what also happens is that this clicks property 329

329

is gonna be increased by using the click method 330

330

that is inherited from the workout class. 331

331

But watch what happens now as I try to do that. 332

332

And so we get workout.click is not a function. 333

333

So, why do you think that is? 334

334

Well, let's try to take a look at the objects 335

335

that we get back from local storage. 336

336

So that's this one here. 337

337

And I know that right now 338

338

we have a ton of console.logs here, 339

339

so we should get rid of them at some point, 340

340

but anyway, for now let's take a look 341

341

at the objects that we basically have right now. 342

342

And so this is currently also the data 343

343

that is in this .workouts, right? 344

344

Now, if we take a look at this, 345

345

then here everything works okay. 346

346

But now if we take a look at the prototype chain, 347

347

you see that now it's no longer an object 348

348

of the type of running, 349

349

and also not of the type of workout, right. 350

350

So the entire prototype chain that we had before is gone. 351

351

So contrast that to one of these objects. 352

352

So again, the data is fine, 353

353

but here, we actually have the prototype with calcPace, 354

354

and then that has the click entities, 355

355

that description methods in the workout prototype, right. 356

356

So, the problem here is that basically, 357

357

when we converted our objects to a string, 358

358

and then back from the string to objects, 359

359

we lost the prototype chain. 360

360

And so these new objects here 361

361

that we recovered from the local storage 362

362

are now just regular objects. 363

363

They are now no longer objects 364

364

that were created by the running 365

365

or by the cycling class. 366

366

And so therefore, 367

367

they will not be able to inherit 368

368

any of their methods. 369

369

And so in the end, 370

370

that's the reason why workout.click 371

371

is now not a function anymore. 372

372

So, again, because the object now no longer has it 373

373

in its prototype. 374

374

So you see that this is just the regular methods 375

375

that are available on any object, all right. 376

376

So this can be a big problem 377

377

when you work with local storage 378

378

and object oriented programming 379

379

like we are doing here. 380

380

Now to fix this problem, we could go ahead 381

381

and restore the object right here. 382

382

So, in our getLocalStorage, 383

383

we could now loop over this data here, 384

384

and then restore the objects 385

385

by creating a new object using the class, 386

386

based on the data that is coming here from local storage. 387

387

But that's a little bit of work 388

388

and so we're not gonna do that here. 389

389

And so instead what I will do 390

390

is to simply disable the functionality 391

391

of counting the clicks. 392

392

So remember that when I first introduced this method here, 393

393

I told you that one of the reasons for it 394

394

is that I also wanted to show you something 395

395

in the next lecture. 396

396

And so that's exactly here, 397

397

what I wanted to show you. 398

398

So basically, that objects coming from local storage 399

399

will not inherit all the methods 400

400

that they did before. 401

401

All right. 402

402

And so with that, we are basically done. 403

403

Let's just get rid of some of these console.logs here, 404

404

because it's not really a good practice 405

405

to have them in the final code. 406

406

So we can have maybe one while we're developing, 407

407

but then at some point it simply clutters, 408

408

like our entire console workout. 409

409

And so that's not helpful. 410

410

And here again. 411

411

And you see that here 412

412

we still have all of these workouts, of course. 413

413

Now actually to finish, 414

414

I want to create a quick and easy way 415

415

to delete all of these workouts at once, 416

416

at least from local storage. 417

417

And so let's go back here, 418

418

and basically add a method 419

419

to the public interface of this class 420

420

for the first time. 421

421

So this class is a little bit unusual, 422

422

because right now, we don't have any public method. 423

423

So there's no public interface. 424

424

But now we will create a reset method here, 425

425

which we can then use out here 426

426

or even in the console. 427

427

And so, actually that's what we will do, 428

428

so using it in a console. 429

429

So what I want to do in this one here 430

430

is to basically remove this workouts item 431

431

from local storage. 432

432

And so besides setting and getting items, 433

433

we can also remove items based on the key. 434

434

All right. 435

435

And with this we removed our workouts 436

436

from the local storage, 437

437

and now we can then reload the page programmatically. 438

438

And so then the application will look completely empty. 439

439

And we can do this with location.reload. 440

440

And location is basically a big object 441

441

that contains a lot of methods 442

442

and properties in the browser. 443

443

And so one of the methods 444

444

is the ability to reload the page. 445

445

So, let's try that now. 446

446

And as I said, I will do that in the console. 447

447

So let's go actually back to our code 448

448

just to see where we can use it. 449

449

So, we are creating the app object 450

450

and then storing it in app, right. 451

451

And so we have access to this variable here, 452

452

of course, in the console. 453

453

So let's take a look at that actually. 454

454

And you'll see that indeed, 455

455

here we have these private fields, 456

456

and then we have all of these methods here 457

457

in the prototype. 458

458

And so one of them is of course, reset. 459

459

And so let's do that. 460

460

So reset. 461

461

And yeah, it worked. 462

462

So our application is back to being empty now 463

463

so that we can add some more realistic data 464

464

if we wanted to. 465

465

(typing) 466

466

For example like this, 467

467

or maybe we went cycling right here, 468

468

which is a really nice location. 469

469

And here, let's say we took two hours 470

470

and gained 500 meters, all right. 471

471

And now, of course, 472

472

everything is back to working here 473

473

because we got rid of that click method. 474

474

We still have some logins here to the console, 475

475

but, never mind, that's not a problem. 476

476

All right. 477

477

But what matters here 478

478

is that our application is now feature complete. 479

479

We implemented everything from our flowchart. 480

480

Right. 481

481

So everything is done here. 482

482

And so at this point, the final architecture 483

483

of our application looks like this. 484

484

So I have all of the methods here 485

485

that we implemented in the app class, 486

486

and also for workout, running and cycling. 487

487

Now, I'm not gonna go over this here now, 488

488

but it's a good idea 489

489

for you to actually check it out, 490

490

to get a really good idea 491

491

of how the different methods 492

492

call each other in our application. 493

493

So this arrows that you see here 494

494

are basically methods calling other methods. 495

495

All right. 496

496

And that's it, that's our application, 497

497

I hope that you liked it 498

498

and that you had as much fun as I had building it. 499

499

So this was a really great experience, 500

500

and now before we actually finish the section, 501

501

let's have one more final lecture, 502

502

where I will give you some suggestions 503

503

of how to improve this application even more. 504

504

So let's go there right now.

Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.