All language subtitles for 24. Uploading a New Recipe - Part 2

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
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
ia Interlingua
ga Irish
it Italian
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 continue working 2

2

on the recipe uploading feature. 3

3

And this time we will actually work on the model 4

4

which will be responsible for sending the recipe data 5

5

to the Forkify API. 6

6

So let's go to our model. 7

7

And then down here after the bookmarks 8

8

let's create a new function and export it, 9

9

called upload recipe, okay. 10

10

And this one will eventually make a request to the API. 11

11

And so therefore it's going to be an async function 12

12

and it will receive the data for a new recipe. 13

13

Now, the first task of this function 14

14

here will be to take the raw input data 15

15

and transform it into the same format as the data 16

16

that we also get out of the API. 17

17

So let's take a look at that. 18

18

Now, it reloaded the page, of course. 19

19

So basically the format of the data that we receive 20

20

from the API looks a little bit like this. 21

21

Now, it has some different property names here 22

22

but what really matters 23

23

here is that the ingredients are nicely stored 24

24

in this array. 25

25

So there is an ingredients array 26

26

which contains a bunch of objects 27

27

where each contains quantity, unit, and description. 28

28

However, the data that we get into the function 29

29

right now simply has these three 30

30

or actually these six ingredient properties. 31

31

So ingredient one, two, three, four, five, and six. 32

32

And also it has each of these ingredients 33

33

here separated with these commas, all in one string. 34

34

And so now we need to basically put all of this data 35

35

here into one array and also separate each of these strings 36

36

into the quantity, unit, and description. 37

37

Now, of course, here in the form I could have also created 38

38

three different fields for each ingredient. 39

39

So one input field for the quantity, 40

40

the unit, and to description. 41

41

But that was a little bit too much work 42

42

for this learning project 43

43

and so I decided that I will simply give this hint 44

44

that the format needs to be quantity, unit, description. 45

45

And so that's what we have here. 46

46

So half a kilo, so kilo is to unit, 47

47

and then rice is to description. 48

48

Then here we need one avocado but there is no unit 49

49

and so we leave that one empty. 50

50

And then here we have just salt, 51

51

so without any quantity and any unit. 52

52

And so let's now take this data. 53

53

So these six ingredients and then take the data 54

54

out of there and put them into an object. 55

55

So this is how we will do it. 56

56

So we want to create an array of ingredients. 57

57

And so for that, 58

58

a good idea is to use the map method, right? 59

59

So map is always good to create new arrays 60

60

based on some existing data. 61

61

So in order to use map, we need an array. 62

62

And so let's convert the object 63

63

that we get here back to an array. 64

64

So object.entries, 65

65

and as I mentioned, this is basically the opposite 66

66

of object.fromEntries, 67

67

but it still makes sense to convert it to an object 68

68

here because we will also need the rest of the data 69

69

here as an object. 70

70

So new recipe, 71

71

and then we want to filter this array 72

72

because remember we only want the properties 73

73

that are called ingredient one, two, 74

74

three, all the way until six. 75

75

So in this array that we have right now, 76

76

each element is an entry, right? 77

77

And once again, let me actually show that to you. 78

78

So without seeing the data 79

79

I think that it becomes very difficult to follow this. 80

80

So I will console.log this data 81

81

here and now of course, we need to call this function, 82

82

upload recipe in the controller. 83

83

So let's not do this, 84

84

but let's actually call model.uploadRecipe 85

85

with the new recipe. 86

86

Now, okay, let's click here. 87

87

And so again, that is our array that we will work with now. 88

88

And so remember right now we are filtering this array. 89

89

And so what we want is basically only the entries 90

90

where the first element of the array starts with ingredient 91

91

like this, right? 92

92

And then also the second part should not be empty. 93

93

So in this case, we are of course not interested 94

94

in four, five, six. 95

95

Okay, so here add this condition 96

96

that we need for the filter. 97

97

We want to say, just as I explained just a second ago. 98

98

So the first element of the current entry should start 99

99

with ingredient and the second one should exist, 100

100

so it should not be an empty string. 101

101

So entry one, 102

102

so the second element should not be an empty string, okay. 103

103

And so this should now filter out only the data 104

104

that we are interested in. 105

105

