diff --git a/_config.yml b/_config.yml index 03c67bce382..ca995a4d181 100644 --- a/_config.yml +++ b/_config.yml @@ -4,15 +4,15 @@ # You can create any custom variable you would like, and they will be accessible # in the templates via {{ site.myvariable }}. -title: Web Development Tips 101 -email: support@webtips101.com -author: webtips101 +title: 30 Days of JavaScript +email: support@30daysofjavascript.com +author: John copyright: Copyright © 2019-2021 description:>- # this means to ignore newlines until "baseurl:" - Tips for learning web development. + Learn JavaScript in 30 days! baseurl: "" # the subpath of your site, e.g. /blog -url: "https://webtips101.com" # the base hostname & protocol for your site, e.g. http://example.com +url: "https://30daysofjavascript.com" # the base hostname & protocol for your site, e.g. http://example.com favicon: "" # the favicon for your site permalink: /:title/ @@ -104,8 +104,8 @@ header_pages: # Page default value defaults: home: - heading: "Web development tips" - subheading: "Learn web development with our quick tips!" + heading: "30 Days of JavaScript" + subheading: "Learn JavaScript in 30 days!" banner: "Your image url" # Excerpt size setting diff --git a/_layouts/home.html b/_layouts/home.html index 4753b165a9c..3366db12677 100644 --- a/_layouts/home.html +++ b/_layouts/home.html @@ -1,5 +1,5 @@ --- -layout: articles +layout: nil heading: 'Your awesome heading' subheading: 'Your awesome subheading' banner: 'default' diff --git a/_posts/2015-02-28-test-markdown.md b/_posts/2015-02-28-test-markdown.md deleted file mode 100644 index ff63e2ac6be..00000000000 --- a/_posts/2015-02-28-test-markdown.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -layout: post -title: Test markdown -subtitle: Each post also has a subtitle -categories: markdown -tags: [test] ---- - -You can write regular [markdown](http://markdowntutorial.com/) here and Jekyll will automatically convert it to a nice webpage. I strongly encourage you to [take 5 minutes to learn how to write in markdown](http://markdowntutorial.com/) - it'll teach you how to transform regular text into bold/italics/headings/tables/etc. - -**Here is some bold text** - -## Here is a secondary heading - -Here's a useless table: - -| Number | Next number | Previous number | -| :------ |:--- | :--- | -| Five | Six | Four | -| Ten | Eleven | Nine | -| Seven | Eight | Six | -| Two | Three | One | - - -How about a yummy crepe? - -![Crepe](https://s3-media3.fl.yelpcdn.com/bphoto/cQ1Yoa75m2yUFFbY2xwuqw/348s.jpg) - -It can also be centered! - -![Crepe](https://s3-media3.fl.yelpcdn.com/bphoto/cQ1Yoa75m2yUFFbY2xwuqw/348s.jpg){: .center-block :} - -Here's a code chunk: - -~~~ -var foo = function(x) { - return(x + 5); -} -foo(3) -~~~ - -And here is the same code with syntax highlighting: - -```javascript -var foo = function(x) { - return(x + 5); -} -foo(3) -``` - -And here is the same code yet again but with line numbers: - -{% highlight javascript linenos %} -var foo = function(x) { - return(x + 5); -} -foo(3) -{% endhighlight %} - -## Boxes -You can add notification, warning and error boxes like this: - -### Notification - -{: .box-note} -**Note:** This is a notification box. - -### Warning - -{: .box-warning} -**Warning:** This is a warning box. - -### Error - -{: .box-error} -**Error:** This is an error box. diff --git a/_posts/2016-05-20-super-long-article.md b/_posts/2016-05-20-super-long-article.md deleted file mode 100644 index 5652a9a267b..00000000000 --- a/_posts/2016-05-20-super-long-article.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -layout: post -title: "Some articles are just so long they deserve a really long title to see if things will break well" -categories: misc ---- - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt. Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit. Proin convallis mi ac felis pharetra aliquam. Curabitur dignissim accumsan rutrum. In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est. - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt. Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit. Proin convallis mi ac felis pharetra aliquam. Curabitur dignissim accumsan rutrum. In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est. - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt. Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit. Proin convallis mi ac felis pharetra aliquam. Curabitur dignissim accumsan rutrum. In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est. diff --git a/_posts/2016-08-12-my-example-post.md b/_posts/2016-08-12-my-example-post.md deleted file mode 100644 index d64a84dd1a8..00000000000 --- a/_posts/2016-08-12-my-example-post.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -layout: post -categories: junk ---- - -Eos eu docendi tractatos sapientem, brute option menandri in vix, quando vivendo accommodare te ius. Nec melius fastidii constituam id, viderer theophrastus ad sit, hinc semper periculis cum id. Noluisse postulant assentior est in, no choro sadipscing repudiandae vix. Vis in euismod delenit dignissim. Ex quod nostrum sit, suas decore animal id ius, nobis solet detracto quo te. - -{% comment %} -Might you have an include in your theme? Why not try it here! -{% include my-themes-great-include.html %} -{% endcomment %} - -No laudem altera adolescens has, volumus lucilius eum no. Eam ei nulla audiam efficiantur. Suas affert per no, ei tale nibh sea. Sea ne magna harum, in denique scriptorem sea, cetero alienum tibique ei eos. Labores persequeris referrentur eos ei. diff --git a/_posts/2017-05-20-this-post-demonstrates-post-content-styles.md b/_posts/2017-05-20-this-post-demonstrates-post-content-styles.md deleted file mode 100644 index ec675ca3160..00000000000 --- a/_posts/2017-05-20-this-post-demonstrates-post-content-styles.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -layout: post -title: "This post demonstrates post content styles" -categories: junk -author: "Bart Simpson" -meta: "Springfield" ---- - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt. Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit. - -## Some great heading (h2) - -Proin convallis mi ac felis pharetra aliquam. Curabitur dignissim accumsan rutrum. In arcu magna, aliquet vel pretium et, molestie et arcu. - -Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est. - -## Another great heading (h2) - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt. Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit. - -### Some great subheading (h3) - -Proin convallis mi ac felis pharetra aliquam. Curabitur dignissim accumsan rutrum. In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. - -Phasellus et hendrerit mauris. Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. - -### Some great subheading (h3) - -Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est. - -> This quote will change your life. It will reveal the secrets of the universe, and all the wonders of humanity. Don't misuse it. - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt. - -### Some great subheading (h3) - -Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit. Proin convallis mi ac felis pharetra aliquam. Curabitur dignissim accumsan rutrum. - -```html - - -
-

Hello, World!

-

AltStyle によって変換されたページ (->オリジナル) /