So let's log at to the console and not this anymore. 106

106

And yeah, so that is what we were looking for. 107

107

And now all we need to do is to basically take the data 108

108

out of the string here and then put that into an object. 109

109

And so for that, we now finally use the map method. 110

110

And so here we already have some ingredients. 111

111

And so now we will take each ingredient 112

112

and split it by the comma, 113

113

so that's the separator that I specified. 114

114

And before we do that, 115

115

let's actually make sure that we remove 116

116

any white space here. 117

117

So we can simply do .replace and I believe that right now 118

118

the replace all method is actually already available. 119

119

So remember in the video where we talked about strings 120

120

I mentioned that replace all 121

121

will soon be available in browsers. 122

122

And I believe that right now it already is. 123

123

And so let's use that here. 124

124

So let's replace all the basically spaces 125

125

with an empty string. 126

126

And so this should then return an array of three elements, 127

127

and so let's not destruct that array. 128

128

So the first element is the quantity, 129

129

the second one is the unit, 130

130

and the third one is the description. 131

131

And now, let's return an object with this. 132

132

So with quantity, unit, and description. 133

133

We will still have to do some things 134

134

here but for now let's take a look at what we get. 135

135

And ingredient.replaceAll is not a function. 136

136

So that's because each ingredient 137

137

here is actually still an array, 138

138

so just like we had it here before in the entry. 139

139

So the first element of entry here remember was the key 140

140

and the second one was the value itself, 141

141

so here we need to use this on ingredient one. 142

142

So the second element of the entry. 143

143

So let's see now, and here we go. 144

144

So we have quantity, unit, and description 145

145

nicely inside of one array. 146

146

And so that's now kind of looks like this, great. 147

147

Now, there is just one thing that we need to notice here, 148

148

which is that when the quantity does not exist 149

149

then we want it to be no. 150

150

And otherwise it's actually a number. 151

151

So currently we still have strings 152

152

here but we want us to be a number now, 153

153

and so let's go ahead and convert that. 154

154

So let's come here. 155

155

So the quantity should be, so if there is a quantity, 156

156

so let's use the ternary operator. 157

157

So if there is a quantity, then convert that to a number. 158

158

All right, and if not, which is the situation 159

159

in which it is an empty string, then we want to return null. 160

160

So that should fix that, and indeed it does. 161

161

But now, let's see what happens 162

162

when we simply put something else here, 163

163

let's say just a number. 164

164

So let's see. 165

165

Well, then here we get a bunch of undefined 166

166

and so that we don't want, 167

167

so our format 168

168

here should always contain quantity, unit, description. 169

169

So in this case, what we would need to do is this. 170

170

So this is what we would expect. 171

171

That's so then we get here the empty strings as expected. 172

172

So basically what this means is that when we split 173

173

this string here, we wanted to have three parts, all right? 174

174

And so let's actually convert that to a code. 175

175

So here we want to now put 176

176

this here into a separate variable. 177

177

So let's call it ingredients array, 178

178

and then that is the array that we destructure. 179

179

But before we do that we can test 180

180

if this array actually has the length of three. 181

181

So if ingArray.length is different from three 182

182

then we want to create a new error. 183

183

So throw new error, 184

184

and then let's say wrong ingredient format, 185

185

please use the correct format. 186

186

And so then at this point here, 187

187

the function will immediately exit. 188

188

Now, then what do we want to actually happen 189

189

with this error? 190

190

Well, we will want to render an error message to this view. 191

191

So to the add recipe view, right? 192

192

And that is very simple. 193

193

So here we can use all try catch 194

194

just like we have been doing before. 195

195

So try and so if some error occurs in this function here, 196

196

then it goes to the catch block as always. 197

197

So here we get the error and then let's log that error 198

198

to the console again, with some emojis here to make it easy, 199

199

to understand that it is our own error. 200

200

And then we can simply say, addRecipeView.renderError. 201

201

And now we can actually pass in the error message 202

202

ourselves because here in the view 203

203

we accounted for that ability. 204

204

So by default the error message 205

205

is coming from this .errorMessage 206

206

but we can also specify our own. 207

207

And so that is what we will do now 208

208

because this way we are able to create the error message 209

209

basically here where the error actually occurred. 210

210