- -``` - -In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. - -#### You might want a sub-subheading (h4) - -In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. - -In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. - -#### But it's probably overkill (h4) - -In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. - -### Oh hai, an unordered list!! - -In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. - -- First item, yo -- Second item, dawg -- Third item, what what?! -- Fourth item, fo sheezy my neezy - -### Oh hai, an ordered list!! - -In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. - -1. First item, yo -2. Second item, dawg -3. Third item, what what?! -4. Fourth item, fo sheezy my neezy - -## Headings are cool! (h2) - -Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est. - -Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est. - -Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. - -### Tables - -| Title 1 | Title 2 | Title 3 | Title 4 | -| --------------------- | --------------------- | --------------------- | --------------------- | -| lorem | lorem ipsum | lorem ipsum dolor | lorem ipsum dolor sit | -| lorem ipsum dolor sit | lorem ipsum dolor sit | lorem ipsum dolor sit | lorem ipsum dolor sit | -| lorem ipsum dolor sit | lorem ipsum dolor sit | lorem ipsum dolor sit | lorem ipsum dolor sit | -| lorem ipsum dolor sit | lorem ipsum dolor sit | lorem ipsum dolor sit | lorem ipsum dolor sit | - -| Title 1 | Title 2 | Title 3 | Title 4 | -| -------------------------- | -------------------------------------- | -------------------------- | -------------------------------------- | -| lorem | lorem ipsum | lorem ipsum dolor | lorem ipsum dolor sit | -| lorem ipsum dolor sit amet | lorem ipsum dolor sit amet consectetur | lorem ipsum dolor sit amet | lorem ipsum dolor sit | -| lorem ipsum dolor | lorem ipsum | lorem | lorem ipsum | -| lorem ipsum dolor | lorem ipsum dolor sit | lorem ipsum dolor sit amet | lorem ipsum dolor sit amet consectetur | diff --git a/_posts/2017-06-10-quick-mardown-example.md b/_posts/2017-06-10-quick-mardown-example.md deleted file mode 100644 index 27c3e682fd4..00000000000 --- a/_posts/2017-06-10-quick-mardown-example.md +++ /dev/null @@ -1,164 +0,0 @@ ---- -layout: post -title: Quick markdown example -subtitle: This is a quick markdown example -categories: markdown -tags: [example] ---- - -Paragraphs are separated by a blank line. - -2nd paragraph. *Italic*, **bold**, and `monospace`. Itemized lists -look like: - - * this one - * that one - * the other one - -Note that --- not considering the asterisk --- the actual text -content starts at 4-columns in. - -> Block quotes are -> written like so. -> -> They can span multiple paragraphs, -> if you like. - -Use 3 dashes for an em-dash. Use 2 dashes for ranges (ex., "it's all -in chapters 12--14"). Three dots ... will be converted to an ellipsis. -Unicode is supported. ☺ - - - -An h2 header ------------- - -Here's a numbered list: - - 1. first item - 2. second item - 3. third item - -Note again how the actual text starts at 4 columns in (4 characters -from the left side). Here's a code sample: - - # Let me re-iterate ... - for i in 1 .. 10 { do-something(i) } - -As you probably guessed, indented 4 spaces. By the way, instead of -indenting the block, you can use delimited blocks, if you like: - -~~~ -define foobar() { - print "Welcome to flavor country!"; -} -~~~ - -(which makes copying & pasting easier). You can optionally mark the -delimited block for Pandoc to syntax highlight it: - -~~~python -import time -# Quick, count to ten! -for i in range(10): - # (but not *too* quick) - time.sleep(0.5) - print(i) -~~~ - - - -### An h3 header ### - -Now a nested list: - - 1. First, get these ingredients: - - * carrots - * celery - * lentils - - 2. Boil some water. - - 3. Dump everything in the pot and follow - this algorithm: - - find wooden spoon - uncover pot - stir - cover pot - balance wooden spoon precariously on pot handle - wait 10 minutes - goto first step (or shut off burner when done) - - Do not bump wooden spoon or it will fall. - -Notice again how text always lines up on 4-space indents (including -that last line which continues item 3 above). - -Here's a link to [a website](http://foo.bar), to a [local -doc](local-doc.html), and to a [section heading in the current -doc](#an-h2-header). Here's a footnote [^1]. - -[^1]: Some footnote text. - -Tables can look like this: - -Name Size Material Color -------------- ----- ------------ ------------ -All Business 9 leather brown -Roundabout 10 hemp canvas natural -Cinderella 11 glass transparent - -Table: Shoes sizes, materials, and colors. - -(The above is the caption for the table.) Pandoc also supports -multi-line tables: - --------- ----------------------- -Keyword Text --------- ----------------------- -red Sunsets, apples, and - other red or reddish - things. - -green Leaves, grass, frogs - and other things it's - not easy being. --------- ----------------------- - -A horizontal rule follows. - -*** - -Here's a definition list: - -apples - : Good for making applesauce. - -oranges - : Citrus! - -tomatoes - : There's no "e" in tomatoe. - -Again, text is indented 4 spaces. (Put a blank line between each -term and its definition to spread things out more.) - -Here's a "line block" (note how whitespace is honored): - -| Line one -| Line too -| Line tree - -and images can be specified like so: - -![example image](http://www.unexpected-vortices.com/sw/rippledoc/example-image.jpg "An exemplary image") - -Inline math equation: $\omega = d\phi / dt$. Display -math should get its own line like so: - -$$I = \int \rho R^{2} dV$$ - -And note that you can backslash-escape any punctuation characters -which you wish to be displayed literally, ex.: \`foo\`, \*bar\*, etc. diff --git a/_posts/2017-12-04-load-webassembly-modules-javascript.md b/_posts/2017-12-04-load-webassembly-modules-javascript.md new file mode 100644 index 00000000000..abb00bc3644 --- /dev/null +++ b/_posts/2017-12-04-load-webassembly-modules-javascript.md @@ -0,0 +1,78 @@ +--- +layout: post +title: Load WebAssembly Modules in JavaScript +subtitle: How Load WebAssembly Modules in JavaScript +categories: javascript +tags: [javascript , node] +--- + + +You can use the Fetch API to fetch .wasm file. The returned `Promise` instance of `fetch` is passed into `WebAssembly.instantiateStreaming`. For example: + +```js +WebAssembly.instantiateStreaming(fetch('program.wasm'), importObj) + .then(prog => { + console.log(prog.instance.exports.add(1, 2)); + }); +``` + +`WebAssembly.instantiateStreaming` would take out the `ArrayBuffer` instance from the `Promise` object and instantiate the module. The following code has the same effect as the above. + +```js +fetch('program.wasm') + .then(response => response.arrayBuffer()) + .then(wasm => WebAssembly.instantiate(wasm, importObj)) + .then(prog => { + console.log(prog.instance.exports.add(1, 2)); + }); +``` + +That's to say, what we want is the `ArrayBuffer`containing your WebAssembly module binary so you can use `XMLHttpRequest` even through it's older than Fetch API. + +```js +const request = new XMLHttpRequest(); +request.responseType = 'arraybuffer'; +request.onload = function() { + const wasm = request.response; + WebAssembly.instantiate(wasm, importObj) + .then(prog => { + console.log(prog.instance.exports.add(1, 2)); + }); +}; +request.open('GET', 'program.wasm'); +request.send(); +``` + +`WebAssembly.instantiate` accepts `ArrayBuffer` or `TypedArray` and returns `Promise`. After the success of the asynchronous operation, the promise’s value is an object containing two properties `module` and `instance`. The `module` property is an instance of `WebAssembly.Module`. It contains stateless WebAssembly code that has already been compiled by the browser. The `instance` property is an instance of `WebAssembly.Instance`. It contains all the exported WebAssembly functions that allow calling into WebAssembly code from JavaScript. + +If only the instance of `WebAssembly.Module` is required, you may use `WebAssembly.compileStreaming`. It accepts the returned `Promise` of `fetch` and returns `Promise`. After completing the operation, the promise's value is an instance of `Module`. + +```js +WebAssembly.compileStreaming(fetch('program.wasm')) + .then(module => new WebAssembly.Instance(module, importObj)) + .then(instance => { + console.log(instance.exports.add(1, 2)); + }); +``` + +As shown in the above, you can take the `Module` object as the argument to constructing the `Instance` object. In fact, `WebAssembly.compileStreaming` will take out the `ArrayBuffer` and use `WebAssembly.compile` to compile it to a `WebAssembly.Module` instance. The following code has the same effect as the above. + +```js +fetch('program.wasm') + .then(response => response.arrayBuffer()) + .then(wasm => WebAssembly.compile(wasm)) + .then(module => new WebAssembly.Instance(module, importObj)) + .then(instance => { + console.log(instance.exports.add(1, 2)); + }); +``` + +You can use a `Module` instance to construct a `WebAssembly.Instance` instance. If you have `ArrayBuffer`, you can construct a `WebAssembly.Module` object. + +```js +const module = new WebAssembly.Module(wasm); +``` + +Using `new` to construct `WebAssembly.Instance` or `WebAssembly.Module` is a blocking operation. `WebAssembly.compile()` and `WebAssembly.instantiate()` are asynchronous operations and return `Promose`. + +You can use `WebAssembly.validate()` to validate a given typed array of WebAssembly binary code. diff --git a/_posts/2017-12-04-plantuml-example.md b/_posts/2017-12-04-plantuml-example.md deleted file mode 100644 index e45b91ab1eb..00000000000 --- a/_posts/2017-12-04-plantuml-example.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -layout: post -title: Plantuml example -categories: example -tags: [plantuml] ---- - -## My First PlantUML - -### PlantUML Block-1 -@startuml -Bob -> Alice : hello -@enduml - - -### PlantUML Block-2 -``` plantuml! -Bob -> Alice : hello world -``` - - -### PlantUML Block-3 -@startuml -(*) --> "Initialization" - -if "Some Test" then - -->[true] "Some Activity" - --> "Another activity" - -right-> (*) -else - ->[false] "Something else" - -->[Ending process] (*) -endif -@enduml - - -### PlantUML Block-4 - -@startuml -skinparam handwritten true - -skinparam usecase { - BackgroundColor DarkSeaGreen - BorderColor DarkSlateGray - - BackgroundColor<< Main>> YellowGreen - BorderColor<< Main>> YellowGreen - - ArrowColor Olive - ActorBorderColor black - ActorFontName Courier - - ActorBackgroundColor<< Human>> Gold -} - -User << Human>> -:Main Database: as MySql << Application>> -(Start) << One Shot>> -(Use the application) as (Use) << Main>> - -User -> (Start) -User --> (Use) - -MySql --> (Use) - -@enduml diff --git a/_posts/2017-12-08-mermaid-example.md b/_posts/2017-12-08-mermaid-example.md deleted file mode 100644 index 4b076809a19..00000000000 --- a/_posts/2017-12-08-mermaid-example.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -layout: post -title: Mermaid example -categories: example -tags: [mermaid] ---- - -### 1. Pie chart - -```mermaid! -pie title Pets adopted by volunteers - "Dogs" : 386 - "Cats" : 85 - "Rats" : 35 -``` - -### 2. sequence diagram - -@startmermaid -sequenceDiagram - Alice ->> Bob: Hello Bob, how are you? - Bob-->>John: How about you John? - Bob--x Alice: I am good thanks! - Bob-x John: I am good thanks! - Note right of John: Bob thinks a long
long time, so long
that the text does
not fit on a row. - - Bob-->Alice: Checking with John... - Alice->John: Yes... John, how are you? -@endmermaid - -```mermaid! -graph TD -A[Christmas] -->|Get money| B(Go shopping) - B --> C{Let me think} - C -->|One| D[Laptop] - C -->|Two| E[iPhone] - C -->|Three| F[fa:fa-car Car] -``` - -### 3. Class diagram -```mermaid! -classDiagram -Animal <|-- Duck -Animal <|-- Fish -Animal <|-- Zebra -Animal : +int age -Animal : +String gender -Animal: +isMammal() -Animal: +mate() -class Duck{ - +String beakColor - +swim() - +quack() -} -class Fish{ - -int sizeInFeet - -canEat() -} -class Zebra{ - +bool is_wild - +run() -} -``` - -### 4. State diagram -```mermaid! -stateDiagram -[*] --> Still -Still --> [*] - -Still --> Moving -Moving --> Still -Moving --> Crash -Crash --> [*] -``` diff --git a/_posts/2017-12-08-nodemon.md b/_posts/2017-12-08-nodemon.md new file mode 100644 index 00000000000..39618f41fa4 --- /dev/null +++ b/_posts/2017-12-08-nodemon.md @@ -0,0 +1,202 @@ +--- +layout: post +title: "How to Automatically Restart Node.js Apps with Nodemon" +tags: [nodejs] +--- + +In development environments, especially those that involve lots of iterations, we do not want to restart our server or backend app manually when we make changes to our source code. + +This is an issue that [Nodemon](https://nodemon.io/) solves. It acts as a utility library for keeping track of server changes and automatically restarts our app for us. + +According to the documentation, Nodemon is a perfect tool for development in Node.js-based applications. Indeed, it was built with the properties of the Node’s CLI command in mind, since it is a wrapper around the `node` command. + +Basically, it works by detecting changes in the current directory of our source code, and restarts the server to cater to these new changes. + +Recall that in order to run a Node.js app, we begin with the `node` command and append the file name. In development with Nodemon, all we need to do is run Nodemon `filename`, and Nodemon will watch our files for us. + +However, to make use of Nodemon, we need to install it globally on our machines or locally on a per-project basis. + +When installed on a per-project basis, all we need to do is update the `script` tag in the `package.json` file of our project. To use Nodemon in development mode, we can add a `"dev": "nodemon app.js"` line to the `script` tag in the same file. + +When installed globally, Nodemon is available on our system path and works out of the box. + +In this tutorial, I will explain how Nodemon works by exploring its features and how they are being used. + +We will cover the following: + +- What is Nodemon? +- Installing Nodemon both locally and globally +- Nodemon configurations and usage +- Nodemon’s features + +In order to follow along with this tutorial, readers should have a basic understanding of Node.js and Express. + +## What is Nodemon? + +As I earlier mentioned, Nodemon is a utility or a helper tool that watches for file changes and automatically restarts our Node.js applications. It is open source, well maintained, and used by lots of people in the community. + +To see a list of available Nodemon commands, we can use the `-h` flag or the `--help` flag shown below. So we can either run: + +nodemon -h //or nodemon --help + +There are several reasons why we should use Nodemon in developing Node.js based applications. + +Firstly, it is very easy to set up. Secondly, once it is installed, it runs automatically, as it doesn’t require any instance to call, and lastly, it aids faster iterations for development environments. + +Now, let’s explore how we can install Nodemon below. + +## Installing Nodemon + +As we earlier mentioned, Nodemon can either be installed globally on our system path, or locally as a development dependency. + +To install Nodemon globally on our path, we can go ahead and run the command below with the global `-g` flag: + +npm install -g nodemon + +This means that the package can be used and run from the system path on our development machine. + +Otherwise, we can run: + +npm install --save-dev nodemon + +The above command will install Nodemon locally on our machine or as a development dependency. Note here that we are installing Nodemon as a development dependency with the `--save-dev` flag, as we do not want it as a production dependency. + +> When Nodemon is installed globally, we do not need to do any other setup on our local environment as we can run Nodemon from any path on our system and it will watch our source files for us. + +After running the above command, our `package.json` file will be modified and the Nodemon library with its version number will be saved under the key `"devDependencies"` as shown below: + +{ "name": "test-app", "version": "1.0.0", "description": "", "main": "index.js", } "scripts": { "test": "echo \"Error: no test specified\" && exit 1" } { "author": "", "license": "ISC", "private": false, "devDependencies": { "nodemon": "^2.0.7" }, } + +As a development dependency, all we need to do is add a `dev` script in our `package.json` file to be able to use Nodemon in our local setup. Let us now proceed by displaying a simple Node.js application to understand all the features and configuration options for Nodemon. + +Let’s start small with the server setup located in the `app.js` file. The contents of that file is shown below: + +require('dotenv').config() require('./mongoClient') const express = require('express') const config = require('./config') const routes = require('./routes') const app = express() // add routes here routes(app) // catch 404 and forward to error handler app.use((req, res, next) => { const err = new Error('Not Found') console.log(err) err.status = 404 res.send('Route not found') next(err) }) app.listen(process.env.PORT || config.port, () => { console.log(`${config.appName} listening on port ${config.port}!`) }) module.exports = app + +Let us also have a look at how to run this server file using Nodemon. The very basic and minimal setup for making use of Nodemon in our project is shown below in the `package.json` file located in the root: + +{ "name": "nodemon_tutorial", "version": "1.0.0", "description": "A Tutorial for Understanding Nodemon", "main": "app.js", "scripts": { "start": "node app.js", "dev": "nodemon app.js" }, "directories": { "model": "model", "controllers": "controllers" }, "repository": { "type": "git", "url": "" }, "keywords": [ "Node.js", "JavaScript" ], "author": "Alexander Nnakwue", "license": "MIT", "devDependencies": { "nodemon": "^2.0.4" }, "dependencies": { "bcrypt": "^5.0.1", "debug": "^4.1.1", "dotenv": "^8.2.0", "express": "^4.17.1", "express-async-handler": "^1.1.4", "mongoose": "^5.9.25", "mongoose-paginate": "^5.0.3", "path": "^0.12.7", "uuidv4": "^6.2.0" }, "engines": { "node": "13.7.0", "npm": "6.13.6" } } + +As we can see from the setup in the scripts tag below: + +"scripts": { "start": "node app.js", "dev": "nodemon app.js" }, + +So when we run `npm run dev`, it runs Nodemon and watches our files for us. + +The content when we run the file with Nodemon is shown below: + +[nodemon] clean exit - waiting for changes before restart [nodemon] restarting due to changes... [nodemon] starting `node app.js` (node:97775) ExperimentalWarning: Conditional exports is an experimental feature. This feature could change at any time Nodemon_tutorial listening on port 5000! mongodb connected Mongoose: users.createIndex({ email: 1 }, { unique: true, background: true }) Mongoose: users.createIndex({ phoneNumber: 1 }, { unique: true, background: true }) + +> Any output from this script is prefixed with `[nodemon]`, otherwise all output from your application, errors included, will be echoed out as expected. + +With the `--inspect` flag (useful for a Node.js process listening for a debugger) in the `package.json` file, the output when we run `npm run dev` is shown below: + +retina@alexander backend-server % npm run dev> nodemon_tutorial@1.0.0 dev /Users/retina/Dropbox/My Mac (alexander)/Desktop/nodemon_tutorial/nodemon_tutorial> nodemon --inspect app.js [nodemon] 2.0.7 [nodemon] to restart at any time, enter `rs` [nodemon] watching path(s): *.* [nodemon] watching extensions: js,mjs,json [nodemon] starting `node --inspect app.js` Debugger listening on ws://127.0.0.1:9229/8618d563-210c-4070-bed5-b077016abae2 For help, see: https://nodejs.org/en/docs/inspector (node:98970) ExperimentalWarning: Conditional exports is an experimental feature. This feature could change at any time Nodemon_tutorial listening on port 5000! + +As of version `1.1.x`, Nodemon will search for a `scripts.start` property or a `main` property in the `package.json` file in the current working directory and start the app for us. + +Let’s try this out: + +(aba) retina@alexander backend-server % nodemon [nodemon] 2.0.7 [nodemon] to restart at any time, enter `rs` [nodemon] watching path(s): *.* [nodemon] watching extensions: js,mjs,json [nodemon] starting `node app.js` (node:99661) ExperimentalWarning: Conditional exports is an experimental feature. This feature could change at any time Nodemon_tutorial listening on port 5000! mongodb connected Mongoose: users.createIndex({ email: 1 }, { unique: true, background: true }) Mongoose: users.createIndex({ phoneNumber: 1 }, { unique: true, background: true }) + +As we can see from the above, our app still works as it should. Note that here, I have deleted the `scripts` property from the `package.json` file and rerun the app with just the `nodemon` command: + +// delete the script tag and run nodemon afresh "scripts": { "start": "node app.js", "dev": "nodemon app.js" } + +For this to work, we needed to have `nodemon` globally installed in our system path. The output when we run the command `npm i nodemon -g` to install Nodemon globally is shown below: + +retina@alexander ~ % npm i nodemon -g /usr/local/bin/nodemon -> /usr/local/lib/node_modules/nodemon/bin/nodemon.js> nodemon@2.0.7 postinstall /usr/local/lib/node_modules/nodemon> node bin/postinstall || exit 0 + nodemon@2.0.7 added 120 packages from 57 contributors in 13.404s + +## Nodemon configurations and usage + +Nodemon supports both local and global configurations the same way we can configure the system globally or on a per-project basis. + +For a local setup, we can have a `nodemon.json` file in the current working directory of our project, and for a global setup, we can have the same file in our system’s home path. + +Also, we can set up a `nodemonConfig` in the projects `package.json` file for those who prefer to keep all their package configurations in a single place. + +Note that these configurations come with a caveat when it comes to which ones are executed. If we specify a `--config` file or provide a local `nodemon.json` file, any `package.json` config is ignored. + +As you may have noticed, there are three ways of configuring Nodemon for development – local, global, and via the Node CLI. When we type `nodemon --help options`, we get to see all the available CLI options for our use. + +For more info on available ways to configure Nodemon, we can also type `*nodemon --help config*` on our terminal. + +Typically the options to control Nodemon are passed in via the CLI and can be listed when we run `nodemon --help option`. + +Now, let’s examine some of the several [configurations that we can add](https://github.com/remy/nodemon/blob/master/doc/sample-nodemon.md) by passing more parameters to a configuration(`--config`) file or to our `nodemon.json` file. Some of these configurations might be useful while developing our projects. Let’s take a look at some of them below. + +### Monitoring multiple directories + +Nodemon by default monitors the current working directory, but this can be altered by using the `--watch` option to add specific paths. + +For instance, we can instruct Nodemon to only watch for changes in our `services` directory or in the `app.js` file in the `nodemon_tutorial` directory by running the command below: + +nodemon --watch nodemon_tutorial/app.js --watch services + +> Always add a `--watch` flag for each directory we intend to watch. This usually is required when multiple directories are passed. + +### Ignoring files + +Since Nodemon by default restarts a web server when there are file changes, we can effectively change this default setting by configuring Nodemon to ignore changes made in some specific files, directories, or file patterns via the command line. + +See an example below where we ignore the `tests` folder: + +nodemon --ignore tests/ + +The above command, when run, will automatically ignore any changes made in the `tests` folder. Also, note that by default Nodemon ignores files in the `node_modules` and `.git` folder. Amazing right? Let’s move on. + +### Delaying restart + +The default timeout to check for new file changes is usually about one second. However, there are cases where we intend to delay the time it takes for Nodemon to check for file changes for a longer period. + +We can do this by using the `--delay` command. See the code sample below: + +nodemon --delay 3000ms index.js + +`3000ms` is the delay value in milliseconds (this could also be in seconds) before our app restarts. Therefore, Nodemon will only restart the web server when that time elapses. + +### Extensions to watch + +We can specify extensions to watch when there are file changes in directories or sub directories. + +For example, we can specify our own list with the `-e` (or `--ext`) command line argument. See the code sample below: + +nodemon -e njk + +> By default, Nodemon looks for files with the `.js`, `.mjs`, `.coffee`, `.litcoffee`, and `.json` extensions. + +### Running non-Node code + +Apart from Node programs, Nodemon can also be used to monitor other programs. Based on the file extension, Nodemon will go ahead to execute the command. + +For more details on running non-Node code, readers can check the [documentation](https://github.com/remy/nodemon#running-non-node-scripts). + +> While Nodemon is running, we can manually restart our application. So instead of stopping and restarting Nodemon, we can just type `rs` and press **enter**, and Nodemon will restart the server or the running process for us. + +## Features of Nodemon + +### Piping output to a file (or anywhere else) + +We can tell Nodemon not to write to the `stdout` by specifying a set of rules to do so. More details can be [found in the documentation](https://github.com/remy/nodemon#pipe-output-to-somewhere-else). + +### Adding default executables + +Nodemon, with the help of the `nodemon.json` config file, can have a default executable declared. This will in turn allow us watch for changes that are not `node.js` specific. + +To do so, we can make use of the `execMap` property. Note that it is generally recommended to use the global `nodemon.json` to add an `execMap` option to our config. You can read more [details in the documentation](https://github.com/remy/nodemon#default-executables). + +### Triggering events on state change + +We can add a notification when Nodemon restarts. Also, an action can be triggered when an [event](https://github.com/remy/nodemon/wiki/Events#states) occurs. More details about this can be [found in the documentation](https://github.com/remy/nodemon#triggering-events-when-nodemon-state-changes). + +### Usable as a module + +As of version 1.0.0, Nodemon can work as a required module in Node.js. By doing this, we can then extend its functionality and make it suit our other needs. + +More details can be [found in the documentation here.](https://github.com/remy/nodemon/blob/master/doc/requireable.md) + +## Conclusion + +In Node.js, Nodemon can be likened to a magic wand because of its ability to automatically restart a web application upon file changes. In other words, Nodemon simply eliminates the need for programmers to manually stop and restart their application source code in development repeatedly after every change is made. + +It is a utility tool that makes rapid development less cumbersome. As a tool, it continuously monitors your Node.js application and quietly waits for file changes before automatically restarting the server. To add some more extra configurations, we can make use of a `nodemon.json` file. diff --git a/_posts/2017-12-15-table-example.md b/_posts/2017-12-15-table-example.md deleted file mode 100644 index af03411cedb..00000000000 --- a/_posts/2017-12-15-table-example.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -layout: post -title: Table example -subtitle: -categories: example -tags: [table] ---- - -## Table example as below - -**For now, these extended features are provided:** - -* Cells spanning multiple columns -* Cells spanning multiple rows -* Cells text align separately -* Table header not required -* Grouped table header rows or data rows - -### Rowspan and Colspan -^^ in a cell indicates it should be merged with the cell above. -This feature is contributed by [pmccloghrylaing](https://github.com/pmccloghrylaing). - -| Stage | Direct Products | ATP Yields | -| ----: | --------------: | ---------: | -|Glycolysis | 2 ATP || -|^^ | 2 NADH | 3--5 ATP | -|Pyruvaye oxidation | 2 NADH | 5 ATP | -|Citric acid cycle | 2 ATP || -|^^ | 6 NADH | 15 ATP | -|^^ | 2 FADH | 3 ATP | -| 30--32 ATP ||| - -[ Net ATP yields per hexose] - -### Multiline -A backslash at end to join cell contents with the following lines. -This feature is contributed by [Lucas-C](https://github.com/Lucas-C). - -|: Easy Multiline :||| -|:------ |:------ |:-------- | -| Apple | Banana | Orange \ -| Apple | Banana | Orange \ -| Apple | Banana | Orange -| Apple | Banana | Orange \ -| Apple | Banana | Orange | -| Apple | Banana | Orange | - - -### Headerless -Table header can be eliminated. - -|--|--|--|--|--|--|--|--| -|♜ | |♝ |♛ |♚ |♝ |♞ |♜ | -| |♟ |♟ |♟ | |♟ |♟ |♟ | -|♟ | |♞ | | | | | | -| |♗ | | |♟ | | | | -| | | | |♙ | | | | -| | | | | |♘ | | | -|♙ |♙ |♙ |♙ | |♙ |♙ |♙ | -|♖ |♘ |♗ |♕ |♔ | | |♖ | - - -```markdown -|: Fruits \|\| Food :||| -|:-------- |:-------- |:------------ | -| Apple |: Apple :| Apple \ -| Banana | Banana | Banana \ -| Orange | Orange | Orange | -|: Rowspan is 5 :||: How's it? :| -|^^ A. Peach ||^^ 1. Fine | -|^^ B. Orange ||^^ 2. Bad $I = \int \rho R^{2} dV$ | -|^^ C. Banana || It's OK! ![example image][my-image] | -``` - -### Text Alignment -Table cell can be set alignment separately. - -| \:Fruits || Food :| -|:-------- |:------ |:-------- | -| Apple | Banana | Orange | -| Apple | Banana | Orange | - - -| | Fruits\:: || -|:-------- |:------ |:-------- | -| Apple | Banana | Orange | -| Apple | Banana | Orange | - - -|: \:Fruits :|| |: Food :|| -|:-------- |:------ |:-------- |:-------- |:------ | -| Apple | Banana | Orange |: Strawberry :| -| Apple & Banana || ^^ | Peach :|| - - -|: \:Fruits :|| |: Food :|| -| Apple | Banana | Orange |: Strawberry :| - - -|: Fruits \|\| Food :||| -|:-------- |:-------- |:------------ | -| Apple |: Apple :| Apple \ -| Banana | Banana | Banana \ -| Orange | Orange | Orange | -|: Rowspan is 5 :||: How's it? :| -|^^ A. Peach ||^^ 1. Fine | -|^^ B. Orange ||^^ 2. Bad $I = \int \rho R^{2} dV$ | -|^^ C. Banana || It's OK! ![example image][my-image] | - -[my-image]: http://www.unexpected-vortices.com/sw/rippledoc/example-image.jpg "An exemplary image" - diff --git a/_posts/2017-12-18-video-example.md b/_posts/2017-12-18-video-example.md deleted file mode 100644 index 353cdb7b54f..00000000000 --- a/_posts/2017-12-18-video-example.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -layout: post -title: Video example -subtitle: -categories: example -tags: [video] ---- - -## Canon in D (Pachelbel's Canon) - Cello & Piano [BEST WEDDING VERSION] -Some of you know that we occasionally play for weddings. As you can imagine, we get a LOT of requests for Canon in D, and we discovered that there were no good arrangements available anywhere for piano and cello! Hard to believe given its popularity. So we decided to make our own! We tried to stick as closely to the original as possible (which was written for three violins and basso continuo), and we performed it *not* at a snail's pace so the bride can actually make it down the aisle without putting everyone to sleep. 🙊(Yeah, we said it! Nobody likes a slow processional!) Also, the number one complaint about this piece from cellists is always how booooring it is to play because they literally have to play the same 8 bass notes over and over for the entire piece. Problem solved with this arrangement because the cello never has to play the bass! 🙌(The piano does, but we get lots of other fun stuff too so it's ok!) So for all you musicians out there playing weddings, we hope you enjoy playing this arrangement a little more than the ones you were used to...You can get it from www.musicnotes.com. 😊Be sure to let us know in the comments if you do! - -![](//www.youtube.com/watch?v=Ptk_1Dc2iPY) - -## GUCCI HALLUCINATION / THE LINE ANIMATION / GUCCI -BACKGROUND / - -Gucci share their creative vision through a series of surreal animated paintings by acclaimed artist Ignasi Monreal and The Line Animation studio. The animations make up part of a larger campaign shared via social media, above the line and print. - -APPROACH / - -Our aim was to ground and accentuate the outlandish scenarios with ambient sound design. Neither proclaiming to be positive or negative, the sound conveys a sense of the uncanny and leaves the audience with nothing but their own interpretations. their creative vision through a series of surreal animated paintings by acclaimed artist Ignasi Monreal and The Line Animation studio. The animations make up part of a larger campaign shared via social media, above the line and print. - -![](https://vimeo.com/263856289) - - -## FINNEAS Demos How He Builds Songs For Billie Eilish -Grammy Award-winning musician and producer FINNEAS sits down with Pitchfork and closely examines his creative process while working on some of the biggest hit songs of the past couple years. FINNEAS explores the sounds that brought upon -some of his greatest musical breakthroughs in songs such as bad guy, bury a friend, ocean eyes, when the party's over, I Lost a Friend, Used to This and much more. - -![][demo] - -[demo]: https://dai.ly/x7tgcev - -## 2019 BMW Vision M NEXT Concept (HD) - -In future, drivers will be able to choose whether they wish to be driven or do the driving themselves. With the BMW Vision M NEXT, the BMW Group is revealing its take on how driving pleasure might look in future. It offers a foretaste of the BMW M brand’s electrified future by placing the focus squarely on the actively engaged driver. Intelligent technologies provide comprehensive yet carefully targeted assistance to turn them into the ultimate driver. - -![](https://www.dailymotion.com/video/x7bur2y) - -## This is the poster image -In modern browsers, adding a video to your page is as easy as adding an image. No longer do you need to deal with special plug-ins or require crazy markup, you can do it with a single element. -![video](//www.html5rocks.com/en/tutorials/video/basics/devstories.webm) - diff --git a/_posts/2018-05-26-mathjax-test.md b/_posts/2018-05-26-mathjax-test.md deleted file mode 100644 index 92bf6f17c98..00000000000 --- a/_posts/2018-05-26-mathjax-test.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -layout: post -title: Mathjax Test -subtitle: My first mathjax expression -categories: markdown -tags: [test] ---- - -* A safe integer is an integer that - * can be exactly represented as an IEEE-754 double precision number, and - * whose IEEE-75 representation cannot be the result of rounding any other integer to fit the IEEE-754 representation -* For example, $ 2 ^ {53} - 1 $ is a safe integer, - * it can be exactly represented diff --git a/_posts/2018-12-05-an-exhibit-of-markdown.md b/_posts/2018-12-05-an-exhibit-of-markdown.md deleted file mode 100644 index dc437148b28..00000000000 --- a/_posts/2018-12-05-an-exhibit-of-markdown.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -layout: post -title: An exhibit of Markdown -subtitle: Each post also has a subtitle -categories: markdown -tags: [example, markdown] ---- - -This note demonstrates some of what [Markdown][1] is capable of doing. - -## An exhibit of Markdown - - - -*Note: Feel free to play with this page. Unlike regular notes, this doesn't automatically save itself.* - -## Basic formatting - -Paragraphs can be written like so. A paragraph is the basic block of Markdown. A paragraph is what text will turn into when there is no reason it should become anything else. - -Paragraphs must be separated by a blank line. Basic formatting of *italics* and **bold** is supported. This *can be **nested** like* so. - -## Lists - -### Ordered list - -1. Item 1 -2. A second item -3. Number 3 -4. IV - -*Note: the fourth item uses the Unicode character for [Roman numeral four][2].* - -### Unordered list - -* An item -* Another item -* Yet another item -* And there's more... - -## Paragraph modifiers - -### Code block - - Code blocks are very useful for developers and other people who look at code or other things that are written in plain text. As you can see, it uses a fixed-width font. - -You can also make `inline code` to add code into other things. - -### Quote - -> Here is a quote. What this is should be self explanatory. Quotes are automatically indented when they are used. - -## Headings - -There are six levels of headings. They correspond with the six levels of HTML headings. You've probably noticed them already in the page. Each level down uses one more hash character. - -### Headings *can* also contain **formatting** - -### They can even contain `inline code` - -Of course, demonstrating what headings look like messes up the structure of the page. - -I don't recommend using more than three or four levels of headings here, because, when you're smallest heading isn't too small, and you're largest heading isn't too big, and you want each size up to look noticeably larger and more important, there there are only so many sizes that you can use. - -## URLs - -URLs can be made in a handful of ways: - -* A named link to [MarkItDown][3]. The easiest way to do these is to select what you want to make a link and hit `Ctrl+L`. -* Another named link to [MarkItDown](http://www.markitdown.net/) -* Sometimes you just want a URL like . - -## Horizontal rule - -A horizontal rule is a line that goes across the middle of the page. - ---- - -It's sometimes handy for breaking things up. - -## Images - -Markdown can also contain images. I'll need to add something here sometime. - -## Finally - -There's actually a lot more to Markdown than this. See the official [introduction][4] and [syntax][5] for more information. However, be aware that this is not using the official implementation, and this might work subtly differently in some of the little things. - - - [1]: http://daringfireball.net/projects/markdown/ - [2]: http://www.fileformat.info/info/unicode/char/2163/index.htm - [3]: http://www.markitdown.net/ - [4]: http://daringfireball.net/projects/markdown/basics - [5]: http://daringfireball.net/projects/markdown/syntax diff --git a/_posts/2018-12-07-welcome-to-jekyll.md b/_posts/2018-12-07-welcome-to-jekyll.md deleted file mode 100644 index 6340b225bcd..00000000000 --- a/_posts/2018-12-07-welcome-to-jekyll.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -layout: post -title: Welcome to Jekyll! -subheading: hello world! -author: Jeffrey -categories: jekyll -banner: https://bit.ly/32PAjtM -tags: jekyll theme yat -sidebar: [] ---- - -You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `jekyll serve`, which launches a web server and auto-regenerates your site when a file is updated. - -To add new posts, simply add a file in the `_posts` directory that follows the convention `YYYY-MM-DD-name-of-post.ext` and includes the necessary front matter. Take a look at the source for this post to get an idea about how it works. - -## section 1 -Jekyll also offers powerful support for code snippets: - -{% highlight ruby %} -def print_hi(name) -puts "Hi, #{name}" -end -print_hi('Tom') -#=> prints 'Hi, Tom' to STDOUT. -{% endhighlight %} - -## section 2 - -Check out the [Jekyll docs][jekyll-docs] for more info on how to get the most out of Jekyll. File all bugs/feature requests at [Jekyll’s GitHub repo][jekyll-gh]. If you have questions, you can ask them on [Jekyll Talk][jekyll-talk]. - -[jekyll-docs]: https://jekyllrb.com/docs/home -[jekyll-gh]: https://github.com/jekyll/jekyll -[jekyll-talk]: https://talk.jekyllrb.com/ - -$ a * b = c ^ b $ - -$ 2^{\frac{n-1}{3}} $ - -$ \int\_a^b f(x),円dx. $ - -```cpp -#include -using namespace std; - -int main() { - cout << "Hello World!"; - return 0; -} -// prints 'Hi, Tom' to STDOUT. -``` - -```python -class Person: - def __init__(self, name, age): - self.name = name - self.age = age - -p1 = Person("John", 36) - -print(p1.name) -print(p1.age) -``` diff --git a/_posts/2019-06-10-object-assign.md b/_posts/2019-06-10-object-assign.md new file mode 100644 index 00000000000..a62b7183457 --- /dev/null +++ b/_posts/2019-06-10-object-assign.md @@ -0,0 +1,76 @@ +--- +layout: post +title: Object.assign() +subtitle: Learn how to use Object.assign() in JavaScript +tags: [javascript] +--- + +In this article, we will teach you how to use the JavaScript `Object.assign()` method which is available in modern JS starting with ES6+. + +The `Object.assign()` only performs a shallow clone, not a deep clone. + +This is the syntax of the `Object.assign()` method: + +```js +Object.assign(target, ...sources) +``` + +The `Object.assign()` method works by copying all enumerable and own properties from the `source` objects to the `target` object and returns the `target` object. + +The `Object.assign()` methods calls the getters on the source objects and setters on the target. It assigns properties only, not copying or defining new properties. + +## Using JavaScript `Object.assign()` to clone an object + +The example below makes use of the `Object.assign()` method to clone an object. + +```js +let comp = { + bg: 'black' +}; + +let clonedComp = Object.assign({}, comp); +console.log(clonedComp); +``` + +The output in the browser's console will be: + +``` +{ bg: 'black' } +``` + +## Using JavaScript `Object.assign()` to merge objects + +The `Object.assign()` can be used to merge source objects into a target object which has properties consisting of all the properties of the source objects. For example: + +```js +let A = { + height: 10, + width: 20 +}; + +let B = { + color: 'Red', + borderStyle: 'solid' +}; + +let AB = Object.assign({}, A, B); + +console.log(AB); + +``` + +The output will be: + +`{ + height: 10, + width: 20, + color: 'Red', + borderStyle: 'solid' +}` + + +If the source object contains the same property as the target, the property of the later object overwrites the earlier one. + +## Summary + +The `Object.assign()` method assigns enumerable and own properties from a source object to a target object. diff --git a/_posts/202-09-18-hubspot-vs-wordpress-serverless-functions.md b/_posts/202-09-18-hubspot-vs-wordpress-serverless-functions.md new file mode 100644 index 00000000000..dbbb58281af --- /dev/null +++ b/_posts/202-09-18-hubspot-vs-wordpress-serverless-functions.md @@ -0,0 +1,240 @@ +--- +layout: post +title: "Serverless Functions on HubSpot CMS: vs. WordPress" +categories: Serverless +--- + +Throughout this post, we'll learn about serverless functions on HubSpot CMS for adding custom functionalities to your CMS-powered website on HubSpot that has, among other services, a built-in CRM and a set of inbound marketing tools out of the box. + +Serverless functions offer nearly limitless extensibility. We will show you how easy it is to use them and how powerful they are. + +HubSpot provides various built-in tools for working with your contacts, leads, customers, and prospects. Simultaneously, it offers a CMS that you can use to publish blog posts and publish landing pages. It has also services for SEO and analytics out of the box without installing plugins. + +Unlike WordPress, HubSpot provides a much better experience for developers. + +Recently, HubSpot added support for serverless functions that allows you to enhance your site's back-end functionality and easy extensibility without resorting to outdated plugins like in the case of WordPress, which was initially developed as a simple blogging platform. + +After you install WordPress for the first time, it doesn't offer much; so if you only need to add a few pages or blog posts, that's quick and easy. However, when you need any advanced functions, such as generating leads or designing landing pages, you'll have to look for a plugin to install the required functionality. Even standard functionalities for SEO, such as adding fields for meta descriptions and sitemaps, are not present. + +If you still want to use WordPress, you can also benefit from HubSpot CRM and the other built-in marketing tools by [integrating your WordPress website with HubSpot](https://www.techiediaries.com/wordpress-hubspot-integration/). + +For the security side, it's infrequent for a month to pass by without some security issues. + +WordPress is highly customizable with plugins and themes, especially if you know how to use or even develop them. However, installing them without caution can mess up your website. + +Moreover, if the plugins are not updated and maintained, they become more vulnerable to various spambots, crashes, and attacks, exposing your website to many security vulnerabilities. + +Unlike WordPress, we designed HubSpot for marketers in the first place with an easy-to-use interface that enables you to author and optimize content with no extra plugins. + +There are other tools such as [Gatsby or Hexo](https://www.techiediaries.com/jekyll-hugo-hexo/) which are very developer-friendly, but if you want to build a website for clients with no technical background; these are not the best choices. + +At some point, you'll need some customization or functionality which is not built-in into HubSpot. Thanks to the serverless functions, you can use JavaScript to extend and customize your website without managing your server. + +HubSpot's serverless functions, combined with other developer-friendly HubSpot CMS features, provides a solution that works for everyone. Serverless functions offer developers almost unlimited extensibility, while users and marketers can quickly populate the site with content. + +In the following sections, we'll show you step by step how HubSpot serverless functions can enable you to customize websites that your clients will appreciate while still using the modern frontend tools that you are familiar with. + + +## HubSpot Serverless Functions + +Serverless is a modern architecture that enables developers to build and run applications and services without managing the server's infrastructure. You don't need to provision, scale, and maintain servers or install and manage databases to host and serve your web applications. + +As a developer, you only need to write code without worrying about any required infrastructures. Moreover, when your business grows, they are much easier to scale. + +HubSpot serverless functions are built with Node.js and JavaScript, so they use tools modern developers are comfortable with, and unlike the case of WordPress, you don't need to learn PHP or WordPress APIs to build them. + +Note, however, that they are not designed as a generic platform where you would run code unrelated to HubSpot. + +In terms of extensibility, serverless functions are as powerful as WordPress plugins. We can use them to interact with HubSpot and integrate it with any third-party services through APIs. + +The use cases of HubSpot serverless functions are unlimited, and you can use them to implement any requirements you or your clients need. For example, you could generally use them for: + +- Getting data and persisting it in HubDB or the HubSpot CRM +- Integrating your website with other third-party services like Google Forms +- Event registration systems +- Submitting forms that send data to other services + +HubSpot’s serverless functions are built-in JavaScript and use the [NodeJS](https://nodejs.org/en/) runtime. They are designed to extend your HubSpot site's functionality, such as implementing advanced form submissions and fetching data from other third-party services. + +The functions' code is stored in the developer file system and accessed from the Design Manager UI or the CLI. You can use the CLI to generate and edit the code locally using your preferred local development tools and then upload them to HubSpot. + +For the next section, you need to access a CMS Hub Enterprise account or sign up for a [free sandbox account](https://app.hubspot.com/signup/standalone-cms-developer?userType=developer) to try the example serverless functions. + +## Practical Example with HubSpot Serverless Functions + +This section will present you by example how to deploy serverless functions into a site created based on the [CMS Boilerplate](https://github.com/HubSpot/cms-theme-boilerplate). + +If you are not familiar with HubSpot development, you also need to follow [the getting started with serverless functions](https://developers.hubspot.com/docs/cms/guides/getting-started-with-serverless-functions) guide before going through this section if you want to write your code as your progress through the steps. + +Let's start by implementing a serverless function that sends a GET request to a third-party REST API to fetch the latest news data using the Axios client. + +> **Note**: We’ll be using a third-party API available from [NewsAPI.org](https://newsapi.org/) to retrieve news data. So you first need to go to their website [here](https://newsapi.org/register) to register for an API key. + +APIs that require authentication or use API keys are not safe for a website's frontend, as they would expose your credentials. That's why serverless functions are a good solution as an intermediary, allowing you to keep your credentials secret. + +Head over to a command-line interface and run the following commands: + +```bash +cd local-cms-dev +mkdir myfunctions +hs create function +``` + +First, we navigate to our local CMS project, and we call the `hs create function` command to generate a simple boilerplate function. + +> **Note**: For a comprehensive documentation on the HubSpot CLI, see the [reference documentation](https://developers.hubspot.com/docs/cms/developer-reference/local-development-cms-cli). + +You'll be prompted for some information about your functions, such as: + +- Name of the folder where your function will be created, enter `myfunctions\getnews` +- Name of the JavaScript file for your function, enter `getnews` +- Select the HTTP method for the endpoint, select `GET` +- Path portion of the URL created for the function, enter `getnews` + +You should get a message saying that **A function for the endpoint "/_hcms/API/getnews" has been created. Upload "myfunctions\getnews.functions" to try it out** + +This means, once uploaded, our function will be available from the `/_hcms/API/getnews` endpoint. + +Before uploading the function, let's first implement our desired functionality. + +Open the `myfunctions\getnews.function\getnews.js` file, you'll find some boilerplate code for a serverless function that sends a GET request to HubSpot search API. Remove the boilerplate code and leave only the following updated code: + +```js +const axios = require('axios'); +const API_KEY = ''; + +exports.main = async (_, sendResponse) => { + +}; +``` + +We require the Axios library for sending HTTP requests, and we export a main function that HubSpot will execute when a request is made to the associated endpoint. We also define an `API_KEY` variable that holds the API key from the news API. + +Next, inside the body of the main function, add the following code: + +```js +const response = await axios.get(`https://newsapi.org/v2/everything?q=HubSpot&from=2021年03月12日&sortBy=popularity&apiKey=${API_KEY}`); +sendResponse({ body: { response: response.data }, statusCode: 200 }); +``` + +We call Axios to send a GET request to the API endpoint; then, we call the `sendResponse` method to send the fetched data back to the client. We could call this API directly from the frontend code, but we'll need to expose our API key, which should be secret, but thanks to the serverless function fetching data will take place on the server-side, and we don't have to expose the secret. + +This API will search for news articles that mention the "HubSpot" keyword on the internet. + +Finally, run the following command to upload your function: + +```bash +hs upload myfunctions myfunctions +``` + +This command will upload files from the `myfunctions` local folder to a `myfunctions` folder (that will be created) in the Design Manager of your account. + +Finally, you can run the method by visiting the `/_hcms/API/getnews` endpoint with your web browser. In our case, we need to visit [http://hubspot-developers-ch48rf-14526108.hs-sites.com/_hcms/api/getnews](http://hubspot-developers-ch48rf-14526108.hs-sites.com/_hcms/api/getnews) + +Next, let's implement a second serverless function for creating HubSpot contacts from new Google form submissions. + +If you use Google forms for generating leads, you can easily and automatically save the submissions to HubSpot CRM to organize, track, and build better relationships with your leads and customers. + +Head back to your terminal and run the previous command to generate a serverless function: + +```bash +hs create function +``` + +You'll be prompted for the following information: + +- Name of the folder where your function will be created, enter `myfunctions\getformcontact` +- Name of the JavaScript file for your function, enter `getformcontact` +- Select the HTTP method for the endpoint, select `POST` +- Path portion of the URL created for the function, enter `getformcontact` + +Next, you need to get a HubSpot API key from [https://app.hubspot.com/l/api-key/]( https://app.hubspot.com/l/api-key/) then open the `myfunctions\getformcontact.function\getformcontact.js` file and add the following code to your serverless function: + +```js +var request = require("request"); + +exports.main = (context, sendResponse) => { + const body = context.body; + + var options = { + method: 'POST', + url: 'https://api.hubapi.com/crm/v3/objects/contacts', + qs: { hapikey: '51a40969-a29d-45bc-88fa-d687df3c31b7' }, + headers: { accept: 'application/json', 'content-type': 'application/json' }, + body: { + properties: { + firstname: body['First name'], + lastname: body['Last name'], + email: body['Email'], + phone: body['Phone'] + } + }, + json: true + }; + + request(options, function (error, response, body) { + if (error) throw new Error(error); + sendResponse({ body: { response: "The contact is successfully created!" }, statusCode: 200 }); + }); +}; +``` + +We use the `body` property of the `context` parameter, passed to the exported `main` function by HubSpot when sending a request to the associated endpoint, to retrieve the data submitted via a POST request to the endpoint. Next, we use the data (first name, last name, email, and phone) to create a contact on HubSpot CRM by sending a POST request to the `https://api.hubapi.com/crm/v3/objects/contacts` endpoint. + +Next, we need to set up a simple Google form. Simply go to [Google forms](https://docs.google.com/forms/u/0/) and create a new form with the first name, last name, email, and phone fields. + +After creating the form, you should go to **Script editor** of the form, then [add a script and set up a trigger](https://efficientcoder.net/post-google-form-webhook/) for invoking the script when the user submits the form. In the script editor, write the following code: + +```js +var hubspotEndpoint = "https://hubspot-developers-ch48rf-14526108.hs-sites.com/_hcms/api/getformcontact"; +function onSubmit(e) { + const form = FormApp.getActiveForm(); + const allResponses = form.getResponses(); + const latestResponse = allResponses[allResponses.length - 1]; + var res = latestResponse.getItemResponses(); + var data = {}; + for (var i = 0; i < res.length; i++) { + const qTitle = res[i].getItem().getTitle(); + const qAnswer = res[i].getResponse(); + data[qTitle] = qAnswer; + } + + UrlFetchApp.fetch(hubspotEndpoint, { + "method": "post", + "contentType": "application/json", + "payload": JSON.stringify(data) + }); +}; +``` +This is a [Google Apps script](https://en.wikipedia.org/wiki/Google_Apps_Script), a scripting platform developed by Google for light-weight application development in the Google Workspace platform. + +Inside the the `hubspotEndpoint` variable, make sure to put the URL to your HubSpot serverless endpoint. + +Next, run the following command to upload your functions: + +```bash +hs upload myfunctions myfunctions +``` + +Now, go to your form, fill in some contact details and submit it. After doing that, this script will invoke our serverless function to create the contact on HubSpot CRM and send the contact's details via a POST request. You can make sure the contact with the same details is created by accessing the [Contacts](https://app.hubspot.com/contacts) page of your HubSpot CRM account. + +Without serverless functions, you would need to resort to workarounds such as automations using services such as [Zapier](https://zapier.com/apps/hubspot/integrations) or [Integromat](https://www.integromat.com/en/integrations/hubspotcrm) if you need to connect both apps. + +## Conclusion + +We have covered how to use serverless functions to add custom functionality to our HubSpot powered website and integrate with its built-in services such as the CRM. + +We introduced you to serverless functions on HubSpot, which offers developers an edge over websites created with Wix, Squarespace, or similar services; with unlimited extensibility and custom functionalities while working with the preferred tools and modern workflows such as CLIs, IDEs, and GitHub, etc. + +Also, unlike WordPress, HubSpot serverless functions let you add powerful features to websites quickly and easily with JavaScript and modern tools. In the same time, you avoid the security issues and other problems related to WordPress plugins. + +If you need a small brochure based website where you only need to update the content once in a while, any CMS would do the job. + +However, for those looking for more out of the box functionalities such as CRM management, SEO, and extensibility without resorting to workarounds and hacks, you owe it to yourself to try HubSpot. Make sure to sign up for a [sandbox account](https://app.hubspot.com/signup/standalone-cms-developer?userType=developer) and create your own HubSpot serverless functions in minutes. + +### Further reading + +- [HubSpot vs. WordPress](https://www.hubspot.com/products/cms/best/wordpress-alternatives) +- [Serverless Architectures](https://martinfowler.com/articles/serverless.html) +- [HubSpot Serverless Functions](https://developers.hubspot.com/docs/cms/features/serverless-functions) + diff --git a/_posts/2020-02-28-headless-cms.md b/_posts/2020-02-28-headless-cms.md new file mode 100644 index 00000000000..5bca63ba55f --- /dev/null +++ b/_posts/2020-02-28-headless-cms.md @@ -0,0 +1,51 @@ +--- +layout: post +title: Headless CMS +categories: headless-cms +tags: [headless-cms] +--- + +This article will cover the basics of what a headless CMS actually is. + +## What is a headless CMS? + +A **headless CMS** is a back-end only content management system (CMS) built from the ground up as a content repository that makes content accessible via a RESTful API or GraphQL API for display on any device. + +The term "headless" comes from the concept of chopping the "head" (the front end, i.e. the website) off the "body" (the back end, i.e. the content repository). A headless CMS remains with an interface to manage content and a RESTful or GraphQL API to deliver content wherever you need it. Due to this approach, a headless CMS does not care about how and where your content gets displayed. A headless CMS has only one focus: storing and delivering structured content and allowing content editors to collaborate on new content. + +The counterpart of a headless CMS is often called _monolithic_, _regular_ or _coupled_ CMS, We’re going to use those terms later on. + + +Let’s have a look at a Monolithic CMS and its feature set: + +1. A database for the content to read and write to. +2. An admin interface to let editors manage the content. +3. An integration of reading and writing. +4. The actual front-end that combines the data from the database with HTML. + +To convert that into a headless CMS we remove the templating feature (4.) from the stack as that is the head of that CMS - the actual website. With that done, we can replace it with an RESTful or GraphQL API that is accessible by other systems to access the data that was managed in the Admin UI.Et voilà: you now have got yourself a **headless CMS**. + + +Other than by using a regular/monolithic CMS, a website can’t be built only with a headless CMS. A headless CMS separated the head from its stack and therefore lacks this point by design. Therefore, the developer must craft the website by themself and use the provided REST or GraphQL APIs of the headless CMS to access the content. + +Creating the whole website on their own seems like a big task on the list, but by decoupling the CMS from the front-end a developer can choose any technology they are already familiar with and do not need to learn the technology for that specific CMS. + +Another big bonus is the fact that one developer can also focus on their own work without handling the bugs of an already existing stack of technology - therefore it is easier to optimize pages for pagespeed and webvitals and even relaunch parts of the website or make breaking technology decision without worrying about losing the existing content. + + + +## Use cases for Headless CMS + +- Separating your content from the tech stack of your website to give be able to move faster. +- Websites, Web apps that use JavaScript frameworks like VueJS/Nuxt.js, React/Next.js, Preact, +- Websites created with static site generators such as Jekyll, Gatsby or Middleman. +- Native Mobile Apps for iOS, Android, Windows Phone +- Enrich your ecommerce Stack BigCommerce, Commercetools, Hybris, Magento2, or others) with a proper CMS for your marketing team. +- Use it for feature flags of your own product to schedule releases of new features. +- As a configuration interface for your home automation solution. +- Or to manage content for your intranet. + +## Summary + +As you see there is no 100% right way and CMS for every use case - but we think that chopping off the presentation layer of your content and make it accessible for more than just one platform if needed is the approach we should aim for! Not just to reuse your content more easily, but if you every want to change your technology stack you don’t have to worry about your content. + diff --git a/_posts/2020-05-26-npx.md b/_posts/2020-05-26-npx.md new file mode 100644 index 00000000000..7b2e520bff1 --- /dev/null +++ b/_posts/2020-05-26-npx.md @@ -0,0 +1,57 @@ +--- +layout: post +title: Introducing NPX +subtitle: What is npx and how it works? +categories: javascirpt +tags: [javascript , node] +--- + +In this article, we'll learn about npx and how to use it with Node to run packages from the npm registry. + +### Node + +A JavaScript runtime that enables us to run javascript outside of a browser. It also enables us to run Javascript on the server-side. + +### NPM + +Stands for Node Package Manager and is a tool that allows us to install and manage node packages as dependencies. + +### So, what is NPX? + +**NPX** is an NPM package runner that makes it really easy to install any sort of node executable that would have normally been installed using NPM. + +### Why use NPX? + +There are a number of ways to install node packages, you can have them _sitting locally_ (local to the project) or _install globally_ (in the user environment). + +Sometimes, instead of using either of the two install methods above, you may just want to use the package and go. + +Sometimes, you might just want to experiment with a list of packages as you may not know exactly what you need. + +In these cases, ​instead of installing locally or globally, you can go straight to running those packages with NPX. + +### How does it work? + +NPX comes bundled with NPM starting with version 5.2+. So, if your version of NPM is 5.2 or higher, then you have NPX installed. + +When you run a package using NPX, it searches for the package in the local and global registry, and then it runs the package. + +If the package is not already installed, NPX downloads the package files and installs the package, but it will only cache the files instead of saving it. + +To use NPX, you would run a command like this: + +``` +npx some-package +``` + +One great way for you to see how quickly NPX works is to create a react app using: + +``` +$ npx create-react-app my-app +``` + +The above command will generate a react app, named `my-app`, in the path that the command was run in using the `create-react-app` package. NPX then searches for the package in your environment. If it is not found, NPX downloads the files and runs the command to create a new react app, using just that one line of command. + +One disadvantage of NPX is that it needs to search for packages, whether or not they are installed, before it actually runs them. This, to me, can sometimes be an overhead when you need to get things done very quickly. + +Thank you so much for reading, I hope I have been able to at least shed some light on what NPX is, to explore further you can read [here](https://www.npmjs.com/package/npx). diff --git a/_posts/2020-08-12-javascript-destructuring-assignment.md b/_posts/2020-08-12-javascript-destructuring-assignment.md new file mode 100644 index 00000000000..e5529f1312b --- /dev/null +++ b/_posts/2020-08-12-javascript-destructuring-assignment.md @@ -0,0 +1,396 @@ +--- +layout: post +title: "JavaScript Destructuring Assignment" +categories: javascript +--- + + +The object destructuring is a useful JavaScript feature to extract properties from objects and bind them to variables. + +What’s better, object destructuring can extract multiple properties in one statement, can access properties from nested objects, and can set a default value if the property doesn’t exist. + +In this post, I’ll explain how to use object destructuring in JavaScript. + +## 1. The need for object destructuring + +Imagine you’d like to extract some properties of an object. In a pre-ES2015 environment, you would need to write the following code: + +```javascript +var hero = { + name: 'Batman', + realName: 'Bruce Wayne' +}; + +var name = hero.name;var realName = hero.realName; +name; // => 'Batman', +realName; // => 'Bruce Wayne' +``` + +The property `hero.name` value is assigned to the variable `name`. Same way `hero.realName` value is assigned to `realName`. + +Such a way to access properties and assign them to variables requires boilerplate code. By writing `var name = hero.name`, you have to mention the `name` binding 2 times, and the same for `realName`. + +That’s where the object destructuring syntax is useful: you can read a property and assign its value to a variable without duplicating the property name. More than that, you can read multiple properties from the same object in just one statement! + +Let’s refactor the above script and apply the object destructuring to access the properties `name` and `realName`: + +```javascript +const hero = { + name: 'Batman', + realName: 'Bruce Wayne' +}; + +const { name, realName } = hero; +name; // => 'Batman', +realName; // => 'Bruce Wayne' +``` + +`const { name, realName } = hero` is an object destructuring assignment. This statement defines the variables `name` and `realName`, then assigns to them the values of properties `hero.name` and `hero.realName` correspondigly. + +Comparing the 2 approaches to access the object properties: + +```javascript +const name = hero.name; +const realName = hero.realName; + +// is equivalent to: + +const { name, realName } = hero; +``` + +it’s visible that the object destructuring is handier because neither the property names nor the object variable is duplicated. + + + +## 2. Extracting a property + +The basic syntax of object destructuring is pretty simple: + +```javascript +const { identifier } = expression; +``` + +Where `identifier` is the name of the property to access and `expression` should evaluate to an object. After the destructuring, the variable `identifier` contains the property value. + +Here’s the equivalent code using a property accessor: + +```javascript +const identifier = expression.identifier; +``` + +Let’s try the object destructuring in practice: + +```javascript +const hero = { + name: 'Batman', + realName: 'Bruce Wayne' +}; + +const { name } = hero; +name; // => 'Batman' +``` + +The statement `const { name } = hero` defines the variable `name` and initializes it with the value of `hero.name` property. + +## 3. Extracting multiple properties + +To destructure the object into multiple properties, enumerate as many properties as you like adding commas `,` in-between: + +```javascript +const { identifier1, identifier2, ..., identifierN } = expression; +``` + +Where `identifier1`, ..., `identifierN` are names of properties to access, and `expression` should evaluate to an object. After the destructuring, the variables `identifier1`, ..., `identifierN` contain corresponding properties values. + +Here’s the equivalent code: + +```javascript +const identifier1 = expression.identifier1; +const identifier2 = expression.identifier2; +// ... +const identifierN = expression.identifierN; +``` + +Let’s take a look again at the example from the first section, where 2 properties are extracted: + +```javascript +const hero = { + name: 'Batman', + realName: 'Bruce Wayne' +}; + +const { name, realName } = hero; +name; // => 'Batman', +realName; // => 'Bruce Wayne' +``` + +`const { name, realName } = hero` creates 2 variables `name` and `realName` assigned with values of corresponding properties `hero.name` and `hero.realName`. + +## 4. Default values + +If the destructured object doesn’t have the property specified in the destructuring assignment, then the variable is assigned with `undefined`. Let’s see how it happens: + +```javascript +const hero = { + name: 'Batman', + realName: 'Bruce Wayne' +}; + +const { enemies } = hero; +enemies; // => undefined +``` + +After destructuring the variable `enemies` is `undefined` because the property `enemies` doesn’t exist in the object `hero`. + +Fortunately, you can set a default value if the property doesn’t exist in the destructured object. Here’s the basic syntax: + +```javascript +const { identifier = defaultValue } = expression; +``` + +Where `identifier` is the name of the property to access and `expression` should evaluate to an object. After the destructuring, the variable `identifier` contains the property value or is assigned with `defaultValue` if `identifier` property doesn’t exist. + +Here’s the equivalent code: + +```javascript +const identifier = expression.identifier === undefined ? + defaultValue : expression.identifier; +``` + +Let’s change the previous code sample, and use the default value feature: + +```javascript +const hero = { + name: 'Batman', + realName: 'Bruce Wayne' +}; + +const { enemies = ['Joker'] } = hero; +enemies; // => ['Joker'] +``` + +Now, instead of being `undefined`, the variable `enemies` defaults to `['Joker']`. + +## 5. Aliases + +If you’d like to create variables of different names than the properties, then you can use the aliasing feature of object destructuring. + +```javascript +const { identifier: aliasIdentifier } = expression; +``` + +`identifier` is the name of the property to access, `aliasIdentifier` is the variable name, and `expression` should evaluate to an object. After the destructuring, the variable `aliasIdentifier` contains the property value. + +The equivalent code: + +```javascript +const aliasIdentifier = expression.identifier; +``` + +Here’s an example of object destructuring alias feature: + +```javascript +const hero = { + name: 'Batman', + realName: 'Bruce Wayne' +}; + +const { realName: secretName } = hero; +secretName; // => 'Bruce Wayne' +``` + +Looking at `const { realName: secretName } = hero`, the destucturing defines a new variable `secretName` (alias variable), and assigns to it the value `hero.realName`. + +## 6. Extracting properties from nested objects + +In the previous examples, the objects were plain: the properties have primitive data types (e.g. strings). + +Often objects can be nested in other objects. In other words, some properties can contain objects. + +In such case, you still can use the object destructuring and access properties from deep. Here’s the basic syntax: + +```javascript +const { nestedObjectProp: { identifier } } = expression; +``` + +`nestedObjectProp` is the name of the property that holds a nested object. `identifier` is the property name to access from the nested object. `expression` should evaluate to the destructured object. + +After the destructuring, the variable `identifier` contains the property value of the nested object. + +The above syntax is equivalent to: + +```javascript +const identifier = expression.nestedObjectProp.identifier; +``` + +The level of nesting you can extract properties from is unlimited. If you want to extract properties from deep, just add more nested curly braces: + +```javascript +const { propA: { propB: { propC: { .... } } } } = object; +``` + +For example, the object `hero` contains a nested object `{ city: 'Gotham'}`. + +```javascript +const hero = { + name: 'Batman', + realName: 'Bruce Wayne', + address: { + city: 'Gotham' + } +}; + +// Object destructuring: +const { address: { city } } = hero; +city; // => 'Gotham' +``` + +The object destructuring `const { address: { city } } = hero` let’s you access the property `city` from the nested object. + +## 7. Extracting a dynamic name property + +You can extract to variables properties with a dynamic name (the property name is known at runtime): + +```javascript +const { [propName]: identifier } = expression; +``` + +`propName` expression should evaluate to a property name (usually a string), and the `identifier` should indicate the variable name created after the destructuring. The second `expression` should evaluate to the object you’d like to destructure. + +An equivalent code without object destructuring: + +```javascript +const identifier = expression[propName]; +``` + +Let’s look at an example where `prop` holds the property name: + +```javascript +const hero = { + name: 'Batman', + realName: 'Bruce Wayne' +}; + +const prop = 'name'; +const { [prop]: name } = hero; +name; // => 'Batman' +``` + +`const { [prop]: name } = hero` is an object destructuring that assigns to variable `name` the value `hero[prop]`, where `prop` is a variable holding the property name. + +## 8. Rest object after destructuring + +The rest syntax is useful to collect the remaining properties after the destructuring: + +```javascript +const { identifier, ...rest } = expression; +``` + +Where `identifier` is the name of the property to access and `expression` should evaluate to an object. + +After the destructuring, the variable `identifier` contains the property value. `rest` variable is a plain object with the remaining properties. + +For example, let’s extract the property `name`, but keep the rest of the properties: + +```javascript +const hero = { + name: 'Batman', + realName: 'Bruce Wayne' +}; + +const { name, ...realHero } = hero; +realHero; // => { realName: 'Bruce Wayne' } +``` + +The destructuring `const { name, ...realHero } = hero` extracts the property `name`. + +At the same time, the remaining properties (`realName` in this case) are collected into the variable `realHero`: `{ realName: 'Bruce Wayne' }`. + +## 9. Common use cases + +### 9.1 Bind properties to variables + +As seen in many examples before, the object destructuring binds property values to variables. + +The object destructuring can assign values to variables declared using `const`, `let` and `var`. Or even assign to an already existing variable. + +For example, here’s how to destructure using `let` statement: + +```javascript +// let +const hero = { + name: 'Batman', +}; + +let { name } = hero; +name; // => 'Batman' +``` + +How to destructure using `var` statement: + +```javascript +// var +const hero = { + name: 'Batman', +}; + +var { name } = hero; +name; // => 'Batman' +``` + +And how to destructure to an already declared variable: + +```javascript +// existing variable +let name; + +const hero = { + name: 'Batman', +}; + +({ name } = hero); +name; // => 'Batman' +``` + +I find it satisfying to combine `for..of` cycle with object destructuring to extract the property right away: + +```javascript +const heroes = [ + { name: 'Batman' }, + { name: 'Joker' } +]; + +for (const { name } of heroes) { console.log(name); // logs 'Batman', 'Joker' +} +``` + +### 9.2 Function parameter destructuring + +Generally, the object destructuring can be placed anywhere where an assignment happens. + +For instance, you could destruct an object right inside the parameters list of a function: + +```javascript +const heroes = [ + { name: 'Batman' }, + { name: 'Joker' } +]; + +const names = heroes.map( + function({ name }) { return name; + } +); + +names; // => ['Batman', 'Joker'] +``` + +`function({ name })` destructures the function parameter, creating a variable `name` holding the value of `name` property. + +## 10. Summary + +The object destructuring is a powerful feature that lets you extract properties from an object and bind these values to variables. + +I especially like about object destructuring is the concise syntax and ability to extract multiple variables in one statement. + +Hopefully, my post has helped you see how useful object destructuring is! + diff --git a/_posts/2020-1-01-dependency-injection-angular.md b/_posts/2020-1-01-dependency-injection-angular.md new file mode 100644 index 00000000000..6969f0cea9c --- /dev/null +++ b/_posts/2020-1-01-dependency-injection-angular.md @@ -0,0 +1,266 @@ +--- +layout: post +title: "Dependency Injection: Angular Example" +subtitle: "Learn about dependency injection in Angular" +categories: angular +tags: [angular] +--- + +Dependency Injection is often more simply referred to as DI. The paradigm exists throughout Angular. It keeps code flexible, testable, and mutable. Classes can inherit external logic without knowing how to create it. Any consumers of those classes also do not need to know anything. + +DI saves classes and consumers alike from having to know more than necessary. Yet the code is as modular as it was before thanks to the mechanisms supporting DI in Angular. + +Services are a key benefactor of DI. They rely on the paradigm for _injection_ into various consumers. Those consumers can then take advantage of that service provides and/or forward it elsewhere. + +Service are not alone. Directives, pipes, components, and so on: every schematic in Angular benefits from DI in some way or another. + +## Injectors + +Injectors are data structures that store instructions detailing where and how services form. They act as intermediaries within the Angular DI system. + +Module, directive, and component classes contain metadata specific to injectors. A new injector instance accompanies every one of these classes. In this way, the application tree mirrors its hierarchy of injectors. + +The `providers: []` metadata accepts services that then register with the class’ injector. This provider field adds the instructions necessary for an injector to function. A class (assuming it has dependencies) instantiates a service by taking on its class as its data type. The injector aligns this type a creates an instance of that service on the class’ behalf. + +Of course, the class can only instantiate what the injector has instructions for. If the class’ own injector does not have the service registered, then it queries its parent. So on and so forth until either reaching an injector with the service or the application root. + +Services can register at any injector within the application. Services go in the `providers: []` metadata field of class modules, directives, or components. The class’ children can instantiate a service registered in the class’ injector. Child injectors fallback on parent injectors after all. + +## Dependency Injection + +Take a look at the skeletons for each class: service, module, directive, and component. + +```typescript +// service + +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: /* injector goes here */ +}) +export class TemplateService { + constructor() { } +} +``` + +```typescript +// module + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +@NgModule({ + imports: [ + CommonModule + ], + declarations: [], + providers: [ /* services go here */ ] +}) +export class TemplateModule { } +``` + +```typescript +// directive + +import { Directive } from '@angular/core'; + +@Directive({ + selector: '[appTemplate]', + providers: [ /* services go here */ ] +}) +export class TemplateDirective { + constructor() { } +} +``` + +```typescript +//component + +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-template', + templateUrl: './template.component.html', + styleUrls: ['./template.component.css'], + providers: [ /* services go here */ ] +}) +export class TemplateComponent { + // class logic ... +} +``` + +Each skeleton can register services to an injector. In fact, TemplateService _is_ a service. As of Angular 6, services can now register with injectors using `@Injectable` metadata. + +##### **In Any Case** + +Notice the `providedIn: string` (`@Injectable`) and `providers: []` (`@Directive`, `@Componet` and `@Module`) metadata. They tell injectors where and how to create a service. Otherwise, injectors would not know how to instantiate. + +What if a service has dependencies? Where would the results go? Providers answers those question so that injectors can instantiate properly. + +Injectors form the backbone of the DI framework. They store instructions to instantiate services so consumers do not have to. They receive service instances without needing to know anything about the source dependency! + +I should also note that other schematics without injectors can still utilize dependency injection. They cannot register additional services but they can still instantiate from injectors. + +## Service + +The `providedIn: string` metadata of `@Injectable` specifies which injector to register with. Using this method, and depending on if the service gets used, the service may or may not register with the injector. Angular calls this _tree-shaking_. + +By default the value is set to `‘root’`. This translates to the root injector of the application. Basically, setting the field to `‘root’` makes the service available anywhere. + +##### **Quick Note** + +As previously mentioned, child injectors fallback on their parents. This fallback strategy ensures parents do not have to re-register for every injector. Refer to this article on [Services and Injectors](https://guide.freecodecamp.org/angular/services-and-injectors) for an illustration of this concept. + +Registered services are _singletons_. Meaning, the instructions to instantiate the service exists on only one injector. This assumes it has not been explicitly registered elsewhere. + +## Module, Directive, and Component + +Modules and components each have their own injector instance. This is evident given the `providers: []` metadata field. This field takes an array of services and registers them with the injector of the module or component class. This approach happens in the `@NgModule`, `@Directive`, or `@Component` decorators. + +This strategy omits _tree-shaking_, or the optional removal of unused services from injectors. Service instances live on their injectors for the life of the module or component. + +## Instantiating References + +References to the DOM can instantiate from any class. Keep in mind that references are still services. They differ from traditional services in representing the state of something else. These services include functions to interact with their reference. + +Directives are in constant need of DOM references. Directives perform mutations on their host elements through these references. See the following example. The directive’s injector instantiates a reference of the host element into the class’ constructor. + +```typescript +// directives/highlight.directive.ts + +import { Directive, ElementRef, Renderer2, Input } from '@angular/core'; + +@Directive({ + selector: '[appHighlight]' +}) +export class HighlightDirective { + constructor( + private renderer: Renderer2, + private host: ElementRef + ) { } + + @Input() set appHighlight (color: string) { + this.renderer.setStyle(this.host.nativeElement, 'background-color', color); + } +} +``` + +```html +// app.component.html + +

Highlighted Text!

+``` + +`Renderer2` also gets instantiated. Which injector do these services come from? Well, each service’s source code comes from `@angular/core`. These services must then register with the application’s root injector. + +```typescript +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; +import { AppComponent } from './app.component'; +import { HighlightDirective } from './directives/highlight.directive'; + +@NgModule({ + declarations: [ + AppComponent, + HighlightDirective + ], + imports: [ + BrowserModule + ], + providers: [], + bootstrap: [ + AppComponent + ] +}) +export class AppModule { } +``` + +An empty providers array!? Not to fear. Angular registers many services with the root injector automatically. This includes `ElementRef` and `Renderer2`. In this example, we are managing the host element through its interface stemming from the instantiation of `ElementRef`. `Renderer2` lets us update the DOM through Angular’s view model. + +You can read more about views from [this article](https://guide.freecodecamp.org/angular/views). They are the preferred method for DOM/view updates in Angular applications. + +It is important recognize the role that injectors play in the above example. By declaring variable types in the constructor, the class obtains valuable services. Each parameter’s data type maps to a set of instructions within the injector. If the injector has that type, it returns an instance of said type. + +## Instantiating Services + +The [Services and Injectors](https://guide.freecodecamp.org/angular/services-and-injectors) article explains this section to an extent. Though, this section rehashes the previous section or the most part. Services will often provide references to something else. They may just as well provide an interface extending a class’ capabilities. + +The next example will define a logging service that gets added to a component’s injector via its `providers: []` metadata. + +```typescript +// services/logger.service.ts + +import { Injectable } from '@angular/core'; + +@Injectable() +export class LoggerService { + callStack: string[] = []; + + addLog(message: string): void { + this.callStack = [message].concat(this.callStack); + this.printHead(); + } + + clear(): void { + this.printLog(); + this.callStack = []; + console.log("DELETED LOG"); + } + + private printHead(): void { + console.log(this.callStack[0] || null); + } + + private printLog(): void { + this.callStack.reverse().forEach((log) => console.log(message)); + } +} +``` + +```typescript +// app.component.ts + +import { Component } from '@angular/core'; +import { LoggerService } from './services/logger.service'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + providers: [LoggerService] +}) +export class AppComponent { + constructor(private logger: LoggerService) { } + + logMessage(event: any, message: string): void { + event.preventDefault(); + this.logger.addLog(`Message: ${message}`); + } + + clearLog(): void { + this.logger.clear(); + } +} +``` + +```html +// app.component.html + +