Okay, so error.message, and so now let's see what happens. 211

211

So for now, let's use the correct format 212

212

just to see if everything keeps working, 213

213

and it does. 214

214

But now, let's do it wrong 215

215

and we get wrong ingredient format 216

216

but it is still coming from the model. 217

217

So here we got uncaught in promise 218

218

and that actually makes sense, 219

219

because remember that here we are in 220

220

an async function already. 221

221

So this returns a promise 222

222

and so basically this then rejects the promise. 223

223

And so therefore we should handle that already right here. 224

224

So try like this and then catch the error 225

225

and simply throw that error again. 226

226

Okay, let's try that again. 227

227

Okay, and that still doesn't look 228

228

the way we want it to look. 229

229

So we wanted here to be an error message, 230

230

and so that should come from the controller. 231

231

And so that means that there is something wrong 232

232

in the controller. 233

233

And I guess I know why that happens 234

234

because remember that this is an async function right here. 235

235

So it returns a promise but then right 236

236

here we are actually not awaiting that promise. 237

237

So we need to use await 238

238

here and then also make this an async function. 239

239

And so only with this, 240

240

we are now actually handling this function 241

241

here as a function that returns a promise 242

242

so that the rejected promise can then actually get caught 243

243

here in this catch block. 244

244

So let's try once again here with some number. 245

245

Ah, and now it works. 246

246

So now, we get the actual error with these emoji mark 247

247

and also the error that we want here, okay, great. 248

248

So we have that part working of the ingredients. 249

249

Now, it's time to actually create the object 250

250

that is ready to be uploaded. 251

251

So let's create a recipe object here. 252

252

And so basically this object will be the opposite 253

253

of this one here. 254

254

So here we take in the source URL formatted as this, 255

255

and we want to send the data where the URL looks like this. 256

256

So where the property has this format, 257

257

it's the same here for the URL and to cooking time actually, 258

258

because that is exactly the format 259

259

that the API is ready to receive. 260

260

So it has to be exactly the way that we received it. 261

261

Okay, so let's write that object very quick. 262

262

So that is at newRecipe.title 263

263

then the source URL is that newRecipe.sourceUrl, like this. 264

264

Then the image URL is newRecipe.image, right? 265

265

Then the publisher is actually the same, 266

266

newRecipe.publisher. 267

267

The cooking time, newRecipe.cookingTime. 268

268

So fortunately, VS Code is giving us 269

269

already the correct suggestions, .servings. 270

270

And so that's all I think. 271

271

And so all we have to do now is to add the ingredients 272

272

array, and that's it. 273

273

And then we also have two numbers 274

274

here which we should convert to numbers 275

275

using this plus trick, all right. 276

276

And so now, let's actually log this one to the console 277

277

and not just the ingredients. 278

278

Oh, and of course, all this should be happening 279

279

inside of this try block, right. 280

280

So let's see, okay. 281

281

That looks great. 282

282

And it looks ready to be actually sent to our API, okay. 283

283

So let's do that. 284

284

So remember we already have a method for getting JSON. 285

285

So that's this one and now let's create a method 286

286

for sending JSON here in our helper. 287

287

And actually it's going to be very similar. 288

288

So for now, let's just copy it, 289

289

but then a bit later we will simply refactor this. 290

290

So here let's call it send JSON, all right. 291

291

And so now, let's learn how we can actually send data 292

292

using the fetch function. 293

293

So up until this point, 294

294

all we ever did was to simply pass in a URL 295

295

into the fetch function 296

296

and that would then automatically create a get request. 297

297

However, to send data, 298

298

remember how we discussed 299

299

before that that needs to be a post request. 300

300

And so here besides passing in the URL 301

301

we also need to pass in an object of some options, okay. 302

302

And the first option is going to be the method. 303

303

And so that method is now post. 304

304

Then we also need to pass in an object of headers, 305

305

and headers are basically some snippets of text, 306

306

which are like information about the request itself. 307

307

And many of them are like standard headers. 308

308

And one that we need to define is the Content Type. 309

309

So Content Type with an uppercase C and a T, 310

310

so make sure you get that right. 311

311

And then here application/JSON, 312

312

and so with this we tell the API. 313

313

So we specify in the request 314

314

that the data that we're gonna send 315

315

is going to be in the JSON format. 316

316

And so only then our API can correctly accept that data 317

317

and create a new recipe in the database. 318

318

And now, finally the payload of the request. 319

319

So basically the data that we want to send, 320

320

which is called the body. 321

321

So the body should be in JSON. 322

322

Remember as I just explained, 323

323

and so we can once again use JSON.stringify 324

324

and then convert the data that we want to send. 325

325

Now, and here we actually need to accept that data 326

326

here into the function, of course, as a second parameter. 327

327

So let's call that upload data. 328

328

And so that is the data that we then convert to JSON 329

329

so that it can be sent, and that's actually it. 330

330

So that's all we need to do. 331

331

So we still pass in a URL 332

332

which we will need to specify next. 333

333

And then we take that URL and the upload data, 334

334

and then simply create this fetch request like this, okay. 335

335

And then everything else is actually going to be the same. 336

336

So we will still have this request a racing about a timeout 337

337

function so that it can't run forever. 338

338

And we will also await any data 339

339

coming back because this API that we're gonna use 340

340

so the Forkify API will actually return the data 341

341

back that we just sent. 342

342

And you will see in a moment 343

343

why that is very important, okay. 344

344

So again, everything here is going to be the same. 345

345

And so a bit later we will then refactor these two 346

346

here into the same function, but let's do that later. 347

347

So here we now need to import the send JSON function. 348

348

And so now, let's use our newly created function 349

349

to create the Ajax request. 350

350

So send JSON and now the URL of the API, 351

351

and actually we have that here stored somewhere, 352

352

so that's this URL that we have in the config, right? 353

353

So slash recipes, 354

354

but that's actually not all as we will see in a second. 355

355

All right, let's get rid of this. 356

356

And now, let's go to the Forkify documentation page. 357

357

So at this URL, because now we actually need the API key. 358

358

So please click here now on this button, 359

359

which will then generate your unique developer key. 360

360

Now, if you got some kind of error 361

361

here while generating your key 362

362

then maybe it is because you requested more than one 363

363

API keys per hour. 364

364

So remember that you should only ever request one API key. 365

365

That's why I have this limit here in place 366

366

so that no one can abuse my API basically. 367

367

Now, if you did actually only try it once 368

368

and you still got an error, 369

369

then you can always contact me on Twitter, okay. 370

370

So here's the link to my Twitter page 371

371

and then just tweet the error at me 372

372

and I will try to help you. 373

373

Now, my key disappeared here, 374

374

so let's click again and now I will copy 375

375

it so that I can use it in my code. 376

376

So let's go down here or actually it's right here. 377

377

So you'll see the API path is actually exactly the same 378

378

as for getting all the recipes. 379

379

Now, the only difference is that of course, 380

380

we will not a search for anything now 381

381

but we will have to add our key like this, 382

382

so with this key parameter, okay. 383

383

And so yeah, we are doing a post request now, right. 384

384

And so that creates a new recipe 385

385

then when we hit this end point, 386

386

so this path with a post request and some data, okay. 387

387

Now, let's store actually this key in the config file. 388

388

So as a string, okay. 389

389

And then let's use that key here. 390

390

So again, the question mark to specify a list of parameters 391

391

and then key equals, 392

392

and then we have to import it up here 393

393

and then the key, okay. 394

394

And remember that this will actually send the recipe 395

395

then back to us. 396

396

And so let's store that as data and also await it. 397

397

And then finally, let's log that data to the console. 398

398

So console.logData, and now let's see what happens. 399

399

So we got a lot of errors here, 400

400

so it seems like the data is completely wrong. 401

401

And that's simply because I just forgot 402

402

to actually put that data here. 403

403

So the recipe, so of course send JSON has two parameters. 404

404

So not only the URL but also the data. 405

405

Let's try that again. 406

406

And it kind of worked 407

407

already because this error that we got back 408

408

here is actually already an error coming from our API. 409

409

So tells us that the input data is invalid 410

410

because the source URL 411

411

needs to be at least five characters long. 412

412

So let's try that again. 413

413

And actually we need to reload for now. 414

414

So the URL, let's just add something here 415

415

and probably all of them need this. 416

416

So let's do that quickly here in the HTML. 417