Log Example

+
+ + +
+ +

Delete Logged Messages

+ +``` + +Focus on the AppComponent constructor and metadata. The component injector receives instructions from the provider’s metadata field containing LoggerService. The injector then knows what to instantiate LoggerService from requested in the constructor. + +The constructor parameter `loggerService` has the type `LoggerService` which the injector recognizes. The injector follows through with the instantiation as mentioned. + +## Conclusion + +Dependency injection (DI) is a paradigm. The way it works in Angular is through a hierarchy of injectors. A class receives its resources without having to create or know about them. Injectors receive instruction and instantiate a service depending on which one was requested. + +DI shows up a lot in Angular. The official Angular documentation explains why the paradigm is so prevalent. They also go on to describe the numerous use-cases for DI in Angular way beyond what was discussed in this article. Check it out by clicking below! diff --git a/_posts/2020-12-18-fetch-async-await-json.md b/_posts/2020-12-18-fetch-async-await-json.md new file mode 100644 index 00000000000..9298e6831e5 --- /dev/null +++ b/_posts/2020-12-18-fetch-async-await-json.md @@ -0,0 +1,208 @@ +--- +layout: post +title: "Use JavaScript Fetch with async/await: Get JSON Data" +subtitle: +categories: javascript +tags: [javascript] +--- + + +The [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) is the default tool to make network in web applications. While `fetch()` is generally easy to use, there some nuances to be aware of. + +In this post, you’ll find the common scenarios of how to use `fetch()` with `async/await` syntax. You’ll understand how to fetch data, handle fetch errors, cancel a fetch request, and more. + + +## Intro to _fetch()_ + +The Fetch API accesses resources across the network. You can make HTTP requests (using `GET`, `POST` and other methods), download, and upload files. + +To start a request, call the special function `fetch()`: + +```javascript +const response = await fetch(resource[, options]); +``` + +which accepts 2 arguments: + +- `resource`: the URL string, or a [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object +- `options`: the configuration object with properties like `method`, `headers`, `body`, `credentials`, [and more](https://javascript.info/fetch-api). + +`fetch()` starts a request and returns a promise. When the request completes, the promise is resolved with the [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) object. If the request fails due to some network problems, the promise is rejected. + +`async/await` syntax fits great with `fetch()` because it simplifies the work with promises. + +For example, let’s make a request to fetch some movies: + +```javascript +async function fetchMovies() { + const response = await fetch('/movies'); + // waits until the request completes... + console.log(response); +} +``` + +`fetchMovies()` is an asynchronous function since it’s marked with the `async` keyword. + +`await fetch('/movies')` starts an HTTP request to `'/movies'` URL. Because the `await` keyword is present, the asynchronous function is paused until the request completes. + +When the request completes, `response` is assigned with the response object of the request. Let’s see in the next section how to extract useful data, like JSON or plain text, from the response. + +## Fetching JSON + +The `response` object, returned by the `await fetch()`, is a generic placeholder for multiple data formats. + +For example, you can extract the JSON object from a fetch response: + +```javascript +async function fetchMoviesJSON() { + const response = await fetch('/movies'); + const movies = await response.json(); return movies; +} + +fetchMoviesJSON().then(movies => { + movies; // fetched movies +}); +``` + +`response.json()` is a method on the Response object that lets you extract a JSON object from the response. The method returns a promise, so you have to wait for the JSON: `await response.json()`. + +The [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) object offers a lot of useful methods (all returning promises): + +- `response.json()` returns a promise resolved to a JSON object +- `response.text()` returns a promise resolved to raw text +- `response.formData()` returns a promise resolved to [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData) +- `response.blob()` returns a promise resolved to a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) (a file-like object of raw data) +- `response.arrayBuffer()()` returns a promise resolved to an [ArryBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) (raw generic binary data) + +## Handling fetch errors + +When I was familiarizing with `fetch()`, I was surprised that `fetch()` doesn’t throw an error when the server returns a bad HTTP status, e.g. client (`400–499`) or server errors (`500–599`). + +For example, let’s access a non-existing page `'/oops'` on the server. As expected, such request ends in a `404` response status: + +```javascript +async function fetchMovies404() { + const response = await fetch('/oops'); + + response.ok; // => false + response.status; // => 404 + + const text = await response.text(); + return text; +} + +fetchMovies404().then(text => { + text; // => 'Page not found' +}); +``` + +When fetching the URL `'/oops'` the server responds with status `404` and text `'Page not found'`. Surprisingly, `fetch()` doesn’t throw an error for a missing URL, but considers this as a _completed_ HTTP request. + +`fetch()` rejects only if a request cannot be made or a response cannot be retrieved. It might happen because of network problems: no internet connection, host not found, the server is not responding. + +Fortunately, `response.ok` property lets you separate good from bad HTTP response statuses. The property is set to `true` only if the response has status `200-299`. + +In the above example, the `response.ok` property is `false` because the response has the status `404`. + +If you’d like to throw an error on a _bad HTTP status_ (outside of the range `200-299`), check the value of `response.ok` property and throw an error manually: + +```javascript +async function fetchMoviesBadStatus() { + const response = await fetch('/oops'); + + if (!response.ok) { const message = `An error has occured: ${response.status}`; throw new Error(message); } + const movies = await response.json(); + return movies; +} + +fetchMoviesBadStatus().catch(error => { + error.message; // 'An error has occurred: 404' +}); +``` + +## Canceling a fetch request + +Unfortunately, `fetch()` API alone doesn’t allow to cancel a fetch request once started. To cancel a fetch request you need an additional tool [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController). + +Connecting `fetch()` and `AbortController` requires 3 steps: + +```javascript +// Step 1: instantiate the abort controller +const controller = new AbortController(); + +// Step 2: make the fetch() aware of controller.signal +fetch(..., { signal: controller.signal }); + +// Step 3: call to cancel the request +controller.abort(); +``` + +A) Before starting the request, create an abort controller instance: `controller = new AbortController()`. + +B) When starting the request properly, use the options argument of `fetch(url, { signal: controller.signal })` and set `signal` property to be `controller.signal`. + +C) Finally, if you need to cancel the request, just call `controller.abort()` method. + +For example, let’s implement 2 buttons that control a fetch request. Clicking the button _Fetch movies_ starts a `fetch()` request, while clicking _Cancel fetch_ aborts the request in progress: + +```javascript +let controller = null; + +fetchMoviesButton.addEventListener('click', async () => { + controller = new AbortController(); try { + const response = await fetch('/movies', { + signal: controller.signal }); + } catch (error) { + console.log('Fetch error: ', error); + } + controller = null; +}); + +cancelFetchButton.addEventListener('click', () => { + if (controller) { + controller.abort(); } +}); +``` + +Open [the demo](https://codesandbox.io/s/cancel-fetch-request-ggieh?file=/src/index.html). Click _Fetch movies_ to start the request, then right away click _Cancel fetch_ to cancel it. This makes the active request cancel: `await fetch()` gets rejected by throwing an abort error. The `catch` block then catches the abort error. + +The abort controller instances aren’t reusable. Each time you start a `fetch()` request, you have to create a new abort controller instance for each request. + + +## Parallel fetch requests + +To perform parallel fetch requests use the [Promise.all()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) helper function. + +Let’s start 2 parallel requests to fetch movies and categories: + +```javascript +async function fetchMoviesAndCategories() { + const [moviesResponse, categoriesResponse] = await Promise.all([ fetch('/movies'), fetch('/categories') ]); + const movies = await moviesResponse.json(); + const categories = await categoriesResponse.json(); + + return [movies, categories]; +} + +fetchMoviesAndCategories().then(([movies, categories]) => { + movies; // fetched movies + categories; // fetched categories +}).catch(error => { + // /movies or /categories request failed +}); +``` + +`await Promise.all([...])` starts fetch requests in parallel, and waits until all of them are resolved. + +If any request fails, then the whole parallel promise gets rejected right away with the failed request error. + +In case if you want all parallel requests to complete, despite any of them fail, consider using [Promise.allSettled()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled). + +## Summary + +Calling `fetch()` starts a request and returns a promise. When the request completes, the promise resolves to the response object. From the response object you can extract data in the format you need: JSON, raw text, Blob. + +Because `fetch()` returns a promise, you can simplify the code by using the `async/await` syntax: `response = await fetch()`. + +You’ve found out how to use `fetch()` accompanied with `async/await` to fetch JSON data, handle fetching errors, cancel a request, perform parallel requests. + diff --git a/_posts/2021-05-01-introduction.md b/_posts/2021-05-01-introduction.md new file mode 100644 index 00000000000..8dd2f6d4c6a --- /dev/null +++ b/_posts/2021-05-01-introduction.md @@ -0,0 +1,644 @@ +--- +layout: post +title: 30 Days Of JavaScript +subheading: Introduction +author: John +categories: javascript +banner: https://bit.ly/32PAjtM +tags: javascript +sidebar: [] +--- + + +| # Day | Topics | +| ----- | :-------------------------------------------------------------------------------------------------------------------------------------------------: | +| 01 | [Introduction](./readMe.md) | +| 02 | [Data Types](./02_Day_Data_types/02_day_data_types.md) | +| 03 | [Booleans, Operators, Date](./03_Day_Booleans_operators_date/03_booleans_operators_date.md) | +| 04 | [Conditionals](./04_Day_Conditionals/04_day_conditionals.md) | +| 05 | [Arrays](./05_Day_Arrays/05_day_arrays.md) | +| 06 | [Loops](./06_Day_Loops/06_day_loops.md) | +| 07 | [Functions](./07_Day_Functions/07_day_functions.md) | +| 08 | [Objects](./08_Day_Objects/08_day_objects.md) | +| 09 | [Higher Order Functions](./09_Day_Higher_order_functions/09_day_higher_order_functions.md) | +| 10 | [Sets and Maps](./10_Day_Sets_and_Maps/10_day_Sets_and_Maps.md) | +| 11 | [Destructuring and Spreading](./11_Day_Destructuring_and_spreading/11_day_destructuring_and_spreading.md) | +| 12 | [Regular Expressions](./12_Day_Regular_expressions/12_day_regular_expressions.md) | +| 13 | [Console Object Methods](./13_Day_Console_object_methods/13_day_console_object_methods.md) | +| 14 | [Error Handling](./14_Day_Error_handling/14_day_error_handling.md) | +| 15 | [Classes](./15_Day_Classes/15_day_classes.md) | +| 16 | [JSON](./16_Day_JSON/16_day_json.md) | +| 17 | [Web Storages](./17_Day_Web_storages/17_day_web_storages.md) | +| 18 | [Promises](./18_Day_Promises/18_day_promises.md) | +| 19 | [Closure](./19_Day_Closures/19_day_closures.md) | +| 20 | [Writing Clean Code](./20_Day_Writing_clean_codes/20_day_writing_clean_codes.md) | +| 21 | [DOM](./21_Day_DOM/21_day_dom.md) | +| 22 | [Manipulating DOM Object](./22_Day_Manipulating_DOM_object/22_day_manipulating_DOM_object.md) | +| 23 | [Event Listeners](./23_Day_Event_listeners/23_day_event_listeners.md) | +| 24 | [Mini Project: Solar System](./24_Day_Project_solar_system/24_day_project_solar_system.md) | +| 25 | [Mini Project: World Countries Data Visulalization 1](./25_Day_World_countries_data_visualization_1/25_day_world_countries_data_visualization_1.md) | +| 26 | [Mini Project: World Countries Data Visulalization 2](./26_Day_World_countries_data_visualization_2/26_day_world_countries_data_visualization_2.md) | +| 27 | [Mini Project: Portfolio](./27_Day_Mini_project_portfolio/27_day_mini_project_portfolio.md) | +| 28 | [Mini Project: Leaderboard](./28_Day_Mini_project_leaderboard/28_day_mini_project_leaderboard.md) | +| 29 | [Mini Project:Animating characters](./29_Day_Mini_project_animating_characters/29_day_mini_project_animating_characters.md) | +| 30 | [Final Projects](./30_Day_Mini_project_final/30_day_mini_project_final.md) | + +🧡🧡🧡 HAPPY CODING 🧡🧡🧡 + + +[Day 2>>](./02_Day_Data_types/02_day_data_types.md) + +![Thirty Days Of JavaScript](./images/day_1_1.png) + +- [30 Days Of JavaScript](#30-days-of-javascript) +- [📔 Day 1](#-day-1) + - [Introduction](#introduction) + - [Requirements](#requirements) + - [Setup](#setup) + - [Install Node.js](#install-nodejs) + - [Browser](#browser) + - [Installing Google Chrome](#installing-google-chrome) + - [Opening Google Chrome Console](#opening-google-chrome-console) + - [Writing Code on Browser Console](#writing-code-on-browser-console) + - [Console.log](#consolelog) + - [Console.log with Multiple Arguments](#consolelog-with-multiple-arguments) + - [Comments](#comments) + - [Syntax](#syntax) + - [Arithmetics](#arithmetics) + - [Code Editor](#code-editor) + - [Installing Visual Studio Code](#installing-visual-studio-code) + - [How to Use Visual Studio Code](#how-to-use-visual-studio-code) + - [Adding JavaScript to a Web Page](#adding-javascript-to-a-web-page) + - [Inline Script](#inline-script) + - [Internal Script](#internal-script) + - [External Script](#external-script) + - [Multiple External Scripts](#multiple-external-scripts) + - [Introduction to Data types](#introduction-to-data-types) + - [Numbers](#numbers) + - [Strings](#strings) + - [Booleans](#booleans) + - [Undefined](#undefined) + - [Null](#null) + - [Checking Data Types](#checking-data-types) + - [Comments Again](#comments-again) + - [Variables](#variables) +- [💻 Day 1: Exercises](#-day-1-exercises) + +## 📔 Day 1 + +## Introduction + +**Congratulations** on deciding to participate in 30 days of JavaScript programming challenge. In this challenge you will learn everything you need to be a JavaScript programmer, and in general, the whole concept of programming. In the end of the challenge you will get a 30DaysOfJavaScript programming challenge completion certificate. In case you need help or if you would like to help others you may join the [telegram group](https://t.me/ThirtyDaysOfJavaScript). + +**A 30DaysOfJavaScript** challenge is a guide for both beginners and advanced JavaScript developers. Welcome to JavaScript. JavaScript is the language of the web. I enjoy using and teaching JavaScript and I hope you will do so too. + +In this step by step JavaScript challenge, you will learn JavaScript, the most popular programming language in the history of mankind. +JavaScript is used **_to add interactivity to websites, to develop mobile apps, desktop applications, games_** and nowadays JavaScript can be used for **_machine learning_** and **_AI_**. +**_JavaScript (JS)_** has increased in popularity in recent years and has been the leading +programming language for six consecutive years and is the most used programming language on +Github. + +## Requirements + +No prior knowledge of programming is required to follow this challenge. You need only: + +1. Motivation +2. A computer +3. Internet +4. A browser +5. A code editor + +## Setup + +I believe you have the motivation and a strong desire to be a developer, a computer and Internet. If you have those, then you have everything to get started. + +### Install Node.js + +You may not need node.js right now but you may need it for later. Install [node.js](https://nodejs.org/en/). + +![Node download](images/download_node.png) + +After downloading double click and install + +![Install node](images/install_node.png) + +We can check if node is installed on our local machine by opening our device terminal or command prompt. + +```sh +asabeneh $ node -v +v12.14.0 +``` + +When making this tutorial I was using node version 12.14.0, but now the recommended version of node.js for download is 12.17.0. + +### Browser + +There are many browsers out there. However, I strongly recommend Google Chrome. + +#### Installing Google Chrome + +Install [google chrome](https://www.google.com/chrome/) if you do not have one yet. We can write small JavaScript code on the browser console, but we do not use the browser console to develop applications. + +![Google Chrome](images/google_chrome.png) + +#### Opening Google Chrome Console + +You can open Google Chrome console either by clicking three dots at the top right corner of the browser, selecting _More tools -> Developer tools_ or using a keyboard shortcut. I prefer using shortcuts. + +![Opening chrome](images/opening_developer_tool.png) + +To open the Chrome console using a keyboard shortcut. + +```sh +Mac +Command+Option+J + +Windows/Linux: +Ctl+Shift+J +``` + +![Opening console](images/opening_chrome_console_shortcut.png) + +After you open the Google Chrome console, try to explore the marked buttons. We will spend most of the time on the Console. The Console is the place where your JavaScript code goes. The Google Console V8 engine changes your JavaScript code to machine code. +Let us write a JavaScript code on the Google Chrome console: + +![write code on console](./images/js_code_on_chrome_console.png) + +#### Writing Code on Browser Console + +We can write any JavaScript code on the Google console or any browser console. However, for this challenge, we only focus on Google Chrome console. Open the console using: + +```sh +Mac +Command+Option+I + +Windows: +Ctl+Shift+I +``` + +##### Console.log + +To write our first JavaScript code, we used a built-in function **console.log()**. We passed an argument as input data, and the function displays the output. We passed 'Hello, World' as input data or argument in the console.log() function. + +```js +console.log('Hello, World!') +``` + +##### Console.log with Multiple Arguments + +The **conole.log()** function can take multiple parameters separated by comma. The syntax looks like as follows:**console.log(param1, param2, param3)** + +![console log multiple arguments](./images/console_log_multipl_arguments.png) + +```js +console.log('Hello', 'World', '!') +console.log('HAPPY', 'NEW', 'YEAR', 2020) +console.log('Welcome', 'to', 30, 'Days', 'Of', 'JavaScript') +``` + +As you can see from the snippet code above, _console.log()_ can take multiple arguments. + +Congratulations! You wrote your first JavaScript code using _console.log()_. + +##### Comments + +We add comments to our code. Comments are very important to make code more readable and to leave remarks in our code. JavaScript does not execute the comment part of our code.In JavaScript, any text line starting with // in JavaScript is a comment, and anything enclosed like this /\* \*/ is also a comment. + +**Example: Single Line Comment** + +// This is the first comment + // This is the second comment + // I am a single line comment + +**Example: Multiline Comment** + +/_ +This is a multiline comment + Multiline comments can take multiple lines + JavaScript is the language of the web + _/ + +##### Syntax + +Programming languages are similar to human languages. English or many other language uses words, phrases, sentences,compound sentences and other more to convey a meaningful message. The English meaning of syntax is _the arrangement of words and phrases to create well-formed sentences in a language_. The technical definition of syntax is _the structure of statements in a computer language._ Programing languages have syntax. JavaScript is a programming language and like other programming languages it has its own syntax. If we do not write a syntax that JavaScript understands, it will raise different types of errors. We will explore different kinds of JavaScript errors later. For now, let us see syntax errors. + +![Error](images/raising_syntax_error.png) + +I made a deliberate mistake. As a result, the console raises syntax errors. Actually, the syntax is very informative. It informs what type of mistake was made. By reading the error feedback guideline, we can correct the syntax and fix the problem. The process of identifying and removing errors from a program is called debugging. Let us fix the errors: + +```js +console.log('Hello, World!') +console.log('Hello, World!') +``` + +So far, we saw how to display text using the _console.log()_. If we are printing text or string using _console.log()_, the text has to be inside the single quotes, double quotes, or a backtick quotes. +**Example:** + +```js +console.log('Hello, World!') +console.log('Hello, World!') +console.log(`Hello, World!`) +``` + +#### Arithmetics + +Now, let us practice more writing JavaScript codes using _console.log()_ on google chrome console for number data types. +In addition to the text, we can also do mathematical calculations using JavaScript. Let us do the following simple calculations. +The console can directly take arguments without the **_console.log()_** function. However, it is included in this introduction because most of this challenge would be taking place in a text editor where the usage of the function would be mandatory. You can play around directly with instructions on the console. + +![Arithmetic](images/arithmetic.png) + +```js +console.log(2 + 3) // Addition +console.log(3 - 2) // Subtraction +console.log(2 * 3) // Multiplication +console.log(3 / 2) // Division +console.log(3 % 2) // Modulus - finding remainder +console.log(3 ** 2) // Exponentiation 3 ** 2 == 3 * 3 +``` + +### Code Editor + +We can write our codes on the browser console, but it won't do for bigger projects. In a real working environment, developers use different code editors to write their codes. In this 30 days JavaScript challenge, we will be using Visual Studio Code. + +#### Installing Visual Studio Code + +Visual studio code is a very popular open-source text editor. I would recommend to [download Visual Studio Code](https://code.visualstudio.com/), but if you are in favor of other editors, feel free to follow with what you have. + +![Vscode](images/vscode.png) + +If you installed Visual Studio Code, let us start using it. + +#### How to Use Visual Studio Code + +Open the Visual Studio Code by double-clicking its icon. When you open it, you will get this kind of interface. Try to interact with the labeled icons. + +![Vscode ui](./images/vscode_ui.png) + +![Vscode add project](./images/adding_project_to_vscode.png) + +![Vscode open project](./images/opening_project_on_vscode.png) + +![script file](images/scripts_on_vscode.png) + +![Installing Live Server](images/vsc_live_server.png) + +![running script](./images/running_script.png) + +![coding running](./images/launched_on_new_tab.png) + +## Adding JavaScript to a Web Page + +JavaScript can be added to a web page in three different ways: + +- **_Inline script_** +- **_Internal script_** +- **_External script_** +- **_Multiple External scripts_** + +The following sections show different ways of adding JavaScript code to your web page. + +### Inline Script + +Create a project folder on your desktop or in any location, name it 30DaysOfJS and create an **_index.html_** file in the project folder. Then paste the following code and open it in a browser, for example [Chrome](https://www.google.com/chrome/). + +```html + + + + 30DaysOfScript:Inline Script + + + + + +``` + +Now, you just wrote your first inline script. We can create a pop up alert message using the _alert()_ built-in function. + +### Internal Script + +The internal script can be written in the _head_ or the _body_, but it is preferred to put it on the body of the HTML document. +First, let us write on the head part of the page. + +```html + + + + 30DaysOfScript:Internal Script + + + + +``` + +This is how we write an internal script most of the time. Writing the JavaScript code in the body section is the most preferred option. Open the browser console to see the output from the console.log() + +```html + + + + 30DaysOfScript:Internal Script + + + + + + +``` + +Open the browser console to see the output from the console.log() + +![js code from vscode](./images/js_code_vscode.png) + +### External Script + +Similar to the internal script, the external script link can be on the header or body, but it is preferred to put it in the body. +First, we should create an external JavaScript file with .js extension. All files ending with .js extension. All files ending with .js extension are JavaScript files. Create a file named introduction.js inside your project directory and write the following code and link this .js file at the bottom of the body. + +```js +console.log('Welcome to 30DaysOfJavaScript') +``` + +External scripts in the _head_: + +```html + + + + 30DaysOfJavaScript:External script + + + + +``` + +External scripts in the _body_: + +```html + + + + 30DaysOfJavaScript:External script + + + //it could be in the header or in the body // Here is the recommended place + to put the external script + + + +``` + +Open the browser console to see the output of the console.log() + +### Multiple External Scripts + +We can also link multiple external JavaScript files to a web page. +Create a helloworld.js file inside the 30DaysOfJS folder and write the following code. + +```js +console.log('Hello, World!') +``` + +```html + + + + Multiple External Scripts + + + + + + +``` + +_Your main.js file should be below all other scripts_. It is very important to remember this. + +![Multiple Script](./images/multiple_script.png) + +## Introduction to Data types + +In JavaScript and also other programming languages, there are different kinds of data types. The following are JavaScript primitive data types:_String, Number, Boolean, undefined, Null_, and _Symbol_. + +### Numbers + +- Integers: Integer (negative, zero and positive) numbers + Example: + ... -3, -2, -1, 0, 1, 2, 3 ... +- Float-point numbers: Decimal number + Example + ... -3.5, -2.25, -1.0, 0.0, 1.1, 2.2, 3.5 ... + +### Strings + +A collection of one or more characters between two single quotes, double quotes, or backticks. +**Example:** + +```js +'Asabeneh' +'Finland' +'JavaScript is a beautiful programming language' +'I love teaching' +'I hope you are enjoying the first day'`We can also create a string using a backtick` +;('A string could be just as small as one character as big as many pages') +``` + +### Booleans + +A boolean value is either True or False. Any comparisons return a boolean value, which is either true or false. + +A boolean data type is either a true or false value. + +**Example:** + +```js +true // if the light on ,the value is true +false // if the light off, the value is false +``` + +### Undefined + +In JavaScript, if we don't assign a value to a variable, the value is undefined. In addition to that, if a function is not returning anything, it returns undefined. + +```js +let firstName +console.log(firstName) //not defined, because it is not assigned to a value yet +``` + +### Null + +Null in JavaScript means an empty value. + +```js +let emptyValue = null +``` + +## Checking Data Types + +To check the data type of a certain variable, we use the **typeof** operator. See the following example. + +```js +console.log(typeof 'Asabeneh') // string +console.log(typeof 5) // number +console.log(typeof true) // boolean +console.log(typeof null) // object type +console.log(typeof undefined) // undefined +``` + +## Comments Again + +Remember that commenting in JavaScript is similar to other programming languages. Comments are important in making your code more readable. +There are two ways of commenting: + +- _Single line commenting_ +- _Multiline commenting_ + +```js +// commenting the code itself with a single comment +// let firstName = 'Asabeneh'; single line comment +// let lastName = 'Yetayeh'; single line comment +``` + +Multiline commenting: + +```js +/* + let location = 'Helsinki'; + let age = 100; + let isMarried = true; + This is a Multiple line comment + */ +``` + +## Variables + +Variables are _containers_ of data. Variables are used to _store_ data in a memory location. When a variable is declared, a memory location is reserved. When a variable is assigned to a value (data), the memory space will be filled with that data. To declare a variable, we use _var_, _let_, or _const_ keywords. + +For a variable that changes at a different time, we use _let_. If the data does not change at all, we use _const_. For example, PI, country name, gravity do no change, and we can use _const_. We will not use var in this challenge and I don't recommend you to use it. It is error prone way of declaring variable it has lots of leak. We will talk more about var, let, and const in detail in other sections (scope). For now, the above explanation is enough. + +A valid JavaScript variable name must follow the following rules: + +- A JavaScript variable name should not begin with a number. +- A JavaScript variable name does not allow special characters except dollar sign and underscore. +- A JavaScript variable name follows a camelCase convention. +- A JavaScript variable name should not have space between words. + +The following are examples of valid JavaScript variables. + +```js +firstName +lastName +country +city +capitalCity +age +isMarried + +first_name +last_name +is_married +capital_city + +num1 +num_1 +_num_1 +$num1 +year2020 +year_2020 +``` + +The first and second variables on the list follows the camelCase convention of declaring in JavaScrip. In this material, we will use camelCase variables. + +Example of invalid variables: + +```sh + first-name + 1_num + num_#_1 +``` + +Let us declare variables with different data types. To declare a variable, we need to use _let_ or _const_ keyword before the variable name. Following the variable name, we write an equal sign (assignment operator), and a value(assigned data). + +```js +// Syntax +let nameOfVariable = value +``` + +**Examples of declared variables** + +```js +// Declaring different variables of different data types +let firstName = 'Asabeneh' // first name of a person +let lastName = 'Yetayeh' // last name of a person +let country = 'Finland' // country +let city = 'Helsinki' // capital city +let age = 100 // age in years +let isMarried = true + +console.log(firstName, lastName, country, city, age, isMarried) +``` + +```sh +Asabeneh Yetayeh Finland Helsinki 100 True +``` + +```js +// Declaring variables with number values +let age = 100 // age in years +const gravity = 9.81 // earth gravity in m/s2 +const boilingPoint = 100 // water boiling point, temperature in oC +const PI = 3.14 // geometrical constant + +console.log(gravity, boilingPoint, PI) +``` + +```sh +9.81 100 3.14 +``` + +```js +// Variables can also be declaring in one line separated by comma +let name = 'Asabeneh', // name of a person + job = 'teacher', + live = 'Finland' +console.log(name, job, live) +``` + +```sh +Asabeneh teacher Finland +``` + +When you run _index.html_ file in the 01-Day folder you should get this: + +![Day one](./images/day_1.png) + +🌕 You are amazing! You have just completed day 1 challenge and you are on your way to greatness. Now do some exercises for your brain and muscle. + +# 💻 Day 1: Exercises + +1. Write a single line comment which says, _comments can make code readable_ +2. Write another single comment which says, _Welcome to 30DaysOfJavaScript_ +3. Write a multiline comment which says, _comments can make code readable, easy to reuse_ + _and informative_ + +4. Create a variable.js file and declare variables and assign string, boolean, undefined and null data types +5. Create datatypes.js file and use the JavaScript **_typeof_** operator to check different data types. Check the data type of each variable +6. Declare four variables without assigning values +7. Declare four variables with assigned values +8. Declare variables to store your first name, last name, marital status, country and age in multiple lines +9. Declare variables to store your first name, last name, marital status, country and age in a single line +10. Declare two variables _myAge_ and _yourAge_ and assign them initial values and log to the browser console. + +```sh +I am 25 years old. +You are 30 years old. +``` + +🎉 CONGRATULATIONS ! 🎉 + +[Day 2>>](./02_Day_Data_types/02_day_data_types.md) diff --git a/_posts/2021-05-12-data-types.md b/_posts/2021-05-12-data-types.md new file mode 100644 index 00000000000..ae34259c0c2 --- /dev/null +++ b/_posts/2021-05-12-data-types.md @@ -0,0 +1,963 @@ +--- +layout: post +title: "30 Days Of JavaScript: Data Types" +subtitle: Learn about data types +categories: javascript +tags: [javascript] +--- + +- [📔 Day 2](#-day-2) + - [Data Types](#data-types) + - [Primitive Data Types](#primitive-data-types) + - [Non-Primitive Data Types](#non-primitive-data-types) + - [Numbers](#numbers) + - [Declaring Number Data Types](#declaring-number-data-types) + - [Math Object](#math-object) + - [Random Number Generator](#random-number-generator) + - [Strings](#strings) + - [String Concatenation](#string-concatenation) + - [Concatenating Using Addition Operator](#concatenating-using-addition-operator) + - [Long Literal Strings](#long-literal-strings) + - [Escape Sequences in Strings](#escape-sequences-in-strings) + - [Template Literals (Template Strings)](#template-literals-template-strings) + - [String Methods](#string-methods) + - [Checking Data Types and Casting](#checking-data-types-and-casting) + - [Checking Data Types](#checking-data-types) + - [Changing Data Type (Casting)](#changing-data-type-casting) + - [String to Int](#string-to-int) + - [String to Float](#string-to-float) + - [Float to Int](#float-to-int) + - [💻 Day 2: Exercises](#-day-2-exercises) + - [Exercise: Level 1](#exercise-level-1) + - [Exercise: Level 2](#exercise-level-2) + - [Exercises: Level 3](#exercises-level-3) + +# 📔 Day 2 + +## Data Types + +In the previous section, we mentioned a little bit about data types. Data or values have data types. Data types describe the characteristics of data. Data types can be divided into two: + +1. Primitive data types +2. Non-primitive data types(Object References) + +### Primitive Data Types + +Primitive data types in JavaScript include: + + 1. Numbers - Integers, floats + 2. Strings - Any data under single quote, double quote or backtick quote + 3. Booleans - true or false value + 4. Null - empty value or no value + 5. Undefined - a declared variable without a value + +Non-primitive data types in JavaScript includes: + +1. Objects +2. Functions +3. Arrays + +Now, let us see what exactly primitive and non-primitive data types mean. +*Primitive* data types are immutable(non-modifiable) data types. Once a primitive data type is created we cannot modify it. + +**Example:** + +```js +let word = 'JavaScript' +``` + +If we try to modify the string stored in variable *word*, JavaScript should raise an error. Any data type under a single quote, double quote, or backtick quote is a string data type. + +```js +word[0] = 'Y' +``` + +This expression does not change the string stored in the variable *word*. So, we can say that strings are not modifiable or in other words immutable. +Primitive data types are compared by its values. Let us compare different data values. See the example below: + +```js +let numOne = 3 +let numTwo = 3 + +console.log(numOne == numTwo) // true + +let js = 'JavaScript' +let py = 'Python' + +console.log(js == py) //false + +let lightOn = true +let lightOff = false + +console.log(lightOn == lightOff) // false +``` + +### Non-Primitive Data Types + +*Non-primitive* data types are modifiable or mutable. We can modify the value of non-primitive data types after it gets created. +Let us see by creating an array. An array is a list of data values in a square bracket. Arrays can contain the same or different data types. Array values are referenced by their index. In JavaScript array index starts at zero. I.e., the first element of an array is found at index zero, the second element at index one, and the third element at index two, etc. + +```js +let nums = [1, 2, 3] +nums[0] = 10 + +console.log(nums) // [10, 2, 3] +``` + +As you can see, an array, which is a non-primitive data type is mutable. Non-primitive data types cannot be compared by value. Even if two non-primitive data types have the same properties and values, they are not strictly equal. + +```js +let nums = [1, 2, 3] +let numbers = [1, 2, 3] + +console.log(nums == numbers) // false + +let userOne = { +name:'Asabeneh', +role:'teaching', +country:'Finland' +} + +let userTwo = { +name:'Asabeneh', +role:'teaching', +country:'Finland' +} + +console.log(userOne == userTwo) // false +``` + +Rule of thumb, we do not compare non-primitive data types. Do not compare arrays, functions, or objects. +Non-primitive values are referred to as reference types, because they are being compared by reference instead of value. Two objects are only strictly equal if they refer to the same underlying object. + +```js +let nums = [1, 2, 3] +let numbers = nums + +console.log(nums == numbers) // true + +let userOne = { +name:'Asabeneh', +role:'teaching', +country:'Finland' +} + +let userTwo = userOne + +console.log(userOne == userTwo) // true +``` + +If you have a hard time understanding the difference between primitive data types and non-primitive data types, you are not the only one. Calm down and just go to the next section and try to come back after some time. Now let us start the data types by number type. + +## Numbers + +Numbers are integers and decimal values which can do all the arithmetic operations. +Let's see some examples of Numbers. + +### Declaring Number Data Types + +```js +let age = 35 +const gravity = 9.81 // we use const for non-changing values, gravitational constant in m/s2 +let mass = 72 // mass in Kilogram +const PI = 3.14 // pi a geometrical constant + +// More Examples +const boilingPoint = 100 // temperature in oC, boiling point of water which is a constant +const bodyTemp = 37 // oC average human body temperature, which is a constant + +console.log(age, gravity, mass, PI, boilingPoint, bodyTemp) +``` + +### Math Object + +In JavaScript the Math Object provides a lots of methods to work with numbers. + +```js +const PI = Math.PI + +console.log(PI) // 3.141592653589793 + +// Rounding to the closest number +// if above .5 up if less 0.5 down rounding + +console.log(Math.round(PI)) // 3 to round values to the nearest number + +console.log(Math.round(9.81)) // 10 + +console.log(Math.floor(PI)) // 3 rounding down + +console.log(Math.ceil(PI)) // 4 rounding up + +console.log(Math.min(-5, 3, 20, 4, 5, 10)) // -5, returns the minimum value + +console.log(Math.max(-5, 3, 20, 4, 5, 10)) // 20, returns the maximum value + +const randNum = Math.random() // creates random number between 0 to 0.999999 +console.log(randNum) + +// Let us create random number between 0 to 10 + +const num = Math.floor(Math.random () * 11) // creates random number between 0 and 10 +console.log(num) + +//Absolute value +console.log(Math.abs(-10)) // 10 + +//Square root +console.log(Math.sqrt(100)) // 10 + +console.log(Math.sqrt(2)) // 1.4142135623730951 + +// Power +console.log(Math.pow(3, 2)) // 9 + +console.log(Math.E) // 2.718 + +// Logarithm +// Returns the natural logarithm with base E of x, Math.log(x) +console.log(Math.log(2)) // 0.6931471805599453 +console.log(Math.log(10)) // 2.302585092994046 + +// Trigonometry +Math.sin(0) +Math.sin(60) + +Math.cos(0) +Math.cos(60) +``` + +#### Random Number Generator + +The JavaScript Math Object has a random() method number generator which generates number from 0 to 0.999999999... + +```js +let randomNum = Math.random() // generates 0 to 0.999... +``` + +Now, let us see how we can use random() method to generate a random number between 0 and 10: + +```js +let randomNum = Math.random() // generates 0 to 0.999 +let numBtnZeroAndTen = randomNum * 11 + +console.log(numBtnZeroAndTen) // this gives: min 0 and max 10.99 + +let randomNumRoundToFloor = Math.floor(numBtnZeroAndTen) +console.log(randomNumRoundToFloor) // this gives between 0 and 10 +``` + +## Strings + +Strings are texts, which are under **_single_** , **_double_**, **_back-tick_** quote. To declare a string, we need a variable name, assignment operator, a value under a single quote, double quote, or backtick quote. +Let's see some examples of strings: + +```js +let space = ' ' // an empty space string +let firstName = 'Asabeneh' +let lastName = 'Yetayeh' +let country = 'Finland' +let city = 'Helsinki' +let language = 'JavaScript' +let job = 'teacher' +let quote = "The saying,'Seeing is Believing' is not correct in 2020." +let quotWithBackTick = `The saying,'Seeing is Believing' is not correct in 2020.` +``` + +### String Concatenation + +Connecting two or more strings together is called concatenation. +Using the strings declared in the previous String section: + +```js +let fullName = firstName + space + lastName; // concatenation, merging two string together. +console.log(fullName); +``` + +```sh +Asabeneh Yetayeh +``` + +We can concatenate strings in different ways. + +#### Concatenating Using Addition Operator + +Concatenating using the addition operator is an old way. This way of concatenating is tedious and error-prone. It is good to know how to concatenate this way, but I strongly suggest to use the ES6 template strings (explained later on). + +```js +// Declaring different variables of different data types +let space = ' ' +let firstName = 'Asabeneh' +let lastName = 'Yetayeh' +let country = 'Finland' +let city = 'Helsinki' +let language = 'JavaScript' +let job = 'teacher' +let age = 250 + + +let fullName =firstName + space + lastName +let personInfoOne = fullName + '. I am ' + age + '. I live in ' + country; // ES5 string addition + +console.log(personInfoOne) +``` + +```sh +Asabeneh Yetayeh. I am 250. I live in Finland +``` + +#### Long Literal Strings + +A string could be a single character or paragraph or a page. If the string length is too big it does not fit in one line. We can use the backslash character (\\) at the end of each line to indicate that the string will continue on the next line. +**Example:** + +```js +const paragraph = "My name is Asabeneh Yetayeh. I live in Finland, Helsinki.\ +I am a teacher and I love teaching. I teach HTML, CSS, JavaScript, React, Redux, \ +Node.js, Python, Data Analysis and D3.js for anyone who is interested to learn. \ +In the end of 2019, I was thinking to expand my teaching and to reach \ +to global audience and I started a Python challenge from November 20 - December 19.\ +It was one of the most rewarding and inspiring experience.\ +Now, we are in 2020. I am enjoying preparing the 30DaysOfJavaScript challenge and \ +I hope you are enjoying too." + +console.log(paragraph) +``` + +#### Escape Sequences in Strings + +In JavaScript and other programming languages \ followed by some characters is an escape sequence. Let's see the most common escape characters: + +- \n: new line +- \t: Tab, means 8 spaces +- \\\\: Back slash +- \\': Single quote (') +- \\": Double quote (") + +```js +console.log('I hope everyone is enjoying the 30 Days Of JavaScript challenge.\nDo you ?') // line break +console.log('Days\tTopics\tExercises') +console.log('Day 1\t3\t5') +console.log('Day 2\t3\t5') +console.log('Day 3\t3\t5') +console.log('Day 4\t3\t5') +console.log('This is a backslash symbol (\\)') // To write a backslash +console.log('In every programming language it starts with \"Hello, World!\"') +console.log("In every programming language it starts with \'Hello, World!\'") +console.log('The saying \'Seeing is Believing\' isn\'t correct in 2020') +``` + +Output in console: + +```sh +I hope everyone is enjoying the 30 Days Of JavaScript challenge. +Do you ? +Days Topics Exercises +Day 1 3 5 +Day 2 3 5 +Day 3 3 5 +Day 4 3 5 +This is a backslash symbol (\) +In every programming language it starts with "Hello, World!" +In every programming language it starts with 'Hello, World!' +The saying 'Seeing is Believing' isn't correct in 2020 +``` + +#### Template Literals (Template Strings) + +To create a template strings, we use two back-ticks. We can inject data as expressions inside a template string. To inject data, we enclose the expression with a curly bracket({}) preceded by a $ sign. See the syntax below. + +```js +//Syntax +`String literal text` +`String literal text ${expression}` +``` + +**Example: 1** + +```js +console.log(`The sum of 2 and 3 is 5`) // statically writing the data +let a = 2 +let b = 3 +console.log(`The sum of ${a} and ${b} is ${a + b}`) // injecting the data dynamically +``` + +**Example:2** + +```js +let firstName = 'Asabeneh' +let lastName = 'Yetayeh' +let country = 'Finland' +let city = 'Helsinki' +let language = 'JavaScript' +let job = 'teacher' +let age = 250 +let fullName = firstName + ' ' + lastName + +let personInfoTwo = `I am ${fullName}. I am ${age}. I live in ${country}.` //ES6 - String interpolation method +let personInfoThree = `I am ${fullName}. I live in ${city}, ${country}. I am a ${job}. I teach ${language}.` +console.log(personInfoTwo) +console.log(personInfoThree) +``` + +```sh +I am Asabeneh Yetayeh. I am 250. I live in Finland. +I am Asabeneh Yetayeh. I live in Helsinki, Finland. I am a teacher. I teach JavaScript. +``` + +Using a string template or string interpolation method, we can add expressions, which could be a value, or some operations (comparison, arithmetic operations, ternary operation). + +```js +let a = 2 +let b = 3 +console.log(`${a} is greater than ${b}: ${a> b}`) +``` + +```sh +2 is greater than 3: false +``` + +### String Methods + +Everything in JavaScript is an object. A string is a primitive data type that means we can not modify it once it is created. The string object has many string methods. There are different string methods that can help us to work with strings. + +1. *length*: The string *length* method returns the number of characters in a string included empty space. + +**Example:** + +```js +let js = 'JavaScript' +console.log(js.length) // 10 +let firstName = 'Asabeneh' +console.log(firstName.length) // 8 +``` + +2. *Accessing characters in a string*: We can access each character in a string using its index. In programming, counting starts from 0. The first index of the string is zero, and the last index is the length of the string minus one. + + ![Accessing sting by index](../images/string_indexes.png) + +Let us access different characters in 'JavaScript' string. + +```js +let string = 'JavaScript' +let firstLetter = string[0] + +console.log(firstLetter) // J + +let secondLetter = string[1] // a +let thirdLetter = string[2] +let lastLetter = string[9] + +console.log(lastLetter) // t + +let lastIndex = string.length - 1 + +console.log(lastIndex) // 9 +console.log(string[lastIndex]) // t +``` + +3. *toUpperCase()*: this method changes the string to uppercase letters. + +```js +let string = 'JavaScript' + +console.log(string.toUpperCase()) // JAVASCRIPT + +let firstName = 'Asabeneh' + +console.log(firstName.toUpperCase()) // ASABENEH + +let country = 'Finland' + +console.log(country.toUpperCase()) // FINLAND +``` + +4. *toLowerCase()*: this method changes the string to lowercase letters. + +```js +let string = 'JavasCript' + +console.log(string.toLowerCase()) // javascript + +let firstName = 'Asabeneh' + +console.log(firstName.toLowerCase()) // asabeneh + +let country = 'Finland' + +console.log(country.toLowerCase()) // finland +``` + +5. *substr()*: It takes two arguments, the starting index and number of characters to slice. + +```js +let string = 'JavaScript' +console.log(string.substr(4,6)) // Script + +let country = 'Finland' +console.log(country.substr(3, 4)) // land +``` + +6. *substring()*: It takes two arguments, the starting index and the stopping index but it doesn't include the character at the stopping index. + +```js +let string = 'JavaScript' + +console.log(string.substring(0,4)) // Java +console.log(string.substring(4,10)) // Script +console.log(string.substring(4)) // Script + +let country = 'Finland' + +console.log(country.substring(0, 3)) // Fin +console.log(country.substring(3, 7)) // land +console.log(country.substring(3)) // land +``` + +7. *split()*: The split method splits a string at a specified place. + +```js +let string = '30 Days Of JavaScript' + +console.log(string.split()) // Changes to an array -> ["30 Days Of JavaScript"] +console.log(string.split(' ')) // Split to an array at space -> ["30", "Days", "Of", "JavaScript"] + +let firstName = 'Asabeneh' + +console.log(firstName.split()) // Change to an array -> ["Asabeneh"] +console.log(firstName.split('')) // Split to an array at each letter -> ["A", "s", "a", "b", "e", "n", "e", "h"] + +let countries = 'Finland, Sweden, Norway, Denmark, and Iceland' + +console.log(countries.split(',')) // split to any array at comma -> ["Finland", " Sweden", " Norway", " Denmark", " and Iceland"] +console.log(countries.split(', ')) // ["Finland", "Sweden", "Norway", "Denmark", "and Iceland"] +``` + +8. *trim()*: Removes trailing space in the beginning or the end of a string. + +```js +let string = ' 30 Days Of JavaScript ' + +console.log(string) +console.log(string.trim(' ')) + +let firstName = ' Asabeneh ' + +console.log(firstName) +console.log(firstName.trim()) // still removes spaces at the beginning and the end of the string +``` + +```sh + 30 Days Of JavasCript +30 Days Of JavasCript + Asabeneh +Asabeneh +``` + +9. *includes()*: It takes a substring argument and it checks if substring argument exists in the string. *includes()* returns a boolean. If a substring exist in a string, it returns true, otherwise it returns false. + +```js +let string = '30 Days Of JavaScript' + +console.log(string.includes('Days')) // true +console.log(string.includes('days')) // false - it is case sensitive! +console.log(string.includes('Script')) // true +console.log(string.includes('script')) // false +console.log(string.includes('java')) // false +console.log(string.includes('Java')) // true + +let country = 'Finland' + +console.log(country.includes('fin')) // false +console.log(country.includes('Fin')) // true +console.log(country.includes('land')) // true +console.log(country.includes('Land')) // false +``` + +10. *replace()*: takes as a parameter the old substring and a new substring. + +```js +string.replace(oldsubstring, newsubstring) +``` + +```js +let string = '30 Days Of JavaScript' +console.log(string.replace('JavaScript', 'Python')) // 30 Days Of Python + +let country = 'Finland' +console.log(country.replace('Fin', 'Noman')) // Nomanland +``` + +11. *charAt()*: Takes index and it returns the value at that index + +```js +string.charAt(index) +``` + +```js +let string = '30 Days Of JavaScript' +console.log(string.charAt(0)) // 3 + +let lastIndex = string.length - 1 +console.log(string.charAt(lastIndex)) // t +``` + +12. *charCodeAt()*: Takes index and it returns char code (ASCII number) of the value at that index + +```js +string.charCodeAt(index) +``` + +```js +let string = '30 Days Of JavaScript' +console.log(string.charCodeAt(3)) // D ASCII number is 68 + +let lastIndex = string.length - 1 +console.log(string.charCodeAt(lastIndex)) // t ASCII is 116 + +``` + +13. *indexOf()*: Takes a substring and if the substring exists in a string it returns the first position of the substring if does not exist it returns -1 + +```js +string.indexOf(substring) +``` + +```js +let string = '30 Days Of JavaScript' + +console.log(string.indexOf('D')) // 3 +console.log(string.indexOf('Days')) // 3 +console.log(string.indexOf('days')) // -1 +console.log(string.indexOf('a')) // 4 +console.log(string.indexOf('JavaScript')) // 11 +console.log(string.indexOf('Script')) //15 +console.log(string.indexOf('script')) // -1 +``` + +14. *lastIndexOf()*: Takes a substring and if the substring exists in a string it returns the last position of the substring if it does not exist it returns -1 + + +```js +//syntax +string.lastIndexOf(substring) +``` + +```js +let string = 'I love JavaScript. If you do not love JavaScript what else can you love.' + +console.log(string.lastIndexOf('love')) // 67 +console.log(string.lastIndexOf('you')) // 63 +console.log(string.lastIndexOf('JavaScript')) // 38 +``` + +15. *concat()*: it takes many substrings and joins them. + +```js +string.concat(substring, substring, substring) +``` + +```js +let string = '30' +console.log(string.concat("Days", "Of", "JavaScript")) // 30DaysOfJavaScript + +let country = 'Fin' +console.log(country.concat("land")) // Finland +``` + +16. *startsWith*: it takes a substring as an argument and it checks if the string starts with that specified substring. It returns a boolean(true or false). + +```js +//syntax +string.startsWith(substring) +``` + +```js +let string = 'Love is the best to in this world' + +console.log(string.startsWith('Love')) // true +console.log(string.startsWith('love')) // false +console.log(string.startsWith('world')) // false + +let country = 'Finland' + +console.log(country.startsWith('Fin')) // true +console.log(country.startsWith('fin')) // false +console.log(country.startsWith('land')) // false +``` + +17. *endsWith*: it takes a substring as an argument and it checks if the string ends with that specified substring. It returns a boolean(true or false). + +```js +string.endsWith(substring) +``` + +```js +let string = 'Love is the most powerful feeling in the world' + +console.log(string.endsWith('world')) // true +console.log(string.endsWith('love')) // false +console.log(string.endsWith('in the world')) // true + +let country = 'Finland' + +console.log(country.endsWith('land')) // true +console.log(country.endsWith('fin')) // false +console.log(country.endsWith('Fin')) // false +``` + +18. *search*: it takes a substring as an argument and it returns the index of the first match. The search value can be a string or a regular expression pattern. + +```js +string.search(substring) +``` + +```js +let string = 'I love JavaScript. If you do not love JavaScript what else can you love.' +console.log(string.search('love')) // 2 +console.log(string.search(/javascript/gi)) // 7 +``` + +19. *match*: it takes a substring or regular expression pattern as an argument and it returns an array if there is match if not it returns null. Let us see how a regular expression pattern looks like. It starts with / sign and ends with / sign. + +```js +let string = 'love' +let patternOne = /love/ // with out any flag +let patternTwo = /love/gi // g-means to search in the whole text, i - case insensitive +``` + +Match syntax + +```js +// syntax +string.match(substring) +``` + +```js +let string = 'I love JavaScript. If you do not love JavaScript what else can you love.' +console.log(string.match('love')) +``` + +```sh +["love", index: 2, input: "I love JavaScript. If you do not love JavaScript what else can you love.", groups: undefined] +``` + +```js +let pattern = /love/gi +console.log(string.match(pattern)) // ["love", "love", "love"] +``` + +Let us extract numbers from text using a regular expression. This is not the regular expression section, do not panic! We will cover regular expressions later on. + +```js +let txt = 'In 2019, I ran 30 Days of Python. Now, in 2020 I am super exited to start this challenge' +let regEx = /\d+/ + +// d with escape character means d not a normal d instead acts a digit +// + means one or more digit numbers, +// if there is g after that it means global, search everywhere. + +console.log(txt.match(regEx)) // ["2", "0", "1", "9", "3", "0", "2", "0", "2", "0"] +console.log(txt.match(/\d+/g)) // ["2019", "30", "2020"] +``` + +20. *repeat()*: it takes a number as argument and it returns the repeated version of the string. + +```js +string.repeat(n) +``` + +```js +let string = 'love' +console.log(string.repeat(10)) // lovelovelovelovelovelovelovelovelovelove +``` + +## Checking Data Types and Casting + +### Checking Data Types + +To check the data type of a certain variable we use the _typeof_ method. + +**Example:** + +```js +// Different javascript data types +// Let's declare different data types + +let firstName = 'Asabeneh' // string +let lastName = 'Yetayeh' // string +let country = 'Finland' // string +let city = 'Helsinki' // string +let age = 250 // number, it is not my real age, do not worry about it +let job // undefined, because a value was not assigned + +console.log(typeof 'Asabeneh') // string +console.log(typeof firstName) // string +console.log(typeof 10) // number +console.log(typeof 3.14) // number +console.log(typeof true) // boolean +console.log(typeof false) // boolean +console.log(typeof NaN) // number +console.log(typeof job) // undefined +console.log(typeof undefined) // undefined +console.log(typeof null) // object +``` + +### Changing Data Type (Casting) + +- Casting: Converting one data type to another data type. We use _parseInt()_, _parseFloat()_, _Number()_, _+ sign_, _str()_ + When we do arithmetic operations string numbers should be first converted to integer or float if not it returns an error. + +#### String to Int + +We can convert string number to a number. Any number inside a quote is a string number. An example of a string number: '10', '5', etc. +We can convert string to number using the following methods: + +- parseInt() +- Number() +- Plus sign(+) + +```js +let num = '10' +let numInt = parseInt(num) +console.log(numInt) // 10 +``` + +```js +let num = '10' +let numInt = Number(num) + +console.log(numInt) // 10 +``` + +```js +let num = '10' +let numInt = +num + +console.log(numInt) // 10 +``` + +#### String to Float + +We can convert string float number to a float number. Any float number inside a quote is a string float number. An example of a string float number: '9.81', '3.14', '1.44', etc. +We can convert string float to number using the following methods: + +- parseFloat() +- Number() +- Plus sign(+) + +```js +let num = '9.81' +let numFloat = parseFloat(num) + +console.log(numFloat) // 9.81 +``` + +```js +let num = '9.81' +let numFloat = Number(num) + +console.log(numFloat) // 9.81 +``` + +```js +let num = '9.81' +let numFloat = +num + +console.log(numInt) // 9.81 +``` + +#### Float to Int + +We can convert float numbers to integers. +We use the following method to convert float to int: + +- parseInt() + +```js +let num = 9.81 +let numInt = parseInt(num) + +console.log(numInt) // 9 +``` + +🌕 You are awesome. You have just completed day 2 challenges and you are two steps ahead on your way to greatness. Now do some exercises for your brain and for your muscle. + +## 💻 Day 2: Exercises + +### Exercise: Level 1 + +1. Declare a variable named challenge and assign it to an initial value **'30 Days Of JavaScript'**. +2. Print the string on the browser console using __console.log()__ +3. Print the __length__ of the string on the browser console using _console.log()_ +4. Change all the string characters to capital letters using __toUpperCase()__ method +5. Change all the string characters to lowercase letters using __toLowerCase()__ method +6. Cut (slice) out the first word of the string using __substr()__ or __substring()__ method +7. Slice out the phrase *Days Of JavaScript* from *30 Days Of JavaScript*. +8. Check if the string contains a word __Script__ using __includes()__ method +9. Split the __string__ into an __array__ using __split()__ method +10. Split the string 30 Days Of JavaScript at the space using __split()__ method +11. 'Facebook, Google, Microsoft, Apple, IBM, Oracle, Amazon' __split__ the string at the comma and change it to an array. +12. Change 30 Days Of JavaScript to 30 Days Of Python using __replace()__ method. +13. What is character at index 15 in '30 Days Of JavaScript' string? Use __charAt()__ method. +14. What is the character code of J in '30 Days Of JavaScript' string using __charCodeAt()__ +15. Use __indexOf__ to determine the position of the first occurrence of __a__ in 30 Days Of JavaScript +16. Use __lastIndexOf__ to determine the position of the last occurrence of __a__ in 30 Days Of JavaScript. +17. Use __indexOf__ to find the position of the first occurrence of the word __because__ in the following sentence:__'You cannot end a sentence with because because because is a conjunction'__ +18. Use __lastIndexOf__ to find the position of the last occurrence of the word __because__ in the following sentence:__'You cannot end a sentence with because because because is a conjunction'__ +19. Use __search__ to find the position of the first occurrence of the word __because__ in the following sentence:__'You cannot end a sentence with because because because is a conjunction'__ +20. Use __trim()__ to remove any trailing whitespace at the beginning and the end of a string.E.g ' 30 Days Of JavaScript '. +21. Use __startsWith()__ method with the string *30 Days Of JavaScript* and make the result true +22. Use __endsWith()__ method with the string *30 Days Of JavaScript* and make the result true +23. Use __match()__ method to find all the __a__’s in 30 Days Of JavaScript +24. Use __concat()__ and merge '30 Days of' and 'JavaScript' to a single string, '30 Days Of JavaScript' +25. Use __repeat()__ method to print 30 Days Of JavaScript 2 times + +### Exercise: Level 2 + +1. Using console.log() print out the following statement: + + ```sh + The quote 'There is no exercise better for the heart than reaching down and lifting people up.' by John Holmes teaches us to help one another. + ``` + +2. Using console.log() print out the following quote by Mother Teresa: + + ```sh + "Love is not patronizing and charity isn't about pity, it is about love. Charity and love are the same -- with charity you give love, so don't just give money but reach out your hand instead." + ``` + +3. Check if typeof '10' is exactly equal to 10. If not make it exactly equal. +4. Check if parseFloat('9.8') is equal to 10 if not make it exactly equal with 10. +5. Check if 'on' is found in both python and jargon +6. _I hope this course is not full of jargon_. Check if _jargon_ is in the sentence. +7. Generate a random number between 0 and 100 inclusively. +8. Generate a random number between 50 and 100 inclusively. +9. Generate a random number between 0 and 255 inclusively. +10. Access the 'JavaScript' string characters using a random number. +11. Use console.log() and escape characters to print the following pattern. + + ```js + 1 1 1 1 1 + 2 1 2 4 8 + 3 1 3 9 27 + 4 1 4 16 64 + 5 1 5 25 125 + ``` + +12. Use __substr__ to slice out the phrase __because because because__ from the following sentence:__'You cannot end a sentence with because because because is a conjunction'__ + +### Exercises: Level 3 + +1. 'Love is the best thing in this world. Some found their love and some are still looking for their love.' Count the number of word __love__ in this sentence. +2. Use __match()__ to count the number of all __because__ in the following sentence:__'You cannot end a sentence with because because because is a conjunction'__ +3. Clean the following text and find the most frequent word (hint, use replace and regular expressions). + + ```js + const sentence = '%I $am@% a %tea@cher%, &and& I lo%#ve %te@a@ching%;. The@re $is no@th@ing; &as& mo@re rewarding as educa@ting &and& @emp%o@weri@ng peo@ple. ;I found tea@ching m%o@re interesting tha@n any ot#her %jo@bs. %Do@es thi%s mo@tiv#ate yo@u to be a tea@cher!? %Th#is 30#Days&OfJavaScript &is al@so $the $resu@lt of &love& of tea&ching' + ``` + +4. Calculate the total annual income of the person by extracting the numbers from the following text. 'He earns 5000 euro from salary per month, 10000 euro annual bonus, 15000 euro online courses per month.' + +🎉 CONGRATULATIONS ! 🎉 + diff --git a/_posts/2022-09-18-angular-14-contentful-tutorial.md b/_posts/2022-09-18-angular-14-contentful-tutorial.md new file mode 100644 index 00000000000..d705868c26d --- /dev/null +++ b/_posts/2022-09-18-angular-14-contentful-tutorial.md @@ -0,0 +1,450 @@ +--- +layout: post +title: "Angular 14 with Contentful tutorial" +categories: angular +--- + +This post will show you how to use Contentful in conjunction with Angular 14 to create a full-stack application. + +Contentful is a cloud-based content management platform for organizing and managing contents which can then be accessed through a variety of platforms, such as a website and a mobile app. + +When it comes to building client-side apps or providing content creation and management services, both Angular 14 and Contentful are popular choices. + +One of the main advantages of [Angular 14](https://angular.io/) is that it provides a uniform way to write and share code, as well as the ability to create apps that can be used on the web, mobile web, native mobile, and the desktop. + +Taking advantage of the current Web Platform's maximum performance as well as new approaches and APIs such as [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) and [Angular Universal](https://angular.io/guide/universal) for server-side rendering, Angular 14 offers a number of benefits in terms of both performance and productivity. + +It also includes high-quality developer tools that simplify the process of developing features in an effective ways and comes with its own [template syntax](https://angular.io/guide/template-syntax) that extends HTML, and can be further expanded with custom components. Additionally, popular integrated development environment (IDE) and text editor provides Angular 14-specific feedback and help for its users. You won't have to worry about getting stuck in the ins and outs of the coding process in order to create powerfull apps; instead, you can concentrate on implementing your application idea. + +Angular 14 is the technology that powers the frontend of Google applications that are utilized by millions of people all around the world because to its scalable architecture and its productivity-enhancing capabilities. + +Contentful is a headless content management system that offers project-specific foundation for the purpose of managing the contents of a website. + +It is headless, or independent of the front-end, enabling you to use the backend and content infrastructure with any framework, including Angular 14, React, Vue, etc. + +It allows you to add and update information that will be displayed on the frontend of your website or mobile application. It also saves you the time and effort of developing your own backend – which requires knowing a backend language/platform such as Python or Node.js and database administration – and offers different tools that assist developers interface the frontend – a website or application – with the backend. + +## Creating contents + +Let’s get started with our first section in this tutorial – in the Contentful UI, we’ll create a [space](https://www.contentful.com/help/spaces-and-organizations/) with a content model and add content that we’ll be later retrieving from the frontend. As a demo, we’ll be developing a job listings website for developers. + +We’ll not be showing a detailed step-by-step guide for this section but you can refer to [this page](https://www.contentful.com/help/contentful-101/) to learn how to do the process. + +We should begin by creating our custom structure for our content. The structure functions similarly to a schema, allowing editors to create repeating pieces of content. In a nutshell, here is what you need to do: + +- Sign up for a free Contentful account +- Create a content type/model called `JobListing` +- Populate the space with content based on the `JobListing` content type + +Ou Job model has the following fields and types: + +- Role: Short Text +- Description: Long Text +- HowToApply: Rich Text +- Organization: Short Text +- Date: Date & time +- Skills: Short Text & List + +After you’ve created and published your job listings. We will now walk you through the process of fetching them through the API and display them with Angular 14. + +> Note: Before you can communicate with Contentful, you'll need an [API key, consisting of the Space ID, the Access Token, and the Entry ID](https://www.contentful.com/developers/docs/references/authentication/) that you can get from your Contentful space. + +## Create Angular 14 Project + +Now that we’ve created our content type and populated some data, let’s proceed to create the Angular 14 project that will fetch and display the job listings from Contentful. + +In this section, we’ll see how to: + +- Create an Angular 14 project and modify the page to display the retrieved content in an appropriate way. +- Create an Angular 14 service that can fetch the data. +- Include the routes required to navigate the app. +- Connect the service to the page and display the fetched content. + +Before you start, you will need to have some prerequisites regarding your development environment. + +Since Angular 14 requires the use of [Angular 14 CLI](https://efficientcoder.net/install-angular-cli/) to scaffold the initial projects’ files and any necessary artifacts during the development of the project, you need to have recent versions of Node.js and npm installed on your development machine. + +There are various ways that you use to install Node.js in your machine: + +- Obtain an installer that is compatible with your operating system from the [official website](https://nodejs.org/). +- Make use of the official package manager of your system. +- Use a Node version manager such as [NVM](https://github.com/nvm-sh/nvm) which will allow you to manage [multiple versions of Node](https://www.shabang.dev/multiple-versions-node-nvm/) on your development machine. We recommend using NVM. + +If you have Node installed on your machine; simply go to a command-line interface, Command Prompt or PowerShell (Windows) or bash terminal (Linux and macOS) and let’s get started by installing Angular 14 CLI. + +Install the most recent version of the Angular 14 CLI by running the following command: + +```bash +npm install -g @angular/cli +``` +> Note: You may need to add sudo (for admin access) in macOS and Linux or use a command prompt with admin access in Windows to install the Angular 14 CLI globally on your machine. + +After the installation, you’ll be able to use the `ng` tool from your terminal. + +At the time of writing this article, Angular CLI **v14** is installed. + +> If you want to use the same version installed in this tutorial at any time later, you simpy need to specify the version when installing the CLI .i.e `npm install -g @angular/cli@13.3.7`. + +Let’s create our Angular 14 project. In the command-line interface run the following command: + +```bash +ng new angularcontentfuldemo --routing --style=css +``` + +After pressing **Enter** in your keyboard, Angular 14 CLI will create your initial project’s files and install the packages and log the process on the terminal which should have the following printed after project’s creation: + +```bash +✔ Packages installed successfully. + Successfully initialized git. +``` + +Next, navigate inside the root folder of your project: + +```bash +cd angularcontentfuldemo +``` + +You can then serve your Angular 14 application using the `ng serve` command as follows: + +```bash +ng serve +``` + +Your app will be served from `http://localhost:4200/`. + +Leave your current command-line interface open for running the development server and open a new one for running the commands that will be following. + +Before proceeding, let's first add our Contentful [Space ID and Access Token](https://www.contentful.com/developers/docs/references/authentication/) to the environment variables of our application. + +> Note: You can create an access token using the [Contentful web app](https://be.contentful.com/login) or the [Content Management API](https://www.contentful.com/developers/docs/references/content-management-api/#/reference/api-keys/create-an-api-key). + +Open the `src/environments.ts` file and update it as follows: + +```ts +export const environment = { + production: false, + contentful: { + spaceId: 'YOUR_SPACE_ID', + accessToken: 'YOUR_ACCESS_TOKEN' + } +}; +``` + +Make sure to replace `YOUR_SPACE_ID` and `YOUR_ACCESS_TOKEN` with your actual credentials. + +Let's continue by installing some necessary dependencies such as `contentful`, `bootstrap`, [rich-text-types](https://www.npmjs.com/package/@contentful/rich-text-types) and [rich-text-html-renderer](https://www.npmjs.com/package/@contentful/rich-text-html-renderer) using the following commands after navigating to your project's folder: + +```bash +npm install contentful bootstrap +npm install @contentful/rich-text-types @contentful/rich-text-html-renderer +``` + +We'll use contentful to connect with Contentful APIs and bootstrap for styling the Angular 14 UI. + +Next, let's add Bootstrap to our project. There are various ways to [add Bootstrap to Angular 14](https://www.techiediaries.com/add-angular-bootstrap/), in our case, we'll include bootstrap files via the `angular.json` file so go ahead and open the configuration file that exists at the root of the project and add the following line: + +```json +"styles": [ + "./node_modules/bootstrap/dist/css/bootstrap.css", + "src/styles.css" + ] +``` + +Open the `src/app/app.component.html` file and update it as follows: + +```html + +
+ +
+``` +We simply removed the boilerplate markup except the [router outlet](https://angular.io/api/router/RouterOutlet) and added a Bootstrap header bar. + +### Create the service for communicating with Contentful + +Let's now create the service that will encapsulate the code for communicating with Contentful. Go back to your command-line interface and run the following command to generate the service: + +```bash +ng g s content +``` + +Create a `content-types.ts` file in the `src/app/` folder and add the following code: + +```ts +import * as CFRichTextTypes from "@contentful/rich-text-types"; +import * as Contentful from "contentful"; + +export interface TypeJobListingFields { + role?: Contentful.EntryFields.Symbol; + description?: Contentful.EntryFields.Text; + howToApply?: CFRichTextTypes.Block | CFRichTextTypes.Inline; + organization?: Contentful.EntryFields.Symbol; + date?: Contentful.EntryFields.Date; + skills?: Contentful.EntryFields.Symbol[]; +} + +export type TypeJobListing = Contentful.Entry; +``` + +This will be used to type the entries corresponding to our content model. We can either write the types manually or use automated tools for a more scalable approach: + +- [cf-content-types-generator](https://github.com/contentful-userland/cf-content-types-generator) +- [contentful-typescript-codegen](https://github.com/intercom/contentful-typescript-codegen) +- [contentful-ts-type-generator](https://github.com/arimkevi/contentful-ts-type-generator) +- [contentful-ts-generator](https://github.com/watermarkchurch/contentful-ts-generator) +- [TS Content Types Generator App](https://github.com/marcolink/cf-content-types-generator-app) + +Open the `src/app/content.service.ts` file and start by adding the following imports: + +```ts +import { Injectable } from '@angular/core'; +import { createClient } from 'contentful'; +import { from } from 'rxjs'; +import { environment } from '../environments/environment'; +import { TypeJobListingFields } from './content-types'; +``` + +Next, add the client property and call the `createClient()` function to create a client as follows: + +```ts +@Injectable({ + providedIn: 'root' +}) +export class ContentService { + + client = createClient({ + space: environment.contentful.spaceId, + accessToken: environment.contentful.accessToken + }); + constructor() {} +} +``` + +Then, add the following method to fetch content from Contentful: + +```ts +getJobListings(query?: object){ + return from( + this.client.getEntries(Object.assign({ + content_type: 'jobListing' + }, query)) + ); +} +``` + +We call the [getEntries](https://contentful.github.io/contentful.js/contentful/latest/ContentfulClientAPI.html#.getEntries) method of `contentful` to retreive the entries corresponding to our model content that we pass as the first argument of the method. We use [Object.assign](https://30daysofjavascript.com/object-assign/) to create an object containing the content type and any other queries that we pass to Contentful. + +The method also accepts a [generic type](https://www.typescriptlang.org/docs/handbook/2/generics.html) that defines the type of the content that will be returned which is in our case `TypeJobListingFields`. + +> _Note If you didn't save your content type id somewhere, you can get it as follows: contentful->content model -> click your content model name -> right sidebar look for your content type id._ + +Also, add the following method to fetch a job listing by ID: + +```ts +getJobListingById(jobListingId: string, query?: any){ + return from( + this.client.getEntry(jobListingId, query) + ); +} +``` + +### Add routing and display the content + +After implementing the service, we need to create a component to display the job listings fetched from the backend; and add routing. +Go back to your command-line interface and run the following commands: + +```bash +ng g c jobListings +ng g c jobListing +``` + +This will generate the components' files and add the components to the root application module. + +Next, open the `src/app/app-routing.module.ts` file and start by importing the components as follows: + +```ts +import { JobListingsComponent } from './job-listings/job-listings.component'; +import { JobListingComponent } from './job-listing/job-listing.component'; +``` + +Then, add the following routes: + +```ts +const routes: Routes = [ + { path: '', pathMatch: 'full', redirectTo: 'listings' }, + { path: 'listings', component: JobListingsComponent }, + { path: 'listing/:id', component: JobListingComponent } +]; +``` + Here we define three routes -- the first route simply redirects the user to the second route which links to the JobListingsComponent. + +You can read more about routing in Angular 14 from this [article](https://www.webtutpro.com/angular-12-routing-by-example-f0cfbdc7b0a8). + +Open the `src/app/job-listings/job-listings.component.ts` file and import the service and the other symbols as follows: + +```ts +import { Component, OnInit } from '@angular/core'; +import { ContentService } from '../content.service'; +import { TypeJobListingFields } from '../content-types'; +import { Entry } from 'contentful'; +``` +Next, inside the component's class define the following array to hold the fetched job listings: + +```ts +jobListings: Entry[] | undefined; +``` + +Next, inject the service via the component's class as follows: + +```ts +constructor(public contentService: ContentService) { } +``` + +[Injecting the service](https://angular.io/guide/dependency-injection#injecting-services) makes it available to the component. + +Then, define the following method for fetching the content: + +```ts +getJobListings(){ + this.contentService.getJobListings() + .subscribe({ + next: (entryCollection) => { + this.jobListings = entryCollection.items; + console.log(this.jobListings); + } + }); +} +``` + +Then, call the previous method inside the `ngOnInit()` life-cycle method of the component: + +```ts +ngOnInit(): void { + this.getJobListings(); +} +``` + +Life-cycle methods are methods that hook into key events of the component. You can find more information about them from this [article](https://angular.io/guide/lifecycle-hooks). + +In the same way open the `src/app/job-listing/job-listing.component.ts` file and add the following imports: + +```ts +import { ActivatedRoute, ParamMap } from '@angular/router'; +import { switchMap } from 'rxjs/operators'; +import { ContentService } from '../content.service'; +import { TypeJobListingFields } from '../content-types'; +``` + +Next, define the following property: + +```ts +jobListing: TypeJobListingFields | null = null; +``` + +Next, inject the following services: + +```ts +constructor(public contentService: ContentService, public route: ActivatedRoute) { } +``` + +The [ActivatedRoute](https://angular.io/api/router/ActivatedRoute) class provides information about active route in the outlet. + +Next, update the `ngOnInit()` hook of the component as follows: + +```ts +ngOnInit(): void { + this.route.paramMap.pipe( + switchMap((params: ParamMap) => + this.contentService.getJobListingById(params.get('id') as string) + )).subscribe({ + next: (entry) => { + this.jobListing = entry.fields; + }}); +} +``` + +When the component is initialized, we get the job's listing ID from the route using [ParamMap with switchMap](https://webtips101.com/angular-routing-switchmap/). Since our service method returns an observable, we flatten the observable with the `switchMap` operator and we subscribe to the resulting observable to get the fetched entry and assign it to the `jobListing` property. + +The [`switchMap` operator](https://rxjs.dev/api/operators/switchMap) also cancels previous ongoing requests. If the user navigates to the route with a different `id` while the ContentService is still fetching the content, `switchMap` removes the previous request and returns the job listing for the current `id`. + +After that, we need to render the content in the component's template. Open the `src/app/job-listings/job-listings.component.html` file and update it as follows: + +```html +
+
+
+ {{ jobListing.role }} +
+
+ {{ jobListing.organization }} - {{ jobListing.date | date }} +
+
+
+
+ Description +
+

+ {{ jobListing.description }} +

+
+
+ How to apply? +
+
+
+
+

+ Skills: {{ jobListing.skills }} +

+
+
+``` + +You should notice that under the **How to apply** section, we are displaying the content of the `howToApply` field but we are getting `[object Object]` displayed. That's because this a Rich Text field which is a JSON format for handling complex content structures in a strongly typed manner in Contentful. +Contentful provides many tools to help you work with the [Rich Text](https://www.contentful.com/developers/docs/concepts/rich-text/) feature and we've previously installed the `@contentful/rich-text-html-renderer` package which makes it easy to display rich text fields via a `documentToHtmlString()` function. + +Since, we are using Angular 14, we need to use the function with a [custom pipe](https://angular.io/guide/pipes) that we can apply to the field in the component's template to display it correctly. +Go back to your command-line interface and run the following command to generate a pipe: + +```bash +ng g pipe toHtml +``` + +Open the `src/app/to-html.pipe.ts` file and update it as follows: + +```ts +import { Pipe, PipeTransform } from '@angular/core'; +import { documentToHtmlString } from '@contentful/rich-text-html-renderer'; +import { Document } from '@contentful/rich-text-types'; + +@Pipe({ + name: 'toHtml' +}) +export class ToHtmlPipe implements PipeTransform { + + transform(value: unknown, ...args: unknown[]): unknown { + return documentToHtmlString(value as Document); + } +} +``` + +You can then go back to the file and display the rich text field using the following code: + +```html +
+``` +Since the result of applying our custom `toHtml` pipe to the `howToApply` field is HTML content, we need to [bind to the innerHtml](https://www.techiediaries.com/angular-innerhtml-binding/) attribute to render it inside the `
`. + +## Conclusion + +We learned how to use Contentful as our Angular 14 application's backend for managing content. + +Software like Wordpress sparked the rise of content management systems. Even though Wordpress is the most popular content management system in the world, Contentful allows you to accomplish more and separate your front-end or view layer from managing content. For more information, you can read [Is Contentful a WordPress alternative?](https://www.contentful.com/blog/2020/03/26/contentful-wordpress-alternative/) or [The Problems with Headless WordPress](https://www.webtutpro.com/the-problems-with-headless-wordpress-196630f5f8f6). + +You'll save time and money because you simply need to write and update content once for all platforms that are integrated with your CMS. +You can create an account for free and start using Contentful to quickly and efficiently manage the contents for your Angular application without the need to build a custom backend from scratch. diff --git a/index.html b/index.html index bdcbd8bf53d..c3e965bf1ee 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,367 @@ # Feel free to add content and custom Front Matter to this file. # To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults -layout: home -title: Home +layout: post +title: "JavaScript in 30 days" banner: "/assets/images/banners/home.jpeg" --- + +This website aims to be the definitive resource and reference for studying modern web development using latest web technologies and methods. + +> Note: Read the relevant articles and tutorials for each topic, then complete the challenges. + +If you are an absolute beginner in web development, please begin by gaining a basic grasp of the following topics: + + +- What is Http and Https +- How web browsers work +- DNS or Domain Name Service +- Hosting + + +You simply need a fundamental understanding of the preceding subjects to become a web developer; in-depth knowledge is unnecessary. + +Although we have some tutorials for the three pillars of the web i.e HTML, CSS and JavaScript, we recommend that you are already familiar with these three prerequisites. You don't need to master every detail of JavaScript, nor HTML or CSS. + +> Note: HTML, CSS and JavaScript are three official languages of the web but recently the web got a fourth official language that is called WebAssembly. + + +What do you need to learn about HTML? + + +- Commonly used tags +- The anatomy of an HTML document +- The DOM +- Semantic HTML +- SEO basics +- Virtual DOM and Shadow DOM + + + +What do you need to learn about JavaScript? + + +- The basic syntax such as declaring variables, functions and classes, constructs such as loops and conditional statements, etc. +- DOM manipulation methods +- How to fetch data from remote sources using the fetch API or Ajax (XHR) +- Promises and asynchronous programming +- Observables and reactive programming (advanced) +- MVC design pattern + + +You also need to familiarize yourself with the following concepts: + + +- Modules and components +- Client-side routing +- SPAs +- Server-side rendering + +And formats such as: + +- JSON format + +### Common questions asked by developers + + +> What is JS? +> What is HTML? +> What is CSS? +> What is WebAssembly? + + +### Resources + + +These are some of the best free online resources to help you learn these HTML, CSS, and JavaScript. + + +Traditional web development involves frontend development and backend development with different technologies such as JavaScript, HTML and PHP. If you are a veteran web developer, you'll mostly be familiar with the LAMP stack. + + +> Note: A LAMP Stack is a mix of open-source software for creating websites and web applications. LAMP stands for Linux, Apache HTTP Server, MySQL relational database management system, and PHP programming language. + +However, nowadays, contemporary tools and technology exist to develop web apps. This is the outcome of a single tool that allows developers to execute JavaScript on the server in addition to the initial platform, the browser. This software is known as Node.js, although it may also be referred to as node. + +> Also check out deno. + +The majority of web applications contain similar functionality, and many developers are keen to make their implementations available to others as open source libraries and modules. + + +These implementations are shared through centralized services like GitHub and the NPM registry. + + +You may download and install packages from the npm registry directly into your Node.js project using package managers such as npm and yarn. + + +Node is not just utilized as a server technology, but it is also deployed on development machines to offer the runtime for command-line interface tools aimed to enhance developer productivity. Popular frameworks and technologies, such as Angular, include their own Node-based CLI tool. For example: + + +- Angular CLI +- etc. + + +It's worth noting that you can also use package managers such as npm to install and manage the dependencies of your front-end application. + + + +By incorporating JavaScript onto the server, developers ushered in a new era of web development that involves designing and developing web applications using a single programming language. This eliminates the need for JavaScript developers to learn another language, such as PHP or Python, in order to build the backend of frontend web applications. + + +Another important factor that has contributed to the modernization of web development is that web browsers have evolved into powerful platforms capable of running full-fledged JavaScript apps without relying on the server for processing but only for serving the static files of the application and data. + + +Front-end web developers, backend web developers, and full-stack web developers are the three sorts of web developers. However, with the ability to run JavaScript on the server, frontend developers can develop full-stack web apps more easily than ever before. + + +This is also true owing to cloud services that provide platforms such as PaaS, Firbase, hosted backends such as Appwrite, and headless CMS systems such as WordPress and Contentful. + + +Moreover, when browsers become powerful, new frontend frameworks and libraries are created by giant tech companies such as React by Facebook and Angular by Google. + + +On top of these frameworks, new meta frameworks and practices are developed such as: + +- Next.js +- Remix +- Nest.js: this is actually a server-side framework inspired by Angular but not built on top if it. +- Server side rendering +- Static site rendering +- Lazy loading +- JSX +- Reactive programming +- State management +- REST and GraphQL APIs +- React server components + + +Although Angular is a JavaScript client-side framework, it is actually built and used with TypeScript, a superset of JavaScript created by Microsoft that adds support for strong typing and object oriented concepts to JavaScript. + + +> Note: Web browsers do not interpret TypeScript, thus it must be compiled to JavaScript on the development machine before being sent and executed on the users' machines. However, a new proposal to support TypeScript in browsers was recently introduced. + + + +React also introduced a new syntax called JSX that can be used to write HTML in JavaScript. + +Because modern web browsers can render and run full-fledged web applications, which frequently comprise several source code files and other assets such as CSS, images, and fonts. This resulted in the development of a type of tools known as bundlers, such as webpack. + +For JavaScript applications, Webpack is a static module bundler that takes all of your application's code and makes it usable in a web browser. The JavaScript, node modules, images, and CSS styles used in your app are bundled into reusable pieces of code called modules that may be utilized in your website with ease. With this modular split of responsibilities provided by Webpack, it is much simpler to manage, debug, validate, and test your code. Webpack isolates the code depending on how it is utilized in your app. + +> Also check out Vite + +The majority of the processing in modern frontend or client-side JavaScript frameworks can be done in the browser, but they still need to retrieve data from the server, which houses the database that can properly store user data. As a result, they must connect with the backend via a set of standards known as web programming application interfaces, or APIs. REST and, more recently, GraphQL are the most prevalent. + + +Because Node is a platform for executing JavaScript on the server at the first place, we can use it to build backend apps that provide access to the server's database and other resources to client-side applications via REST or GraphQL APIs. + + +So, assuming you already know JavaScript syntax, which is required for any frontend web developer, you can leverage Node with a variety of frameworks such as Express.js and Happi.js to provide a web API for your frontend app to communicate with the server, allowing you to develop a full-stack web application. + +> Talk about databases +> Hosted and managed vs self hosted databases +> Relational vs Document vs Graph databases + +- CockroachDB is a distributed database with standard SQL for cloud applications +- YugabyteDB + + +- MySQL + +- PostgreSQL + +- MongoDB + +> How about storing data on the client side, is that possible? + +> What is an ORM? + + + + + +What if you don't want to learn additional backend staff and instead want to focus on your frontend skills, but you still need to develop full-stack web applications? This is also achievable thanks to cloud services, either hosted or self-hosted. + +- Firebase by Google +- Appwrite +- Supabase +- Parse + +This sort of services is known as PaaS, which stands for Platform As A Service. + + +The list also inlcude headless CMS systems — Content Management Systems — such as Contentful that you can use to manage contents of any types and integrate that with your frontend application to deliver a complete experience for users. + + +WordPress, the most popular CMS of all times, has recently exposed a REST API for interacting with your site from a frontend application allowing developers to build modern applications that use PHP and Wordpress as the backend without building everything from scratch. + + +In most situations, building web applications entails implementing authentication to allow users to identify themselves before they can access restricted resources, such as regions of your application or data. You may create your own authentication system by employing several strategies, such as: + + +- JWT +- Session and cookies. + + +If you want to build the authentication system yourself, you'll have to use a bunch of different libraries on top of Node.js and frameworks such as Express. However, you can also use other third party services such as Firebase to provide authentication functionality for your application. +📚 +Aside from web APIs, authentication is considered one of the most common web development problems that most developers must solve when developing web applications, so you don't have to worry about that because you don't have to reinvent the wheel, but you can use existing solutions as downloadable modules and libraries available from npm. + + +Other Common web dev problems are CRUD operations and pagination. Pagination can be implemented at server-side or client-side, as finite or infinite scrolling, etc. +offset and cursor pagination +> Client-side pagination is for a small amount of data and is primarily for presentation purposes. Server side pagination handles large amount data, and provides stability and scalability. + +> https://nordicapis.com/everything-you-need-to-know-about-api-pagination/ +> https://itnext.io/the-best-database-pagination-technique-is-530abf2aab51 + +One more common web dev problem is routing... + +- Client-side vs server-side routing +- File-based routing + + +> Talk about caching + +> Talk about state management + +What about WebAssembly? Don you need to worry about that? Actually, not that much as you don't need to master it unless you have to build advanced tools such as compilers for the web. However, knowing about it is a good addition to your web development knowledge. + + +As a web developer, you'll mostly won't need to write WebAssembly directly but through frameworks such as Blazor which is a toolkit built by Microsoft on top of WebAssembly that allows developers to write client-side web applications with C#. So this is only necessary beneficial for you if you are a C# developer and want to use your skills to build web applications without learning JavaScript. + +-- + + +Build desktop and mobile applications with your JavaScript skills. + + +- Ionic +- React Native +- Electron + + +- Git-based workflows +- Monorepos +- Material design, Bootstrap and Tailwind +- Serverless + + + +> Realtime communication + + +# Web development stacks +# Static site generators + + +- Next.js +- Gatsby + + +# Modern Frontend Web Frameworks + + +- Angular +- React +- Vue +- Svelte +- Preact +- Lit +- Alpine +- Solid +- Elm +- Stimulus + +PWAs +Web components +https://stackdiary.com/front-end-frameworks/ + + + + +# Modern browser APIs such as: + + +- Dark mode +- Payment APIs +- Web mentions + + + +# Learn web development with Angular + + +## Angular & Appwrite +## Angular & Firebase +## Angular & Contentful +## Angular & Node/Express.js +## Angular & Bootstrap +## Angular & Tailwind +## Angular & Material Design + + +## Angular & Ionic +## Angular & Electron + + +## Angular basics + + +## Common webdev problems with Angular + + +### Angular & authentication +### Angular & CRUD +### Angular & routing +### Angular & pagination +### Angular & http client +### Angular & REST API +### Angular & GraphQL API +### Angular architecture +### Angular monorepo + + +# Learn web development with React +# Learn web development with Vue +# Learn web development with Svelte + + +>> In essence, a CSS framework comprises several CSS stylesheets ready for use by web developers and designers. The stylesheets are prepped for use for standard web design functions: setting colors, layout, fonts, navbars, etc. Generally, stylesheets are supported and expanded by other scripting technologies like SASS and JavaScript. + + +>> With a CSS framework, the user has a completed CSS stylesheet, and they only have to code the HTML with accurate classes, structure, and IDs to set up a web page. The framework already has classes built-in for common website elements – footer, slider, navigation bar, hamburger menu, column-based layouts, etc. + + +1. Bootstrap +2. Tailwind CSS +3. Foundation +4. Bulma +5. Skeleton + + +Hosting services + +- Netlify +- Railway +- Vercel +- Cloudflare + +Other frameworks: + +- Blazor +- PyScript + +## Next Generation Web Frameworks + +>The next-gen web framework. +> fresh is a next generation web framework, built for speed, reliability, and simplicity. Some stand out features: + +- Just-in-time rendering on the edge. +- Island based client hydration for maximum interactivity. +- Zero runtime overhead: no JS is shipped to the client by default. +- No build step. +- No configuration necessary. +- TypeScript support out of the box. +- File-system routing à la Next.js +