417

So I say, default value kind of, 418

418

so you see now we have test 23. 419

419

And as we upload it now then that worked. 420

420

So we get a status success back from our server 421

421

and then our data, right. 422

422

So that data contains everything that we just send 423

423

it plus the created at and also an ID. 424

424

And of course also your key 425

425

and that key will be very important in the next video 426

426

when we then want to mark our own recipes, 427

427

basically as our own. 428

428

Now, it will make sense to actually render 429

429

this newly created recipe also then to the user interface 430

430

after closing this display here, 431

431

so after closing this window, right. 432

432

And so therefore we need to convert 433

433

that to the format that we use in our application, right. 434

434

So basically in our application 435

435

we are using these different property names, right. 436

436

So we are in the same situation 437

437

as we are here in load recipe 438

438

where we get the data in the original format. 439

439

So with this kind of property names, 440

440

and we now need to convert it back to this one 441

441

so that all application understands the data. 442

442

All right, now, instead of writing this entire code 443

443

here twice, we can simply grab 444

444

this and put it into a new function. 445

445

So let's do that right here and call that one, 446

446

create recipe object, 447

447

and it simply receives some data. 448

448

And then it returns an object like this. 449

449

So return this soda then we can do whatever we want with it. 450

450

And in this case, 451

451

that's going to be to put that in the state. 452

452

So state.recipe will be create recipe object 453

453

with the data that we receive. 454

454

So basically just some nice refactoring. 455

455

So this now does exactly what we had before, 456

456

but now we can use that down here as well. 457

457

So we get the data 458

458

and now we want to then store that into the state. 459

459

So again, state.recipe equals create recipe object 460

460

with the data that we just received. 461

461

And now, let's actually come here to the controller 462

462

and log that stated recipe to the console, 463

463

so that's model.state.recipe. 464

464

Okay, so let's see. 465

465

And yeah, it now looks exactly the same as this one, right? 466

466

So beautiful. 467

467

There's just one thing missing, 468

468

which is this bookmarked here and also the key 469

469

is missing as well. 470

470

So let's take care of the bookmarking 471

471

and also of preserving our API key in this object, okay. 472

472

And a quick look at our flow chart 473

473

here will reveal that all we want to do is basically store 474

474

the bookmarks to local storage, right. 475

475

And also mark, of course, that recipe as a bookmark. 476

476

Okay, so we already implemented most of this. 477

477

So this and this in the last lecture, 478

478

then this part and this part in this lecture, 479

479

but let's now also take care of bookmarking it, 480

480

but that is very easy 481

481

because we already have the function for that. 482

482

So that is of course, add bookmark. 483

483

So we already have our recipe. 484

484

And so we can simply call add bookmark with our recipe 485

485

and that will then take care of everything. 486

486

So add bookmark with state.recipe. 487

487

And finally, we also need to add our key to the object, 488

488

so to state.recipe. 489

489

And we could do that here manually, 490

490

but let's actually use a nice trick 491

491

to do that down here or up here 492

492

where the object is actually created, so right here. 493

493

Now, in the case of a load recipe, 494

494

not always there will be a key. 495

495

So most of the recipes of course, don't have any key. 496

496

And so we cannot simply do this. 497

497

So key recipe.key because again, 498

498

not all of them will have one. 499

499

So we only want to add the key if there actually exists one. 500

500

So let's use a nice trick to do that. 501

501

So we can use the end operator, which does short-circuiting. 502

502

So we can do a recipe.key and then this object, all right. 503

503

I will explain to you in a second what this does that. 504

504

And then we can spread this. 505

505

So that looks confusing. 506

506

So let me explain what is happening here. 507

507

So remember that the end operator short-circuits. 508

508

So if recipe.key is a faulty value, 509

509

so if it doesn't exist 510

510

well, then nothing happens here, right. 511

511

And so then destructuring here, well does basically nothing. 512

512

Now, if this actually is some value, 513

513

then the second part of the operator 514

514

is executed and returned. 515

515

And so in that case, it is this object 516

516

here basically that is going to be returned. 517

517

And so then this whole expression will become that object. 518

518

And so then we can spread that object 519

519

to basically put the values here. 520

520

And so that will then be the same 521

521

as if the values would be out here like this, 522

522

key recipe.key. 523

523

But again, only in case that the key actually does exist. 524

524

And so this is a very nice trick 525

525

to conditionally add properties to an object. 526

526

So keep this one in mind, 527

527

now it is a very handy trick sometimes. 528

528

Now, okay, and I think we should actually be done here now. 529

529

So you see uploading data is a lot of work, 530

530

but I think this is still a nice exercise and let's see. 531

531

Here is our key now. 532

532

And also the recipe is now bookmarked, great. 533

533

So just to finish this lecture very quickly, 534

534

let's go back to the controller 535

535

and now actually render this recipe in the recipe view. 536

536

So render recipe, which will be recipeView.render, 537

537

and then as always model.state.recipe. 538

538

But now with this, 539

539

we would not really be able to see that rendered recipe yet 540

540

because we still have that form open. 541

541

So let's now close that form. 542

542

So close form window. 543

543

And we can do that because there is already a method 544

544

for that here. 545

545

So it's this public toggle window method. 546

546

And so let's now use that, okay. 547

547

So and actually let's not do that immediately, 548

548

but only after some time so that we can first display 549

549

a nice success message. 550

550

So we can use a set timeout and an insight of that 551

551

callback function. 552

552

We can then call, addRecipeView.toggleWindow, 553

553

and here let's specify some time, 554

554

let's say two and a half seconds. 555

555

However, as you already know, 556

556

we should never use a magic number like this. 557

557

So let's create one more configuration variable here, 558

558

let's call this the modal close, 559

559

and then let's say seconds so that we know that this value 560

560

is actually a value in seconds. 561

561

So let's use two and a half. 562

562

And now, we need to actually import 563

563

this because I believe that right now 564

564

we are not yet importing this into the controller. 565

565

And indeed we're not. 566

566

So let's say that the named import from config.js. 567

567

And so then down here let's use that modal close seconds 568

568

and then times a thousand 569

569

to convert it to milliseconds, okay. 570

570

And before we do that let's also display a success message. 571

571

And for that we already have in our view, 572

572

the render message method, right. 573

573

Which will take this.message, 574

574

which in this case we don't have one yet, 575

575

but let's actually add one. 576

576

Recipe was successfully uploaded. 577

577

And so now it's very, very easy to do this. 578

578

All we have to do is addRecipeView.renderMessage. 579

579

And so once again, 580

580

now that we have all of these nice methods in place, 581

581

it's very easy to take data 582

582

and then render all kinds of things on the user interface. 583

583

For example, like this error, or the success message, 584

584

or of course the data itself. 585

585

So let's try it one more time. 586

586

And there is our success message and it also disappeared. 587

587

And great, here is our recipe. 588

588

And also with our nicely formatted ingredients. 589

589

So remember we put 0.5 kilos of rice. 590

590

And so of course, that was successfully converted to an half 591

591

And you see it's also already a bookmark. 592

592

So you see that it's right here. 593

593

Of course, there is no image 594

594

because that path that I specified 595

595

there is of course not a correct path 596

596

but that doesn't matter at all here. 597

597

And now, to really finish 598

598

let's now add just one final thing 599

599

which is to render a loading spinner 600

600

in the add recipe view, 601

601

before we actually start to upload the data. 602

602

So this will then show the user that something is happening. 603

603

And so one more time that is now really easy to do 604

604

because we already have all these methods in place. 605

605

Okay, let's slow down our network a little bit to slow 3D 606

606

so that we can actually see it happening. 607

607

Well, that didn't display the spinner for some reason there. 608

608

So let's see. 609

609

AddRecipeView.renderSpinner, looks pretty correct to me. 610

610

So let's just take out this piece 611

611

here so that we can actually inspect the code. 612

612

Now it's taking more time because we are, 613

613

so let's put it back online, add recipe. 614

614

Oh, and now, you see it actually showed the loading spinner. 615

615

So not sure what happened to error but now it is all good. 616

616

Okay, great. 617

617

So all we have left to do now is to then display this recipe 618

618

as our own, 619

619

basically by using the key 620

620

that we have now here in our object 621

621

and also do the same thing in the search. 622

622

So let's take maybe a quick break 623

623

and then come back to finally finish this application.

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