<!DOCTYPE html><html lang="fr" data-beasties-container><head>
<meta charset="utf-8">
<title>Démarrer une Application Web avec Angular</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-2XLY35VMWF"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', 'G-2XLY35VMWF');
</script>
<link rel="manifest" href="manifest.webmanifest">
<meta name="theme-color" content="#1976d2">
<style>.fa-brands,.fa-solid,.fab,.fas{--_fa-family:var(--fa-family,var(--fa-style-family,"Font Awesome 7 Free"));-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:var(--fa-display,inline-block);font-family:var(--_fa-family);font-feature-settings:normal;font-style:normal;font-synthesis:none;font-variant:normal;font-weight:var(--fa-style,900);line-height:1;text-align:center;text-rendering:auto;width:var(--fa-width,1.25em)}.fa-download{--fa:"\f019"}.fa-edit{--fa:"\f044"}.fa-user-plus{--fa:"\f234"}.fa-user-edit{--fa:"\f4ff"}:root{--fa-family-brands:"Font Awesome 7 Brands";--fa-font-brands:normal 400 1em/1 var(--fa-family-brands)}.fa-brands,.fab{--fa-family:var(--fa-family-brands);--fa-style:400}.fa-github{--fa:"\f09b"}.fa-linkedin-in{--fa:"\f0e1"}.fa-youtube{--fa:"\f167"}:root{--fa-font-regular:normal 400 1em/1 var(--fa-family-classic)}:root{--fa-family-classic:"Font Awesome 7 Free";--fa-font-solid:normal 900 1em/1 var(--fa-family-classic);--fa-style-family-classic:var(--fa-family-classic)}.fas{--fa-style:900}.fas{--fa-family:var(--fa-family-classic)}.fa-solid{--fa-style:900}:root{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-primary-text-emphasis:#052c65;--bs-secondary-text-emphasis:#2b2f32;--bs-success-text-emphasis:#0a3622;--bs-info-text-emphasis:#055160;--bs-warning-text-emphasis:#664d03;--bs-danger-text-emphasis:#58151c;--bs-light-text-emphasis:#495057;--bs-dark-text-emphasis:#495057;--bs-primary-bg-subtle:#cfe2ff;--bs-secondary-bg-subtle:#e2e3e5;--bs-success-bg-subtle:#d1e7dd;--bs-info-bg-subtle:#cff4fc;--bs-warning-bg-subtle:#fff3cd;--bs-danger-bg-subtle:#f8d7da;--bs-light-bg-subtle:#fcfcfd;--bs-dark-bg-subtle:#ced4da;--bs-primary-border-subtle:#9ec5fe;--bs-secondary-border-subtle:#c4c8cb;--bs-success-border-subtle:#a3cfbb;--bs-info-border-subtle:#9eeaf9;--bs-warning-border-subtle:#ffe69c;--bs-danger-border-subtle:#f1aeb5;--bs-light-border-subtle:#e9ecef;--bs-dark-border-subtle:#adb5bd;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, .15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-color-rgb:33,37,41;--bs-body-bg:#fff;--bs-body-bg-rgb:255,255,255;--bs-emphasis-color:#000;--bs-emphasis-color-rgb:0,0,0;--bs-secondary-color:rgba(33, 37, 41, .75);--bs-secondary-color-rgb:33,37,41;--bs-secondary-bg:#e9ecef;--bs-secondary-bg-rgb:233,236,239;--bs-tertiary-color:rgba(33, 37, 41, .5);--bs-tertiary-color-rgb:33,37,41;--bs-tertiary-bg:#f8f9fa;--bs-tertiary-bg-rgb:248,249,250;--bs-heading-color:inherit;--bs-link-color:#0d6efd;--bs-link-color-rgb:13,110,253;--bs-link-decoration:underline;--bs-link-hover-color:#0a58ca;--bs-link-hover-color-rgb:10,88,202;--bs-code-color:#d63384;--bs-highlight-color:#212529;--bs-highlight-bg:#fff3cd;--bs-border-width:1px;--bs-border-style:solid;--bs-border-color:#dee2e6;--bs-border-color-translucent:rgba(0, 0, 0, .175);--bs-border-radius:.375rem;--bs-border-radius-sm:.25rem;--bs-border-radius-lg:.5rem;--bs-border-radius-xl:1rem;--bs-border-radius-xxl:2rem;--bs-border-radius-2xl:var(--bs-border-radius-xxl);--bs-border-radius-pill:50rem;--bs-box-shadow:0 .5rem 1rem rgba(0, 0, 0, .15);--bs-box-shadow-sm:0 .125rem .25rem rgba(0, 0, 0, .075);--bs-box-shadow-lg:0 1rem 3rem rgba(0, 0, 0, .175);--bs-box-shadow-inset:inset 0 1px 2px rgba(0, 0, 0, .075);--bs-focus-ring-width:.25rem;--bs-focus-ring-opacity:.25;--bs-focus-ring-color:rgba(13, 110, 253, .25);--bs-form-valid-color:#198754;--bs-form-valid-border-color:#198754;--bs-form-invalid-color:#dc3545;--bs-form-invalid-border-color:#dc3545}*,:after,:before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;border:0;border-top:var(--bs-border-width) solid;opacity:.25}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2;color:var(--bs-heading-color)}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5{font-size:1.25rem}.h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}ul{padding-left:2rem}ul{margin-top:0;margin-bottom:1rem}strong{font-weight:bolder}a{color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,1));text-decoration:underline}a:hover{--bs-link-color-rgb:var(--bs-link-hover-color-rgb)}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,pre{font-family:var(--bs-font-monospace);font-size:1em}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:var(--bs-code-color);word-wrap:break-word}img{vertical-align:middle}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button{text-transform:none}[role=button]{cursor:pointer}[type=button],button{-webkit-appearance:button}[type=button]:not(:disabled),button:not(:disabled){cursor:pointer}.list-unstyled{padding-left:0;list-style:none}.img-fluid{max-width:100%;height:auto}.container,.container-fluid{--bs-gutter-x:1.5rem;--bs-gutter-y:0;width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}@media (min-width:1400px){.container{max-width:1320px}}:root{--bs-breakpoint-xs:0;--bs-breakpoint-sm:576px;--bs-breakpoint-md:768px;--bs-breakpoint-lg:992px;--bs-breakpoint-xl:1200px;--bs-breakpoint-xxl:1400px}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:flex;flex-wrap:wrap;margin-top:calc(-1 * var(--bs-gutter-y));margin-right:calc(-.5 * var(--bs-gutter-x));margin-left:calc(-.5 * var(--bs-gutter-x))}.row>*{flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-top:var(--bs-gutter-y)}.col-4{flex:0 0 auto;width:33.33333333%}.col-6{flex:0 0 auto;width:50%}.col-8{flex:0 0 auto;width:66.66666667%}.col-12{flex:0 0 auto;width:100%}@media (min-width:576px){.col-sm-12{flex:0 0 auto;width:100%}}@media (min-width:768px){.col-md-4{flex:0 0 auto;width:33.33333333%}.col-md-8{flex:0 0 auto;width:66.66666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.33333333%}.col-md-12{flex:0 0 auto;width:100%}}@media (min-width:992px){.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.33333333%}.col-lg-5{flex:0 0 auto;width:41.66666667%}.col-lg-7{flex:0 0 auto;width:58.33333333%}.col-lg-8{flex:0 0 auto;width:66.66666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-12{flex:0 0 auto;width:100%}}@media (min-width:1200px){.col-xl-9{flex:0 0 auto;width:75%}}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-clip:padding-box;border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control:focus{color:var(--bs-body-color);background-color:var(--bs-body-bg);border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.form-control::-webkit-date-and-time-value{min-width:85px;height:1.5em;margin:0}.form-control::-webkit-datetime-edit{display:block;padding:0}.form-control::placeholder{color:var(--bs-secondary-color);opacity:1}.form-control:disabled{background-color:var(--bs-secondary-bg);opacity:1}.form-control::-webkit-file-upload-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:var(--bs-body-color);background-color:var(--bs-tertiary-bg);pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:var(--bs-border-width);border-radius:0;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.form-control::file-selector-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:var(--bs-body-color);background-color:var(--bs-tertiary-bg);pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:var(--bs-border-width);border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::-webkit-file-upload-button{-webkit-transition:none;transition:none}.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button{background-color:var(--bs-secondary-bg)}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:var(--bs-secondary-bg)}.btn{--bs-btn-padding-x:.75rem;--bs-btn-padding-y:.375rem;--bs-btn-font-family: ;--bs-btn-font-size:1rem;--bs-btn-font-weight:400;--bs-btn-line-height:1.5;--bs-btn-color:var(--bs-body-color);--bs-btn-bg:transparent;--bs-btn-border-width:var(--bs-border-width);--bs-btn-border-color:transparent;--bs-btn-border-radius:var(--bs-border-radius);--bs-btn-hover-border-color:transparent;--bs-btn-box-shadow:inset 0 1px 0 rgba(255, 255, 255, .15),0 1px 1px rgba(0, 0, 0, .075);--bs-btn-disabled-opacity:.65;--bs-btn-focus-box-shadow:0 0 0 .25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color)}.btn:focus-visible{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn:first-child:active{color:var(--bs-btn-active-color);background-color:var(--bs-btn-active-bg);border-color:var(--bs-btn-active-border-color)}.btn:first-child:active:focus-visible{box-shadow:var(--bs-btn-focus-box-shadow)}.btn:disabled{color:var(--bs-btn-disabled-color);pointer-events:none;background-color:var(--bs-btn-disabled-bg);border-color:var(--bs-btn-disabled-border-color);opacity:var(--bs-btn-disabled-opacity)}.btn-sm{--bs-btn-padding-y:.25rem;--bs-btn-padding-x:.5rem;--bs-btn-font-size:.875rem;--bs-btn-border-radius:var(--bs-border-radius-sm)}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.nav-link{display:block;padding:var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x);font-size:var(--bs-nav-link-font-size);font-weight:var(--bs-nav-link-font-weight);color:var(--bs-nav-link-color);text-decoration:none;background:0 0;border:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link:focus,.nav-link:hover{color:var(--bs-nav-link-hover-color)}.nav-link:focus-visible{outline:0;box-shadow:0 0 0 .25rem #0d6efd40}.nav-link:disabled{color:var(--bs-nav-link-disabled-color);pointer-events:none;cursor:default}.navbar{--bs-navbar-padding-x:0;--bs-navbar-padding-y:.5rem;--bs-navbar-color:rgba(var(--bs-emphasis-color-rgb), .65);--bs-navbar-hover-color:rgba(var(--bs-emphasis-color-rgb), .8);--bs-navbar-disabled-color:rgba(var(--bs-emphasis-color-rgb), .3);--bs-navbar-active-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-brand-padding-y:.3125rem;--bs-navbar-brand-margin-end:1rem;--bs-navbar-brand-font-size:1.25rem;--bs-navbar-brand-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-brand-hover-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-nav-link-padding-x:.5rem;--bs-navbar-toggler-padding-y:.25rem;--bs-navbar-toggler-padding-x:.75rem;--bs-navbar-toggler-font-size:1.25rem;--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%2833, 37, 41, 0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");--bs-navbar-toggler-border-color:rgba(var(--bs-emphasis-color-rgb), .15);--bs-navbar-toggler-border-radius:var(--bs-border-radius);--bs-navbar-toggler-focus-width:.25rem;--bs-navbar-toggler-transition:box-shadow .15s ease-in-out;position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding:var(--bs-navbar-padding-y) var(--bs-navbar-padding-x)}.navbar>.container{display:flex;flex-wrap:inherit;align-items:center;justify-content:space-between}.navbar-brand{padding-top:var(--bs-navbar-brand-padding-y);padding-bottom:var(--bs-navbar-brand-padding-y);margin-right:var(--bs-navbar-brand-margin-end);font-size:var(--bs-navbar-brand-font-size);color:var(--bs-navbar-brand-color);text-decoration:none;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{color:var(--bs-navbar-brand-hover-color)}.navbar-nav{--bs-nav-link-padding-x:0;--bs-nav-link-padding-y:.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-navbar-color);--bs-nav-link-hover-color:var(--bs-navbar-hover-color);--bs-nav-link-disabled-color:var(--bs-navbar-disabled-color);display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-collapse{flex-grow:1;flex-basis:100%;align-items:center}.navbar-toggler{padding:var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x);font-size:var(--bs-navbar-toggler-font-size);line-height:1;color:var(--bs-navbar-color);background-color:transparent;border:var(--bs-border-width) solid var(--bs-navbar-toggler-border-color);border-radius:var(--bs-navbar-toggler-border-radius);transition:var(--bs-navbar-toggler-transition)}@media (prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 var(--bs-navbar-toggler-focus-width)}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-image:var(--bs-navbar-toggler-icon-bg);background-repeat:no-repeat;background-position:center;background-size:100%}@media (min-width:768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}}.navbar-dark{--bs-navbar-color:rgba(255, 255, 255, .55);--bs-navbar-hover-color:rgba(255, 255, 255, .75);--bs-navbar-disabled-color:rgba(255, 255, 255, .25);--bs-navbar-active-color:#fff;--bs-navbar-brand-color:#fff;--bs-navbar-brand-hover-color:#fff;--bs-navbar-toggler-border-color:rgba(255, 255, 255, .1);--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.card{--bs-card-spacer-y:1rem;--bs-card-spacer-x:1rem;--bs-card-title-spacer-y:.5rem;--bs-card-title-color: ;--bs-card-subtitle-color: ;--bs-card-border-width:var(--bs-border-width);--bs-card-border-color:var(--bs-border-color-translucent);--bs-card-border-radius:var(--bs-border-radius);--bs-card-box-shadow: ;--bs-card-inner-border-radius:calc(var(--bs-border-radius) - (var(--bs-border-width)));--bs-card-cap-padding-y:.5rem;--bs-card-cap-padding-x:1rem;--bs-card-cap-bg:rgba(var(--bs-body-color-rgb), .03);--bs-card-cap-color: ;--bs-card-height: ;--bs-card-color: ;--bs-card-bg:var(--bs-body-bg);--bs-card-img-overlay-padding:1rem;--bs-card-group-margin:.75rem;position:relative;display:flex;flex-direction:column;min-width:0;height:var(--bs-card-height);color:var(--bs-body-color);word-wrap:break-word;background-color:var(--bs-card-bg);background-clip:border-box;border:var(--bs-card-border-width) solid var(--bs-card-border-color);border-radius:var(--bs-card-border-radius)}.card-body{flex:1 1 auto;padding:var(--bs-card-spacer-y) var(--bs-card-spacer-x);color:var(--bs-card-color)}.btn-close{--bs-btn-close-color:#000;--bs-btn-close-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414'/%3e%3c/svg%3e");--bs-btn-close-opacity:.5;--bs-btn-close-hover-opacity:.75;--bs-btn-close-focus-shadow:0 0 0 .25rem rgba(13, 110, 253, .25);--bs-btn-close-focus-opacity:1;--bs-btn-close-disabled-opacity:.25;box-sizing:content-box;width:1em;height:1em;padding:.25em;color:var(--bs-btn-close-color);background:transparent var(--bs-btn-close-bg) center/1em auto no-repeat;filter:var(--bs-btn-close-filter);border:0;border-radius:.375rem;opacity:var(--bs-btn-close-opacity)}.btn-close:hover{color:var(--bs-btn-close-color);text-decoration:none;opacity:var(--bs-btn-close-hover-opacity)}.btn-close:focus{outline:0;box-shadow:var(--bs-btn-close-focus-shadow);opacity:var(--bs-btn-close-focus-opacity)}.btn-close:disabled{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;opacity:var(--bs-btn-close-disabled-opacity)}:root{--bs-btn-close-filter: }.modal{--bs-modal-zindex:1055;--bs-modal-width:500px;--bs-modal-padding:1rem;--bs-modal-margin:.5rem;--bs-modal-color:var(--bs-body-color);--bs-modal-bg:var(--bs-body-bg);--bs-modal-border-color:var(--bs-border-color-translucent);--bs-modal-border-width:var(--bs-border-width);--bs-modal-border-radius:var(--bs-border-radius-lg);--bs-modal-box-shadow:var(--bs-box-shadow-sm);--bs-modal-inner-border-radius:calc(var(--bs-border-radius-lg) - (var(--bs-border-width)));--bs-modal-header-padding-x:1rem;--bs-modal-header-padding-y:1rem;--bs-modal-header-padding:1rem 1rem;--bs-modal-header-border-color:var(--bs-border-color);--bs-modal-header-border-width:var(--bs-border-width);--bs-modal-title-line-height:1.5;--bs-modal-footer-gap:.5rem;--bs-modal-footer-bg: ;--bs-modal-footer-border-color:var(--bs-border-color);--bs-modal-footer-border-width:var(--bs-border-width);position:fixed;top:0;left:0;z-index:var(--bs-modal-zindex);display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:var(--bs-modal-margin);pointer-events:none}.modal.fade .modal-dialog{transform:translateY(-50px);transition:transform .3s ease-out}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;color:var(--bs-modal-color);pointer-events:auto;background-color:var(--bs-modal-bg);background-clip:padding-box;border:var(--bs-modal-border-width) solid var(--bs-modal-border-color);border-radius:var(--bs-modal-border-radius);outline:0}.modal-header{display:flex;flex-shrink:0;align-items:center;padding:var(--bs-modal-header-padding);border-bottom:var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);border-top-left-radius:var(--bs-modal-inner-border-radius);border-top-right-radius:var(--bs-modal-inner-border-radius)}.modal-header .btn-close{padding:calc(var(--bs-modal-header-padding-y) * .5) calc(var(--bs-modal-header-padding-x) * .5);margin-top:calc(-.5 * var(--bs-modal-header-padding-y));margin-right:calc(-.5 * var(--bs-modal-header-padding-x));margin-bottom:calc(-.5 * var(--bs-modal-header-padding-y));margin-left:auto}.modal-body{position:relative;flex:1 1 auto;padding:var(--bs-modal-padding)}@media (min-width:576px){.modal{--bs-modal-margin:1.75rem;--bs-modal-box-shadow:var(--bs-box-shadow)}.modal-dialog{max-width:var(--bs-modal-width);margin-right:auto;margin-left:auto}}@media (min-width:992px){.modal-lg{--bs-modal-width:800px}}:root{--bs-carousel-indicator-active-bg:#fff;--bs-carousel-caption-color:#fff;--bs-carousel-control-icon-filter: }.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-flex{display:flex!important}.d-none{display:none!important}.border-bottom-0{border-bottom:0!important}.justify-content-center{justify-content:center!important}.m-2{margin:.5rem!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:.25rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.me-1{margin-right:.25rem!important}.me-2{margin-right:.5rem!important}.mb-1{margin-bottom:.25rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:3rem!important}.p-4{padding:1.5rem!important}.p-5{padding:3rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-0{padding-top:0!important}.pt-1{padding-top:.25rem!important}.pt-2{padding-top:.5rem!important}.pt-3{padding-top:1rem!important}.pt-4{padding-top:1.5rem!important}.pt-5{padding-top:3rem!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pb-4{padding-bottom:1.5rem!important}.fw-bold{font-weight:700!important}.text-center{text-align:center!important}.text-white{--bs-text-opacity:1;color:rgba(var(--bs-white-rgb),var(--bs-text-opacity))!important}.rounded-0{border-radius:0!important}@media (min-width:768px){.d-md-inline{display:inline!important}.ms-md-4{margin-left:1.5rem!important}}@media (min-width:992px){.text-lg-start{text-align:left!important}}@media (min-width:1200px){.d-xl-inline-block{display:inline-block!important}}@font-face{font-family:Roboto;font-style:normal;font-weight:100;font-display:swap;src:local("Roboto Thin"),local("Roboto-Thin"),url(https://fonts.gstatic.com/s/roboto/v20/KFOkCnqEu92Fr1MmgVxFIzIFKw.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Roboto;font-style:normal;font-weight:100;font-display:swap;src:local("Roboto Thin"),local("Roboto-Thin"),url(https://fonts.gstatic.com/s/roboto/v20/KFOkCnqEu92Fr1MmgVxMIzIFKw.woff2) format("woff2");unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Roboto;font-style:normal;font-weight:100;font-display:swap;src:local("Roboto Thin"),local("Roboto-Thin"),url(https://fonts.gstatic.com/s/roboto/v20/KFOkCnqEu92Fr1MmgVxEIzIFKw.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Roboto;font-style:normal;font-weight:100;font-display:swap;src:local("Roboto Thin"),local("Roboto-Thin"),url(https://fonts.gstatic.com/s/roboto/v20/KFOkCnqEu92Fr1MmgVxLIzIFKw.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Roboto;font-style:normal;font-weight:100;font-display:swap;src:local("Roboto Thin"),local("Roboto-Thin"),url(https://fonts.gstatic.com/s/roboto/v20/KFOkCnqEu92Fr1MmgVxHIzIFKw.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Roboto;font-style:normal;font-weight:100;font-display:swap;src:local("Roboto Thin"),local("Roboto-Thin"),url(https://fonts.gstatic.com/s/roboto/v20/KFOkCnqEu92Fr1MmgVxGIzIFKw.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Roboto;font-style:normal;font-weight:100;font-display:swap;src:local("Roboto Thin"),local("Roboto-Thin"),url(https://fonts.gstatic.com/s/roboto/v20/KFOkCnqEu92Fr1MmgVxIIzI.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:normal;font-weight:300;font-display:swap;src:local("Roboto Light"),local("Roboto-Light"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmSU5fCRc4EsA.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Roboto;font-style:normal;font-weight:300;font-display:swap;src:local("Roboto Light"),local("Roboto-Light"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmSU5fABc4EsA.woff2) format("woff2");unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Roboto;font-style:normal;font-weight:300;font-display:swap;src:local("Roboto Light"),local("Roboto-Light"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmSU5fCBc4EsA.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Roboto;font-style:normal;font-weight:300;font-display:swap;src:local("Roboto Light"),local("Roboto-Light"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmSU5fBxc4EsA.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Roboto;font-style:normal;font-weight:300;font-display:swap;src:local("Roboto Light"),local("Roboto-Light"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmSU5fCxc4EsA.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Roboto;font-style:normal;font-weight:300;font-display:swap;src:local("Roboto Light"),local("Roboto-Light"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmSU5fChc4EsA.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Roboto;font-style:normal;font-weight:300;font-display:swap;src:local("Roboto Light"),local("Roboto-Light"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmSU5fBBc4.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-display:swap;src:local("Roboto"),local("Roboto-Regular"),url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu72xKOzY.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-display:swap;src:local("Roboto"),local("Roboto-Regular"),url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu5mxKOzY.woff2) format("woff2");unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-display:swap;src:local("Roboto"),local("Roboto-Regular"),url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu7mxKOzY.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-display:swap;src:local("Roboto"),local("Roboto-Regular"),url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu4WxKOzY.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-display:swap;src:local("Roboto"),local("Roboto-Regular"),url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu7WxKOzY.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-display:swap;src:local("Roboto"),local("Roboto-Regular"),url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu7GxKOzY.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Roboto;font-style:normal;font-weight:400;font-display:swap;src:local("Roboto"),local("Roboto-Regular"),url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu4mxK.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-display:swap;src:local("Roboto Medium"),local("Roboto-Medium"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fCRc4EsA.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-display:swap;src:local("Roboto Medium"),local("Roboto-Medium"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fABc4EsA.woff2) format("woff2");unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-display:swap;src:local("Roboto Medium"),local("Roboto-Medium"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fCBc4EsA.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-display:swap;src:local("Roboto Medium"),local("Roboto-Medium"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fBxc4EsA.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-display:swap;src:local("Roboto Medium"),local("Roboto-Medium"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fCxc4EsA.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-display:swap;src:local("Roboto Medium"),local("Roboto-Medium"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fChc4EsA.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Roboto;font-style:normal;font-weight:500;font-display:swap;src:local("Roboto Medium"),local("Roboto-Medium"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fBBc4.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-display:swap;src:local("Roboto Bold"),local("Roboto-Bold"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-display:swap;src:local("Roboto Bold"),local("Roboto-Bold"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2) format("woff2");unicode-range:U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-display:swap;src:local("Roboto Bold"),local("Roboto-Bold"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-display:swap;src:local("Roboto Bold"),local("Roboto-Bold"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2) format("woff2");unicode-range:U+0370-03FF}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-display:swap;src:local("Roboto Bold"),local("Roboto-Bold"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+1EA0-1EF9,U+20AB}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-display:swap;src:local("Roboto Bold"),local("Roboto-Bold"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Roboto;font-style:normal;font-weight:700;font-display:swap;src:local("Roboto Bold"),local("Roboto-Bold"),url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmWUlfBBc4.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}body{padding-top:3.5rem;font-family:Roboto,sans-serif}:root{--primary-color: #0d6efd;--secondary-color: #1976d2;--background-dark: #000;--background-footer: #212121;--text-light: #e0e0e0;--text-white: #fff;--github-color: black;--linkedin-color: #0077B5;--twitter-color: #1DA1F2;--youtube-color: #FF0000;--facebook-color: #1877F2}
</style><link rel="stylesheet" href="styles-A6HZA37D.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles-A6HZA37D.css"></noscript><style ng-app-id="ng">.nga-navbar[_ngcontent-ng-c3021492192]{background-color:var(--background-dark);border-bottom:2px solid var(--primary-color)}.nga-logo[_ngcontent-ng-c3021492192]{font-weight:500;position:relative;display:inline-block;transition:color .3s ease,text-shadow .3s ease}.nga-logo[_ngcontent-ng-c3021492192]:hover{color:#ffffffe6;text-shadow:0 0 8px rgba(255,255,255,.8),0 0 15px rgba(255,255,255,.6)}.nga-logo[_ngcontent-ng-c3021492192]:before{content:"";position:absolute;left:0;bottom:-3px;width:0;height:2px;background:#fffc;transition:width .3s ease}.nga-logo[_ngcontent-ng-c3021492192]:hover:before{width:100%}.nga-nav-link[_ngcontent-ng-c3021492192]{position:relative;color:var(--text-white);font-weight:500;text-decoration:none;transition:color .3s ease}.nga-nav-link[_ngcontent-ng-c3021492192]:after{content:"";position:absolute;left:0;bottom:-2px;width:0;height:2px;background-color:#fff;transition:width .3s ease}.nga-nav-link[_ngcontent-ng-c3021492192]:hover{color:#fff}.nga-nav-link[_ngcontent-ng-c3021492192]:hover:after{width:100%}.nga-nav-link-dropdown[_ngcontent-ng-c3021492192]{color:#fff;font-weight:500}.nga-nav-link-dropdown[_ngcontent-ng-c3021492192]:hover{color:#fff}.nga-btn-navbar[_ngcontent-ng-c3021492192]{--bs-btn-color: var(--text-white);--bs-btn-bg: var(--primary-color);--bs-btn-border-color: var(--primary-color);--bs-btn-hover-bg: #0056b3;--bs-btn-hover-border-color: #0056b3;color:var(--bs-btn-color);background-color:var(--bs-btn-bg);border-color:var(--bs-btn-border-color);transition:all .3s ease}.nga-btn-navbar[_ngcontent-ng-c3021492192]:hover{background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);color:var(--text-white)}</style><style ng-app-id="ng">.nga-footer[_ngcontent-ng-c4014730536]{background-color:var(--background-footer);color:#fff}.nga-footer[_ngcontent-ng-c4014730536] a[_ngcontent-ng-c4014730536]{color:#fff;text-decoration:none}.nga-footer[_ngcontent-ng-c4014730536] a[_ngcontent-ng-c4014730536]:hover, .nga-footer[_ngcontent-ng-c4014730536] a[_ngcontent-ng-c4014730536]:focus{color:#fff}.nga-hint[_ngcontent-ng-c4014730536]{background-color:var(--secondary-color);height:34px}.nga-btn-social[_ngcontent-ng-c4014730536]{position:relative;z-index:1;display:inline-block;width:47px;height:47px;padding:0;margin:10px;border-radius:50%;overflow:hidden;vertical-align:middle;cursor:pointer;transition:all .2s ease-in-out;box-shadow:0 5px 11px #0000002e,0 4px 15px #00000026}.nga-btn-social[_ngcontent-ng-c4014730536]:hover{box-shadow:0 8px 17px #0003,0 6px 20px #00000030}.nga-btn-social[_ngcontent-ng-c4014730536] i[_ngcontent-ng-c4014730536]{display:inline-block;width:inherit;font-size:1.25rem;line-height:47px;color:#fff;text-align:center}.nga-btn-social[_ngcontent-ng-c4014730536] i[_ngcontent-ng-c4014730536]:hover{color:#fff;text-shadow:0 0 5px rgba(255,255,255,.8),0 0 10px rgba(255,255,255,.5);transition:color .3s ease,text-shadow .3s ease}.nga-btn-social.nga-btn-github[_ngcontent-ng-c4014730536]{background-color:var(--github-color)}.nga-btn-social.nga-btn-linkedin[_ngcontent-ng-c4014730536]{background-color:var(--linkedin-color)}.nga-btn-social.nga-btn-twitter[_ngcontent-ng-c4014730536]{background-color:var(--twitter-color)}.nga-btn-social.nga-btn-youtube[_ngcontent-ng-c4014730536]{background-color:var(--youtube-color)}.nga-btn-social.nga-btn-facebook[_ngcontent-ng-c4014730536]{background-color:var(--facebook-color)}.nga-footer-link[_ngcontent-ng-c4014730536]{position:relative;color:var(--text-light);font-weight:500;text-decoration:none;transition:color .3s ease}.nga-footer-link[_ngcontent-ng-c4014730536]:after{content:"";position:absolute;left:0;bottom:-2px;width:0;height:2px;background-color:#fff;transition:width .3s ease}.nga-footer-link[_ngcontent-ng-c4014730536]:hover{color:#fff}.nga-footer-link[_ngcontent-ng-c4014730536]:hover:after{width:100%}.nga-footer-bottom[_ngcontent-ng-c4014730536]{background-color:#101010}.nga-footer-link-bottom[_ngcontent-ng-c4014730536]{color:#fff;text-decoration:none;font-weight:500;transition:color .3s ease,text-shadow .3s ease}.nga-footer-link-bottom[_ngcontent-ng-c4014730536]:hover{color:var(--primary-color);text-shadow:0 0 8px var(--primary-color),0 0 15px rgba(255,255,255,.6)}</style><style ng-app-id="ng">.video-thumbnail{position:relative;display:inline-block;border-radius:10px;overflow:hidden;box-shadow:5px 5px 10px #0003;transition:transform .3s ease-in-out}.video-thumbnail:hover{transform:scale(1.05)}.play-button{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);background-color:#f00c;color:#fff;width:60px;height:60px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:24px;box-shadow:0 4px 10px #0000004d;transition:background-color .3s,transform .3s}.video-thumbnail:hover .play-button{background-color:red;transform:translate(-50%,-50%) scale(1.1)}.video-thumbnail img{transition:opacity .3s}.video-thumbnail:hover img{opacity:.7}.nga-btn-guide-image{max-width:300px;height:auto;box-shadow:8px 8px 16px #0003,-5px -5px 10px #ffffff80;border-radius:8px;border:1px solid rgba(0,0,0,.1);margin:10px auto;cursor:pointer}.nga-btn-guide{padding:10px 20px;font-size:1rem;border-radius:8px;box-shadow:5px 5px 10px #0003;border:none}.nga-btn-guide-image img{object-fit:cover}.image-3d{box-shadow:0 8px 15px #0003;border-radius:10px}.bordered-content{padding:0;border:0px solid rgb(213,216,216);margin-top:0;margin-bottom:0;border-radius:0;text-align:left}p{margin:0}.nga-tutorial-main{font-size:1.2em}@media (max-width: 992px){.nga-tutorial-main{font-size:1em}}.nga-btn-guide{border-radius:10em;font-size:.8rem;font-weight:700;padding:.84rem 2.14rem;--bs-btn-color: #fff;--bs-btn-bg: #1976d2;--bs-btn-border-color: #1976d2;--bs-btn-hover-color: white;--bs-btn-hover-bg: #1976d2}.nga-btn-guide:hover{box-shadow:#00000040 0 14px 28px,#00000038 0 10px 10px;transition:box-shadow .3s ease-in-out}.nga-link-author{text-decoration:none}.nga-link-author:hover{color:#fff;text-decoration:underline;cursor:pointer}.grey-darken-1{background-color:#757575}.green-lighten-1{background-color:#66bb6a}.red-darken-1{background-color:#e53935}.blue-gradient3{background-color:#2196f3}.red-gradient{background:linear-gradient(40deg,#ff6b6b,#d32f2f)}.orange-gradient{background:linear-gradient(40deg,#ffa726,#f57c00)}.yellow-gradient{background:linear-gradient(40deg,#ffee58,#fbc02d)}.green-gradient{background:linear-gradient(40deg,#5ea380,#075551)}.green-gradient2{background:linear-gradient(40deg,#66bb6a,#388e3c)}.blue-gradient{background:linear-gradient(40deg,#45cafc,#303f9f)}.blue-gradient2{background:linear-gradient(40deg,#64b5f6,#1976d2)}.indigo-gradient{background:linear-gradient(40deg,#7986cb,#303f9f)}.purple-gradient{background:linear-gradient(40deg,#ba68c8,#8e24aa)}.pink-gradient{background:linear-gradient(40deg,#f48fb1,#d81b60)}.brown-gradient{background:linear-gradient(40deg,#8d6e63,#4e342e)}.gray-gradient{background:linear-gradient(40deg,#bdbdbd,#757575)}.black-gradient{background:linear-gradient(40deg,#616161,#212121)}.white-gradient{background:linear-gradient(40deg,#fff,#f5f5f5)}.aqua-gradient{background:linear-gradient(40deg,#4dd0e1,#00838f)}.gold-gradient{background:linear-gradient(40deg,#ffeb3b,#fbc02d)}.silver-gradient{background:linear-gradient(40deg,#cfd8dc,#90a4ae)}.nga-container-tutorial a{text-decoration:none}.nga-container-tutorial a:link{color:#1976d2}.nga-container-tutorial a:visited{color:#1976d2;font-weight:700}.nga-container-tutorial a:hover{color:#1976d2;font-weight:700;text-decoration:underline}.nga-container-tutorial a:active{color:#1976d2}.nga-hr{color:#fff;opacity:1}.nga-blue-text{color:#2196f3}.nga-text-code{color:#1976d2;font-weight:700}.nga-ellipsis{text-overflow:ellipsis;overflow:hidden}.social-shares{display:none}@media (min-width:992px){.social-shares{display:block;position:fixed;z-index:1;background-color:#fff;border:1px solid #ebebeb;border-radius:5px;padding:15px 2px 10px;text-align:center;top:140px;width:60px}}@media (min-width:992px) and (min-width:1200px){.social-shares{text-decoration:none;width:75px}}@media (min-width:992px){.social-shares ul{text-decoration:none;margin-bottom:0;padding-left:0;list-style:none}}@media (min-width:992px) and (min-width:1200px){.social-shares ul li.share-text{font-size:18px}}@media (min-width:992px){.social-shares ul li a{text-decoration:none;display:-webkit-inline-box;display:inline-flex;-webkit-box-align:center;align-items:center;-webkit-box-pack:center;justify-content:center;width:50px;height:50px;font-size:24px;width:40px;height:40px}}@media (min-width:992px) and (min-width:1200px){.social-shares ul li a{font-size:26px;width:50px;height:50px}}@media (min-width:992px){.social-shares ul li a i.icon-twitter{text-decoration:none;color:#55acee}.social-shares ul li a i.icon-twitter:hover{text-decoration:none;color:#000}.social-shares ul li a i.icon-facebook{color:#3b5998}.social-shares ul li a i.icon-facebook:hover{color:#000}.social-shares ul li a i.icon-linkedin{color:#0082ca}.social-shares ul li a i.icon-linkedin:hover{color:#000}}.nga-btn-social{position:relative;z-index:1;display:inline-block;width:47px;height:47px;padding:0;margin:10px;border-radius:50%;overflow:hidden;vertical-align:middle;cursor:pointer;transition:all .2s ease-in-out;box-shadow:0 5px 11px #0000002e,0 4px 15px #00000026}.nga-btn-social:hover{box-shadow:0 8px 17px #0003,0 6px 20px #00000030}.nga-btn-social i{display:inline-block;width:inherit;font-size:1.25rem;line-height:47px;color:#fff;text-align:center}.nga-btn-social i:hover{color:#fff;text-shadow:0 0 5px rgba(255,255,255,.8),0 0 10px rgba(255,255,255,.5);transition:color .3s ease,text-shadow .3s ease}.nga-btn-social.nga-btn-github{background-color:var(--github-color)}.nga-btn-social.nga-btn-linkedin{background-color:var(--linkedin-color)}.nga-btn-social.nga-btn-twitter{background-color:var(--twitter-color)}.nga-btn-social.nga-btn-youtube{background-color:var(--youtube-color)}.nga-btn-social.nga-btn-facebook{background-color:var(--facebook-color)}.nga-halo-effect{display:inline-block;border-radius:5px;box-shadow:4px 4px 10px #0009,-2px -2px 5px #fff3;filter:brightness(1.1) contrast(1.05)}code[class*=language-],pre[class*=language-]{color:#000;background:0 0;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{position:relative;margin:.5em 0;overflow:visible;padding:1px}pre[class*=language-]>code{position:relative;z-index:1;border-left:10px solid #358ccb;box-shadow:-1px 0 #358ccb,0 0 0 1px #dfdfdf;background-color:#fdfdfd;background-image:linear-gradient(transparent 50%,#458ed10a 50%);background-size:3em 3em;background-origin:content-box;background-attachment:local}code[class*=language-]{max-height:inherit;height:inherit;padding:0 1em;display:block;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background-color:#fdfdfd;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin-bottom:1em}:not(pre)>code[class*=language-]{position:relative;padding:.2em;border-radius:.3em;color:#c92c2c;border:1px solid rgba(0,0,0,.1);display:inline;white-space:normal}pre[class*=language-]:after,pre[class*=language-]:before{content:"";display:block;position:absolute;bottom:.75em;left:.18em;width:40%;height:20%;max-height:13em;box-shadow:0 13px 8px #979797;-webkit-transform:rotate(-2deg);-moz-transform:rotate(-2deg);-ms-transform:rotate(-2deg);-o-transform:rotate(-2deg);transform:rotate(-2deg)}pre[class*=language-]:after{right:.75em;left:auto;-webkit-transform:rotate(2deg);-moz-transform:rotate(2deg);-ms-transform:rotate(2deg);-o-transform:rotate(2deg);transform:rotate(2deg)}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#7d8b99}.token.punctuation{color:#5f6364}.token.boolean,.token.constant,.token.deleted,.token.function-name,.token.number,.token.property,.token.symbol,.token.tag{color:#c92c2c}.token.attr-name,.token.builtin,.token.char,.token.function,.token.inserted,.token.selector,.token.string{color:#2f9c0a}.token.entity,.token.operator,.token.url,.token.variable{color:#a67f59;background:#ffffff80}.token.atrule,.token.attr-value,.token.class-name,.token.keyword{color:#1990b8}.token.important,.token.regex{color:#e90}.language-css .token.string,.style .token.string{color:#a67f59;background:#ffffff80}.token.important{font-weight:400}.token.bold{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.namespace{opacity:.7}@media screen and (max-width:767px){pre[class*=language-]:after,pre[class*=language-]:before{bottom:14px;box-shadow:none}}pre[class*=language-].line-numbers.line-numbers{padding-left:0}pre[class*=language-].line-numbers.line-numbers code{padding-left:3.8em}pre[class*=language-].line-numbers.line-numbers .line-numbers-rows{left:0}pre[class*=language-][data-line]{padding-top:0;padding-bottom:0;padding-left:0}pre[data-line] code{position:relative;padding-left:4em}pre .line-highlight{margin-top:0}.video-caption{font-weight:600;text-decoration:none}
</style><style ng-app-id="ng">.nga-btn-guide[_ngcontent-ng-c429373045]{border-radius:10em;font-size:.8rem;font-weight:700;padding:.84rem 2.14rem;text-transform:uppercase;--bs-btn-color: #fff;--bs-btn-bg: #1976d2;--bs-btn-border-color: #1976d2;--bs-btn-hover-color: white;--bs-btn-hover-bg: #1976d2;--bs-btn-hover-border-color: #1976d2;--bs-btn-focus-shadow-rgb: 49, 132, 253;--bs-btn-active-color: #fff;--bs-btn-active-bg: #1976d2;--bs-btn-active-border-color: #1976d2;--bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);--bs-btn-disabled-color: #fff;--bs-btn-disabled-bg: #1976d2;--bs-btn-disabled-border-color: #1976d2}.nga-btn-guide[_ngcontent-ng-c429373045]:hover{box-shadow:#00000040 0 14px 28px,#00000038 0 10px 10px;transition:box-shadow .3s ease-in-out}.nga-edit-error[_ngcontent-ng-c429373045]{font-size:.9rem;font-weight:500;color:red}.nga-text-guide[_ngcontent-ng-c429373045]{color:#1976d2}</style><meta name="author" content="Danny"><meta name="description" content="Un guide complet pour créer un projet Angular, comprenant l'installation, la configuration, la gestion de l'environnement, du déploiement et des tests.Code source fourni en exemple."><meta name="robots" content="index, follow"><link rel="canonical" href="https://www.ganatan.com/tutorials/demarrer-avec-angular"><link hreflang="x-default" rel="alternate" href="https://www.ganatan.com/tutorials/demarrer-avec-angular"><link hreflang="fr" rel="alternate" href="https://www.ganatan.com/tutorials/demarrer-avec-angular"><link hreflang="en" rel="alternate" href="https://www.ganatan.com/en/tutorials/getting-started-with-angular"><meta property="og:url" content="https://www.ganatan.com/tutorials/demarrer-avec-angular"><meta property="og:type" content><meta property="og:title" content="Démarrer avec Angular | Tutoriel Complet pour Débutants"><meta property="og:description" content><meta property="og:image" content="https://api.ganatan.com/tutorials/img/"><meta property="og:site_name" content><meta property="og:locale" content><meta property="og:image:width" content><meta property="og:image:height" content><meta property="og:image:alt" content><meta property="og:video" content><meta property="og:audio" content><meta property="og:determiner" content><meta property="og:locale:alternate" content><meta property="article:published_time" content><meta property="article:modified_time" content><meta property="article:expiration_time" content><meta property="article:author" content><meta property="article:section" content><meta property="article:tag" content><meta property="article:publisher" content><meta name="twitter:card" content><meta name="twitter:site" content><meta name="twitter:creator" content><meta name="twitter:title" content><meta name="twitter:description" content><meta name="twitter:image" content="https://api.ganatan.com/tutorials/img/"><meta name="twitter:image:alt" content><meta name="twitter:player" content><meta name="twitter:player:width" content><meta name="twitter:player:height" content><meta name="twitter:app:name:iphone" content><meta name="twitter:app:id:iphone" content><meta name="twitter:app:name:ipad" content><meta name="twitter:app:id:ipad" content><meta name="twitter:app:name:googleplay" content><meta name="twitter:app:id:googleplay" content></head>
<body><!--nghm--><script type="text/javascript" id="ng-event-dispatch-contract">(()=>{function p(t,n,r,o,e,i,f,m){return{eventType:t,event:n,targetElement:r,eic:o,timeStamp:e,eia:i,eirp:f,eiack:m}}function u(t){let n=[],r=e=>{n.push(e)};return{c:t,q:n,et:[],etc:[],d:r,h:e=>{r(p(e.type,e,e.target,t,Date.now()))}}}function s(t,n,r){for(let o=0;o<n.length;o++){let e=n[o];(r?t.etc:t.et).push(e),t.c.addEventListener(e,t.h,r)}}function c(t,n,r,o,e=window){let i=u(t);e._ejsas||(e._ejsas={}),e._ejsas[n]=i,s(i,r),s(i,o,!0)}window.__jsaction_bootstrap=c;})();
</script><script>window.__jsaction_bootstrap(document.body,"ng",["click","keydown","input","compositionstart","compositionend"],["blur"]);</script>
<app-root ng-version="20.3.2" ngh="5" ng-server-context="ssg"><app-header _nghost-ng-c3021492192 ngh="0"><header _ngcontent-ng-c3021492192 class="navbar navbar-expand-md navbar-dark fixed-top nga-navbar"><nav _ngcontent-ng-c3021492192 aria-label="Main navigation" class="container"><a _ngcontent-ng-c3021492192 routerlink="/" class="navbar-brand" alt="Home - GANATAN" href="/" jsaction="click:;"><img _ngcontent-ng-c3021492192 width="25" height="25" src="https://api.ganatan.com/assets/img/ganatan-logo.png" srcset="https://api.ganatan.com/assets/img/ganatan-logo.png, https://api.ganatan.com/assets/img/ganatan-logo@2x.png 2x" alt="GANATAN Logo de l'entreprise "><span _ngcontent-ng-c3021492192 class="nga-logo mx-1" aria-label="GANATAN">GANATAN</span></a><!----><!----><button _ngcontent-ng-c3021492192 type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation" class="navbar-toggler"><span _ngcontent-ng-c3021492192 class="navbar-toggler-icon"></span></button><div _ngcontent-ng-c3021492192 id="navbarCollapse" class="collapse navbar-collapse"><!----><ul _ngcontent-ng-c3021492192 class="navbar-nav mx-auto"><li _ngcontent-ng-c3021492192 class="nav-item"><a _ngcontent-ng-c3021492192 aria-current="page" routerlink="/tutorials" class="nav-link nga-nav-link" href="/tutorials" jsaction="click:;">Tutoriels</a></li><!----><!----></ul><ul _ngcontent-ng-c3021492192 class="navbar-nav mx-auto"><li _ngcontent-ng-c3021492192 class="nav-item"><a _ngcontent-ng-c3021492192 aria-current="page" class="nav-link nga-nav-link" href="/about" jsaction="click:;">A propos</a></li><!----><!----><li _ngcontent-ng-c3021492192 class="nav-item"><a _ngcontent-ng-c3021492192 aria-current="page" class="nav-link nga-nav-link" href="https://github.com/ganatan">GitHub</a></li></ul><!----><div _ngcontent-ng-c3021492192 class="d-flex"><button _ngcontent-ng-c3021492192 routerlink="/login" type="button" class="btn btn-sm nga-btn-navbar me-2" tabindex="0" jsaction="click:;"><i _ngcontent-ng-c3021492192 class="fa-solid fa-user-plus"></i> Connexion </button><!----><!----><!----><!----><!----><!----></div><!----></div></nav></header></app-header><main><router-outlet></router-outlet><app-item ngh="3"><!----><div class="nga-tutorial-main"><div id="element-0"><div class="blue-gradient container-fluid pt-5"><div class="container"><div class="row d-flex justify-content-center"><div class="col-md-10"><div class="nga-ellipsis text-center text-white"><h1 class="h1 m-2 pb-1">Démarrer une Application Web avec Angular</h1></div><div class="col-md-12 pt-1 text-center text-white"><span class="d-block d-md-inline me-2"><i class="fas fa-edit"></i> Mis à jour : 23/12/2025 </span><!----><!----><span class="d-block d-md-inline ms-md-4"><i class="fas fa-user-edit me-2"></i><a class="nga-link-author text-white" href="/about" jsaction="click:;">Danny</a></span></div><div class="text-center col-md-12 pt-2"><a href="/en/tutorials/getting-started-with-angular" jsaction="click:;"><img width="24" height="24" alt="English Version" src="https://api.ganatan.com/assets/img/en-24-24.png" srcset="https://api.ganatan.com/assets/img/en-24-24.png, https://api.ganatan.com/assets/img/en-24-24@2x.png 2x"></a></div><!----><!----><hr class="nga-hr"><section class="mt-4"><div class="row mt-1"><div class="col-lg-7 col-md-12 nga-ellipsis"><div class="text-white"><p>Nous allons réaliser une <strong>Application Web.</strong><br><br>Dans ce tutoriel, nous utiliserons <strong>Angular version 21.0.6</strong><br><br>Pour commencer notre application nous partirons de zéro (<strong>from scratch</strong>) en nous efforçant de suivre les meilleures pratiques (<strong>best practices) </strong>d'Angular.<br><br></p><ul><li>Angular a été créé par <strong>Google</strong>.<br><br></li><li>Angular est <strong>open source</strong>, son utilisation est donc gratuite.<br><br></li><li>Angular utilise <strong>Typescript</strong>.<br><br></li><li>Angular est un framework <strong>Javascript Frontend</strong>.</li></ul></div></div><div class="col-lg-5 ml-auto col-md-12"><!----><div><img class="z-depth-0 img-fluid nga-halo-effect" src="https://api.ganatan.com/tutorials/img/demarrer-avec-angular-intro.png" alt="Démarrer avec Angular" title="Démarrer avec Angular"></div><!----></div></div></section><section class="mt-4 mb-4"><div class="row mt-1"><div class="col-lg-12 col-md-12 nga-ellipsis"><div class="card p-4"><div class="row mt-1"><div class="col-lg-5 ml-auto col-md-12 d-flex justify-content-center"><img tabindex="0" class="nga-btn-guide-image z-depth-0 img-fluid" src="https://api.ganatan.com/tutorials/img/demarrer-avec-angular-guide.png" alt="Téléchargez le guide Démarrer avec Angular" title="Téléchargez le guide Démarrer avec Angular" jsaction="click:;keydown:;"></div><div class="col-lg-7 col-md-12 nga-ellipsis text-center"><p class="fw-bold pt-4 mb-4">Si vous n'avez pas le temps de lire ce guide en entier,<br> téléchargez le maintenant<br></p><button type="button" class="nga-btn-guide btn" jsaction="click:;">JE TELECHARGE MON GUIDE</button></div></div><!----><!----></div></div></div></section><!----></div></div></div></div><!----><!----><!----><!----><!----></div><div id="element-1"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Comment le faire ? </h2><!----><div class="pt-4"><p>Pour débuter notre projet voici un résumé de ce que nous allons faire.<br><br></p><ul><li><strong>Installation des outils nécessaires</strong><br><br><strong>Node.js</strong> sera notre plateforme de développement javascript.<br>Pas le choix, sans Node.js ça ne marchera pas.<br><br><strong>Visual studio Code</strong> sera notre éditeur de code.<br>Le choix est totalement arbitraire mais pour un outil Microsoft c'est une petite merveille<br><br><strong>Git </strong>sera notre gestionnaire de logiciel.<br>Grâce à lui vous pourrez utiliser le code source de ce tutoriel.<br><br><strong>Angular CLI </strong>sera notre homme à tout faire.<br>Sans doute l'outil le plus connu et le plus utilisé du Framework Angular.<br><br></li><li><strong>Initialisation du projet</strong><br>Nous utiliserons Angular CLI pour la mise en place de l'architecture du projet,<br>en utilisant les meilleures pratiques (best practices) préconisées par Google.<br><br></li><li><strong>Mise à jour du projet</strong><br>Vérifier les dépendances utilisées et les mettre à jour.<br><br></li><li><strong>Effectuer les Tests</strong><br>Les tests Unitaires et les outils qui leur sont dédiés Karma et Jasmine.<br>Le linting et l' amélioration du code avec ESLint.<br><br></li><li><strong>Environment</strong><br>Depuis la version 15 l'équipe d'Angular n'intègre plus les paramètres d'environnement (environment en anglais).<br>Très utiles nous verrons comment les déclarer et les utiliser.<br><br></li><li><strong>Déploiement</strong><br>Comment déployer votre application sur internet.<br><br></li><li><strong>Code source</strong><br>Le code complet du projet est disponible sur Github.<br><br></li></ul><br></div><!----></div></div></div><!----><!----><!----></div><div id="element-2"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Une image vaut mille mots </h2><!----><div class="pt-4"><p>Le résumé en image de ce que nous allons faire<br></p></div><!----></div></div></div><!----><!----><!----></div><div id="element-3"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/resume-en-images.png" alt="Creer une application web avec Angular résumé en image" title="Creer une application web avec Angular résumé en image"></div></div></div></div></div><!----><!----></div><div id="element-4"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>Si vous êtes du genre très pressé ci-dessous un résumé en commandes sinon passez à l'étape suivante.</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-5"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> Commandes à éxécuter </span></div><!----><div><app-prism-block ngh="1"><pre class="language-git" tabindex="0"><code class="language-git"><span class="token comment"># Désinstallez Angular CLI (au cas ou une ancienne version d'Angular aurait été installée)</span>
npm uninstall -g @angular/cli
<span class="token comment"># Installez Angular CLI version spécifique (la dernière si possible)</span>
npm install -g @angular/cli@21.0.6
<span class="token comment"># Créez un répertoire demo (le nom est ici arbitraire)</span>
mkdir demo
<span class="token comment"># Allez dans ce répertoire</span>
cd demo
<span class="token comment"># Générez un projet appelé angular-starter avec choix manuel des options</span>
<span class="token comment"># Sélectionnez les options par défaut</span>
ng new angular-starter
<span class="token comment"># Positionnez vous dans le projet</span>
cd angular-starter
<span class="token comment"># Exécutez l'application</span>
npm run start
<span class="token comment"># Testez l'application dans votre navigateur</span>
http://localhost:4200</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-6"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Et si vous êtes moins pressé ça va commencer </h2><!----><div class="pt-4"><p>On va faire les choses sérieusement mais on ne va pas se prendre au sérieux.<br>Donc c'est parti pour <strong>un peu d'humour</strong> et <strong>beaucoup de technique.</strong></p></div><!----></div></div></div><!----><!----><!----></div><div id="element-7"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><p class="font-weight-bold"> sans IA </p><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/ca-va-commencer.png" alt="Angular ça va fonctionner" title="Angular ça va fonctionner"></div></div></div></div></div><!----><!----></div><div id="element-8"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><p class="font-weight-bold"> avec IA </p><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/avec-ia.png" alt="avec IA" title="avec IA"></div></div></div></div></div><!----><!----></div><div id="element-9"><!----><div class="blue-gradient2 container-fluid"><div class="container nga-container-tutorial"><div class="row d-flex justify-content-center"><div class="col-md-10"><div class="text-center text-white"><div class="h4 pt-4" id="true"> Etape 1</div><h2 class="pt-2 pb-2">Installation des outils nécessaires pour Angular</h2></div><hr class="nga-hr"><section><div class="row mt-3 mb-4"><div class="col-lg-7 col-md-12 nga-ellipsis"><div class="text-white"><p>Avant d'utiliser Angular il nous faut installer un certain nombre de logiciels<br><br></p><ul><li><strong>Node.js</strong><br>Impossible de faire fonctionner Angular sans lui.<br><br></li><li><strong>Visual Studio Code</strong><br>Ce choix est arbitraire.<br><br></li><li><strong>Git</strong><br>Très utile mais pas essentiel<br><br></li><li><strong>Angular CLI</strong><br>C'est l'homme à tout faire d'Angular</li></ul></div></div><div class="col-lg-5 ml-auto col-md-12 mt-4 mb-5"><img class="z-depth-0 img-fluid" src="https://api.ganatan.com/tutorials/img/installation-outils.png" alt="Installation des outils nécessaires pour Angular" title="Installation des outils nécessaires pour Angular"></div></div></section></div></div></div></div><!----><!----><!----><!----></div><div id="element-10"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Installation de Node.js </h2><!----><div class="pt-4"><p><strong>Si vous ne l'installez pas, Angular ne fonctionnera pas.</strong><br><br>A ce propos Angular, React et Vuejs ont besoin tous trois de Node.js.<br><br>Le site officiel c'est ici <a href="https://nodejs.org/en">https://nodejs.org/en</a> <br><br>Voilà ce qu'il nous dit:<br><strong>Node.js est un environnement d’exécution JavaScript construit sur le moteur JavaScript V8 de Chrome.</strong><br><br>Son inventeur Ryan Lienhart Dahl l'a créé le 27 mai 2009.<br>Il avait une idée précise derrière la tête : <em>la simplicité et la rapidité d'exécution de programmes écrits en javascript</em>.<br><br>Le choix du nom n'est donc pas anodin.<br><br></p><ul><li><strong>Node </strong>signifie <strong>noeud</strong></li><li><strong>JS </strong>signifie <strong>javascript</strong></li></ul><p>Node.js est ainsi le <strong>point central </strong>qui va permettre d'<strong>exécuter des programmes écrits</strong> en javascript <strong>côté serveur.</strong></p></div><!----></div></div></div><!----><!----><!----></div><div id="element-11"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><p class="font-weight-bold"> Mon Dieu ! C'est plein d'étoiles ! </p><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/nodejs-fonctionne.png" alt="Node.js et Angular" title="Node.js et Angular"></div></div></div></div></div><!----><!----></div><div id="element-12"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>Node.js utilise un outil <strong>npm </strong>(Node Package Manager)<br>Npm simplifie la vie du développeur en permettant de publier et de partager des librairies Node.js.<br>Npm permet notamment de simplifier l'installation, la mise à jour ou la désinstallation de ces librairies.<br><br>On pourra parler de librairies, de paquets ou de dépendances (en anglais packages ou dependencies).<br><br>Comment l'installer ?<br><br>Sur le site officiel le téléchargement est accessible à l'adresse<br><a href="https://nodejs.org/en">https://nodejs.org/en</a><br><br>Nous allons utiliser la version<strong> LTS</strong> (<strong>Long Term Support</strong> ou Support à long terme).<br>LTS signifie que l'éditeur nous garantit en général une période de maintenance d'au moins deux ans,<br><br></p><ul><li><strong>Node.js</strong> version 24.12.0 LTS</li><li><strong>npm</strong> (node package manager) version 11.4.1</li></ul><p>Il s'agit d'une installation classique.<br><br></p><ul><li>Sélectionnez <strong>Download Node.js (LTS)</strong>.</li><li>Téléchargez le programme et éxécutez le.</li></ul><p>Une fois l'installation effectuée on peut vérifier que Node.js est installé sur notre poste de travail.</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-13"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> Commandes à éxécuter </span></div><!----><div><app-prism-block ngh="1"><pre class="language-git" tabindex="0"><code class="language-git"><span class="token comment"># Vérification de la version de Node.js et de npm (méthode 1)</span>
node --version
npm --version
<span class="token comment"># Vérification de la version de Node.js et de npm (méthode 2)</span>
node -v
npm -v
<span class="token comment"># Mise à jour de npm</span>
npm install npm -g
<span class="token comment"># Vérification de la mise à jour de npm</span>
npm -v</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-14"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Comment savoir que Node.js fonctionne ? </h2><!----><div class="pt-4">On va vérifier que Node.js fonctionne et qu'il permet d'exécuter un programme javascript.</div><!----></div></div></div><!----><!----><!----></div><div id="element-15"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/nodejs-fonctionne-vraiment.png" alt="Comment marchent Node.js et Angular" title="Comment marchent Node.js et Angular"></div></div></div></div></div><!----><!----></div><div id="element-16"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>Allons sur Wikipedia <a href="https://fr.wikipedia.org/wiki/Node.js">https://fr.wikipedia.org/wiki/Node.js</a><br>Testons le programme d'exemple <em>"un Hello Word"</em> qu'il nous propose.<br><br>Créez un fichier index.js avec un éditeur de code (bloc-notes fera l'affaire).<br>Copiez le code exemple suivant</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-17"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> hello.js </span></div><!----><div><app-prism-block ngh="1"><pre class="language-javascript" tabindex="0"><code class="language-javascript"><span class="token keyword">const</span> <span class="token punctuation">{</span> createServer <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'http'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Création du serveur</span>
<span class="token keyword">const</span> server <span class="token operator">=</span> <span class="token function">createServer</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">request<span class="token punctuation">,</span> response</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
response<span class="token punctuation">.</span><span class="token function">writeHead</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><span class="token string-property property">'Content-Type'</span><span class="token operator">:</span> <span class="token string">'text/plain'</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
response<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token string">'Hello World\n'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
server<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Adresse du serveur : http://localhost:3000</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-18"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4">Il ne reste plus qu'à procéder aux tests</div><!----></div></div></div><!----><!----><!----></div><div id="element-19"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> Test à éxécuter </span></div><!----><div><app-prism-block ngh="1"><pre class="language-git" tabindex="0"><code class="language-git"><span class="token comment"># Exécution du programme javascript</span>
node index.js
<span class="token comment"># Vérification dans le navigateur</span>
http://localhost:3000</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-20"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Installation de Visual studio code </h2><!----><div class="pt-4"><p><strong>Visual Studio Code </strong>est l'éditeur utilisé dans la plupart des conférences sur Angular.<br>Il est notamment utilisé par <strong>John Papa</strong> l'un des meilleurs conférenciers Angular et auteur des guides Angular<br><a href="https://github.com/johnpapa/angular-styleguide">https://github.com/johnpapa/angular-styleguide</a><br><br>Dans la suite du tutoriel nous utiliserons donc <strong>Visual Studio Code</strong>.<br><strong>VS code</strong> est un éditeur de code développé par Microsoft pour Windows, Linux et OS X.<br></p></div><!----></div></div></div><!----><!----><!----></div><div id="element-21"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>Procédons à l'installation.<br><br>Le site officiel est là <a href="https://code.visualstudio.com/">https://code.visualstudio.com/</a><br><br>Nous utiliserons la dernière version <strong>1.100.2 </strong>à télécharger ici<br><br><a href="https://code.visualstudio.com/updates/v1_100">https://code.visualstudio.com/updates/v1_100</a><br><br></p><p>L'installation est simple comme celle de Node.js.<br><br>Cliquez sur <strong>Download for Windows</strong><br>Téléchargez et exécutez <br></p></div><!----></div></div></div><!----><!----><!----></div><div id="element-22"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Installation de Git </h2><!----><div class="pt-4"><p>Ecrire une Application Web c'est un peu comme écrire un livre.<br>Plus le temps passe plus le <strong>nombre de pages</strong> augmentent.<br>De quelques centaines vous pouvez passer à des milliers de pages.<br>Le<strong> nombre de modifications </strong>devient considérable et pour s'y retrouver ce n'est pas une mince affaire.</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-23"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><p class="font-weight-bold"> Des questions, des questions, trop de questions </p><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/installation-git.png" alt="Git Angular et les versions" title="Git Angular et les versions"></div></div></div></div></div><!----><!----></div><div id="element-24"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>Pour gérer ce problème, des outils ont été développés.<br>Ce sont les <strong>logiciels de gestion de versions</strong> (ou <strong>VCS</strong> en anglais, pour version control system).<br><br>Le plus connu est <strong>Git</strong>. Il a été créé par <strong>Linus Torval </strong>le créateur de Linux.<br><br>Il va nous permettre de gérer notre code source et ses différentes versions.<br>Et surtout de pouvoir partager ce code source, permettant ainsi de travailler à plusieurs.<br><br>Git vous permettra aussi d'utiliser et de tester le code source de ce tutoriel.<br><br>Passons à l'installation.</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-25"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>Le site officiel est à l'adresse suivante <a href="https://git-scm.com/">https://git-scm.com/</a><br><br>L'installation est accessible ici <a href="https://git-scm.com/download/win">https://git-scm.com/download/win</a><br><br>Téléchargez l'application puis exécutez la.<br><br>Pour vérifier que Git est installé sur votre poste de travail il suffit de lancer une ligne de commande.</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-26"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> </span></div><!----><div><app-prism-block ngh="1"><pre class="language-git" tabindex="0"><code class="language-git"><span class="token comment"># Test de la version</span>
git --version
</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-27"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Installation d' Angular CLI </h2><!----><div class="pt-4"><p><strong>Angular CLI </strong>ça veut dire <strong>Angular </strong><strong>Command Line Interface.</strong><br>Mais c'est surtout ça.</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-28"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><p class="font-weight-bold"> L' homme à tout faire d'Angular </p><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/anguarl-cli-installation.png" alt="Angular CLI l'homme orchestre" title="Angular CLI l'homme orchestre"></div></div></div></div></div><!----><!----></div><div id="element-29"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>Et autant utiliser la version la plus récente.<br><br><strong>Angular</strong> version <strong>20.1.3</strong><br><strong>Angular CLI</strong> version <strong>20.1.3</strong><br><br>Les dernières versions de ces outils sont disponibles ci-dessous<br><a href="https://github.com/angular/angular/releases">https://github.com/angular/angular/releases</a><br><a href="https://github.com/angular/angular-cli/releases">https://github.com/angular/angular-cli/releases</a><br><br>La procédure d'installation est détaillée sur le site officiel d'Angular<br><br><a href="https://angular.dev/tools/cli/setup-local#dependencies">https://angular.dev/tools/cli/setup-local#dependencies</a><br><br>La méthode est décrite sur la page du site officiel.<br><br>Je vais détailler celle-ci.<br><br><em>- Si une version précédente était installée sur votre poste vous pouvez la désinstaller avec la commande suivante</em><br></p></div><!----></div></div></div><!----><!----><!----></div><div id="element-30"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> </span></div><!----><div><app-prism-block ngh="1"><pre class="language-git" tabindex="0"><code class="language-git"><span class="token comment"># Désinstallation d'angular-cli</span>
npm uninstall -g @angular/cli</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-31"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>Angular CLI est une librairie (ou package).<br>Nous allons l'installer avec npm le gestionnaire de node.js<br><br>Vous pouvez installer une version spécifique d'angular ou installer par défaut la dernière disponible.</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-32"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> </span></div><!----><div><app-prism-block ngh="1"><pre class="language-git" tabindex="0"><code class="language-git"><span class="token comment"># Installation d'angular-cli dernière version disponible</span>
npm install -g @angular/cli
<span class="token comment"># Installation d'angular-cli version spécifique</span>
npm install -g @angular/cli@20.1.3
<span class="token comment"># Test de version installée</span>
ng version</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-33"><!----><div class="container-fluid red-darken-1"><div class="container nga-container-tutorial"><div class="row d-flex justify-content-center"><div class="col-md-10"><div class="text-center text-white"><div class="h4 pt-4" id="true"> Etape 2</div><h2 class="pt-2 pb-2">Initialisation du projet avec Angular CLI</h2></div><hr class="nga-hr"><section><div class="row mt-3 mb-4"><div class="col-lg-7 col-md-12 nga-ellipsis"><div class="text-white"><p>Angular est un framework complet qui couvre un grand nombre de fonctionnalités.<br>La documentation est particulièrement fournie et détaillée.<br><br>Nous essaierons le plus souvent possible de respecter les meilleures pratiques (<strong>best practices</strong>) préconisées par l'équipe d'angular.</p><p><br>Nous pouvons créer manuellement chaque élément de notre application mais le plus simple est d'utiliser <strong>Angular CLI</strong></p></div></div><div class="col-lg-5 ml-auto col-md-12 mt-4 mb-5"><img class="z-depth-0 img-fluid" src="https://api.ganatan.com/tutorials/img/initialization-avec-angularcli.png" alt="Initialisation avec Angular CLI" title="Initialisation du projet avec Angular CLI"></div></div></section></div></div></div></div><!----><!----><!----><!----></div><div id="element-34"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Créer notre application avec Angular CLI </h2><!----><div class="pt-4"><p><br><strong>Angular CLI </strong>est un outil pour initialiser, développer et maintenir des applications Angular.<br><br>Le site officiel est ici <a href="https://angular.dev/cli">https://angular.dev/cli</a><br>Et si vous voulez avoir la liste des commandes Angular CLI<br><br><a href="https://github.com/angular/angular-cli/wiki">https://github.com/angular/angular-cli/wiki</a></p></div><!----></div></div></div><!----><!----><!----></div><div id="element-35"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/angularcli-site.png" alt="Le site Angular CLI" title="Le site Angular CLI"></div></div></div></div></div><!----><!----></div><div id="element-36"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>Pour aller plus vite je vous fais un résumé essentiel.<br><br>Angular CLI nous offre un certain nombre de commandes.<br>Ces commandes nous évitent d'effectuer des tâches répétitives.<br><br>La première commande que nous allons utiliser est <strong>ng new </strong>ou <strong>ng n</strong></p><ul><li>Elle va créer notre application.</li><li>Elle va générer tous les fichiers nécessaires à cette application.</li><li>Elle va évidemment suivre les best practices préconisées par l'équipe de Google.</li></ul><p><br>On choisit le nom de notre application (arbitrairement ce sera ici <strong>angular-starter</strong>)<br>On tape la commande ng new avec les paramètres correspondants<br><br>- On génère le projet (<em>cette partie prend quelques minutes</em>)</p><ul><li><em>Pour une compréhension plus simple nous gérerons le routing et le sass dans un autre tutoriel.</em></li><li><strong>Choisir le type CSS</strong> (valeur par défaut Yes)</li><li><strong>Désactiver le Server side Rendering</strong> (valeur par défaut Non)</li></ul><p>- On se positionne dans le projet<br>- On exécute le projet</p><p>Ce qui donne</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-37"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> </span></div><!----><div><app-prism-block ngh="1"><pre class="language-git" tabindex="0"><code class="language-git"><span class="token comment"># Générer un projet appelé angular-starter avec choix manuel des options</span>
ng new angular-starter
<span class="token comment"># Générer un projet appelé angular-starter avec options par défaut</span>
ng new angular-starter --defaults
<span class="token comment"># Se positionner dans le projet</span>
cd angular-starter
<span class="token comment"># Exécuter</span>
ng serve
<span class="token comment"># Exécuter et lancer automatiquement l'application dans le navigateur</span>
ng serve -o</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-38"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>Angular CLI via la commande <strong>ng serve </strong>execute le projet sur un port par défaut (4200).<br><br>Il ne reste qu'à tester le fonctionnement dans un navigateur en lançant l'url suivante.</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-39"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> </span></div><!----><div><app-prism-block ngh="1"><pre class="language-git" tabindex="0"><code class="language-git"><span class="token comment"># Tester</span>
http://localhost:4200</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-40"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Utiliser notre application avec Visual Studio Code </h2><!----><div class="pt-4"><p>Lancez <strong>VS Code</strong>.<br><br>Ouvrez un dossier dans le répertoire <strong>angular-starter </strong>que nous avons créé lors de l'initialisation.<br><br>Ouvrez ensuite le fichier <strong>package.json</strong>.<br>Celui-ci contient un certain nombre de commandes (ou scripts) que nous utiliserons tout au long de ce tutoriel.<br><br>Ouvrez une console VS code (sélectionnez Afficher/Terminal) pour exécuter les scripts suivants<br><br></p><ul><li><strong>npm run start</strong> : Exécute l'application en mode développement.</li><li><strong>npm run build</strong> : Compile l'application dans le répertoire<strong> dist.</strong></li><li><strong>npm run test</strong> : Exécute les tests unitaires en utilisant le framework <strong>Karma.</strong></li></ul><p>Remarque pour les nostalgiques des versions précédentes</p><p>La commande ng eject (permettant de générer la configuration webpack) a été désactivée.</p><p>Elle a été supprimée depuis la version 8</p><p>Projet exemple de gestion du format de configuration</p><p><br><a href="https://github.com/manfredsteyer/ngx-build-plus">https://github.com/manfredsteyer/ngx-build-plus</a><br><br></p><p>En mode développement si nous voulons personnaliser le port il suffit de modifier le script start dans le fichier package.json.<br><br>Par exemple pour utiliser le port 4201 le script serait le suivant "start": "<strong>ng serve --port 4201</strong>"</p><p>Nous laisserons le port 4200 modifiable à volonté pour la suite du tutoriel.</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-41"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> package.json </span></div><!----><div><app-prism-block ngh="1"><pre class="language-json" tabindex="0"><code class="language-json"> <span class="token property">"scripts"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"ng"</span><span class="token operator">:</span> <span class="token string">"ng"</span><span class="token punctuation">,</span>
<span class="token property">"start"</span><span class="token operator">:</span> <span class="token string">"ng serve --port 4200"</span><span class="token punctuation">,</span>
<span class="token property">"build"</span><span class="token operator">:</span> <span class="token string">"ng build"</span><span class="token punctuation">,</span>
<span class="token property">"watch"</span><span class="token operator">:</span> <span class="token string">"ng build --watch --configuration development"</span><span class="token punctuation">,</span>
<span class="token property">"test"</span><span class="token operator">:</span> <span class="token string">"ng test"</span>
<span class="token punctuation">}</span>
</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-42"><!----><div class="blue-gradient container-fluid"><div class="container nga-container-tutorial"><div class="row d-flex justify-content-center"><div class="col-md-10"><div class="text-center text-white"><div class="h4 pt-4" id="true"> Etape 3</div><h2 class="pt-2 pb-2">Mise à jour du package.json</h2></div><hr class="nga-hr"><section><div class="row mt-3 mb-4"><div class="col-lg-7 col-md-12 nga-ellipsis"><div class="text-white"><p>Node.js est la <strong>plateforme </strong>pour développer notre application.<br>Node.js est basée sur l'utilisation de librairies ou dépendances.<br><br>Npm est le gestionnaire des <strong>librairies </strong>(packages en anglais)<br><br>La mise à jour d'une application et donc de ses librairies est une question périlleuse.<br><br>Je vais vous montrer qu'avec Angular la notion de <strong>mise à jour</strong> des versions est essentielle.<br>Elle doit être menée avec prudence.</p></div></div><div class="col-lg-5 ml-auto col-md-12 mt-4 mb-5"><img class="z-depth-0 img-fluid" src="https://api.ganatan.com/tutorials/img/update.png" alt="Mise à jour du package.json" title="Mise à jour du package.json"></div></div></section></div></div></div></div><!----><!----><!----><!----></div><div id="element-43"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Update or not update </h2><!----><div class="pt-4"><p>Les<strong> librairies javascript</strong> sont constamment <strong>modifiées </strong>et <strong>mises à jour</strong> par leur concepteur.<br>Lorsqu'une nouvelle version est disponible elle porte le nom de <strong>release </strong>(sortie en anglais) et dispose d'un numéro spécifique.<br><br>Si la librairie est open-source vous pouvez voir les dernières versions disponibles en allant sur le dépôt correspondant sur Github puis allez sur Releases.<br><br>Par exemple les différentes versions d'Angular sont accessibles ici<br><a href="https://github.com/angular/angular/releases">https://github.com/angular/angular/releases</a><br><br>Le calendrier des mises à jour est ici<br><a href="https://angular.dev/reference/releases#versioning">https://angular.dev/reference/releases#versioning</a><br><br>Votre passé, votre présent et votre futur.</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-44"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/angular-releases.png" alt="Les releases Angular" title="Les releases Angular"></div></div></div></div></div><!----><!----></div><div id="element-45"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p><em>Remarquez que les versions 2 à 17 ne sont plus supportées.</em><br><br>Et le danger est évidemment que toutes ces mises à jour altèrent le fonctionnement de notre application.<br>Dans tous les cas on ne pourra y échapper il faudra un jour ou l'autre essayer de les intégrer dans nos projets.<br><br>Je vais vous expliquer comment je procède personnellement.</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-46"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><p class="font-weight-bold"> Je n'ai pas pensé aussi loin </p><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/update-or-not-update.png" alt="Les mises à jour Angular" title="Les mises à jour Angular"></div></div></div></div></div><!----><!----></div><div id="element-47"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Comment fait-on ? </h2><!----><div class="pt-4"><p>Utilisons npm (Node Package Manager) le gestionnaire de librairies de Node.js.</p><p><br>La documentation complète est <br>ici <a href="https://docs.npmjs.com/cli/outdated.html">https://docs.npmjs.com/cli/outdated.html</a><br><br></p><p>Deux commandes nous seront utiles<br><br></p><p>Vérifier les versions effectivement installées<br><br></p><ul><li>npm list --depht=0<br><br>Cette commande vérifie les dépendances effectivement installées dans le répertoire node_modules.<br>Elle nous fournit une liste que l'on peut renseigner dans package.json (voir Remarque)</li></ul><p><br>Vérifier les versions de nos librairies via la commande<br><br></p><ul><li>npm outdated<br><br>Cette commande vérifie le registre des dépendances pour vérifier si les packages installés sont à jour.<br>Elle nous fournit ainsi une liste que l'on peut contrôler.</li></ul><p><br>Remarque</p><p>Avant de vérifier les dépendances mettons à jour le fichier package.json en fonction des versions fournies</p><p>par la commande npm list</p><p><br>Pour chaque dépendance indiquée supprimez le caractère ~ ou ^</p><p><br>Par exemple remplacez</p><ul><li>"rxjs": "~7.8.0",</li><li>"tslib": "^2.3.0",</li></ul><p><br>par</p><strong><ul><li>"rxjs": "7.8.2",</li><li>"tslib": "2.8.1",</li></ul></strong><p><br>Pour éviter les erreurs éventuelles supprimer au préalable <br>le fichier <strong>package-lock.json</strong> et le répertoire <strong>node_modules</strong>.</p><p><br>Puis réinstallez les dépendances avec npm install (package-lock.json et node_modules sont alors recréés automatiquement).</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-48"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> </span></div><!----><div><app-prism-block ngh="1"><pre class="language-git" tabindex="0"><code class="language-git"><span class="token comment"># Vérification des versions des dépendances installées dans node_modules</span>
npm list --depth=0
<span class="token comment"># Vérification des dépendances disponibles</span>
npm outdated</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-49"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Résultats de la mise à jour ! </h2><!----><div class="pt-4"><p>Si je mets à jour le fichier package.json je me retrouve confronté à 3 cas de figure<br><br></p><ul><li>1/ Ca marche<br>C'est pas tous les jours la fête mais depuis Angular 8 c'est de plus en plus souvent<br><br></li><li>2/ Ca ne marche pas on essaie de debugger sans y passer trop de temps.<br>Ca dépend de votre patience et du temps que vous avez devant vous<br><br></li><li>3/ Ca marche pas et on attend.<br>Souvent (mais pas toujours) Angular résout votre problème avec la mise à jour suivante.<br>De toute façon ce n'est la peine d'attendre indéfiniment, il faudra bien trouver une solution.<br>Ou alors on se retrouve avec AngularJS en 2022 et là on n'est pas dans le pétrin.</li></ul></div><!----></div></div></div><!----><!----><!----></div><div id="element-50"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/resultats-des-courses.png" alt="Mise à jour angular : Résultat des courses" title="Mise à jour angular : Résultat des courses"></div></div></div></div></div><!----><!----></div><div id="element-51"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Notre prototype Angular </h2><!----><div class="pt-4"><p>L'idéal est d'avoir un prototype d'application qui contienne suffisamment de fonctionnalités.<br>Vous pouvez être à-peu-près sûr que la mise à jour pourra s'effectuer sur la plupart de vos applications.<br>Bien sûr ça ne vous épargnera pas d'optimiser votre CI/CD et de veiller à vos tests.<br></p></div><!----></div></div></div><!----><!----><!----></div><div id="element-52"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/un-prototype-angular.png" alt="Un prototype Angular" title="Un prototype Angular"></div></div></div></div></div><!----><!----></div><div id="element-53"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>En tout cas voici une liste des fonctionnalités essentielles à une application selon moi.</p><ul><li><strong>Routing</strong></li><li><strong>Lazy Loading</strong></li><li><strong>Bootstrap</strong></li><li><strong>Httpclient</strong></li><li><strong>SSR</strong></li><li><strong>PWA</strong></li><li><strong>SEO</strong></li><li><strong>Components</strong></li><li><strong>Services</strong></li><li><strong>Observables</strong></li><li><strong>Directives</strong></li><li><strong>Pagination</strong></li><li><strong>ScrollBox</strong></li><li><strong>Charts</strong></li><li><strong>Authentification (authentication/Route guard/Role guard/Jwt)</strong></li><li><strong>Ngrx</strong></li><li><strong>Reactiveform / Tempate Driven form</strong></li><li><strong>Form Modal</strong></li><li><strong>Internationalization</strong></li><li><strong>Tests (unit et end-to-end)</strong></li></ul><p>Le dépôt qui me sert pour l'instant de prototype est le suivant.<br><a href="https://github.com/ganatan/angular-app">https://github.com/ganatan/angular-app</a></p></div><!----></div></div></div><!----><!----><!----></div><div id="element-54"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Donc c'est parti pour la mise à jour </h2><!----><div class="pt-4"><p>Pour l'exemple nous allons utiliser cette méthode sur notre application angular-starter.<br><br>Le fichier package.json contient les différentes <strong>dépendances</strong> de votre projet.<br>Les dépendances sont en quelque sorte toutes les librairies que vous avez décidé d'utiliser dans votre projet.<br>Elles sont gérées par <strong>npm</strong> (node package manager) le gestionnaire de dépendances de <strong>Node.js</strong>.<br><br>Concernant les dépendances et leur version la documentation npm est la suivante<br><a href="https://docs.npmjs.com/files/package.json#dependencies">https://docs.npmjs.com/files/package.json#dependencies</a><br><br>Les spécificateurs de version sont nombreux.<br><br>Nous pouvons utiliser par exemple</p><ul><li><strong>version</strong> Doit correspondre à la version exactement</li><li><strong>~version</strong> "Approximativement équivalente à la version"</li><li><strong>^version</strong> “Compatible avec la version”</li></ul><p><br>Nous opterons quant à nous pour le premier spécificateur "<strong>version</strong>", qui est le plus simple, le plus explicite mais aussi le plus restrictif.<br><br>Nous allons mettre à jour le fichier package.json avec les dernières dépendances</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-55"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/update-packagejson.png" alt="Mise à jour du fichier Package.json pour Angular" title="Mise à jour du fichier Package.json pour Angular"></div></div></div></div></div><!----><!----></div><div id="element-56"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>- Pour contrôler les dépendances à mettre à jour lancez la commande</p><p>npm outdated</p><p>- Dans certains cas toutes les dépendances peuvent être mises à jour à l'exception de typescript</p><p>Angular 20.1.3 accepte par exemple TypeScript supérieur ou égal à 5.8.3</p><p>Vous pouvez le vérifier après la mise à jour en exécutant le script npm run build</p><p>- Dans le cas donc d'Angular 20.1.3 toutes les dépendances peuvent être mises.</p><p>- Supprimez le fichier package-lock.json et le répertoire node_modules</p><p>Modifiez le fichier package.json comme suit puis executez le script</p><p>npm install</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-57"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> package.json </span></div><!----><div><app-prism-block ngh="1"><pre class="language-json" tabindex="0"><code class="language-json"> <span class="token property">"dependencies"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"@angular/common"</span><span class="token operator">:</span> <span class="token string">"20.1.3"</span><span class="token punctuation">,</span>
<span class="token property">"@angular/compiler"</span><span class="token operator">:</span> <span class="token string">"20.1.3"</span><span class="token punctuation">,</span>
<span class="token property">"@angular/core"</span><span class="token operator">:</span> <span class="token string">"20.1.3"</span><span class="token punctuation">,</span>
<span class="token property">"@angular/forms"</span><span class="token operator">:</span> <span class="token string">"20.1.3"</span><span class="token punctuation">,</span>
<span class="token property">"@angular/platform-browser"</span><span class="token operator">:</span> <span class="token string">"20.1.3"</span><span class="token punctuation">,</span>
<span class="token property">"@angular/router"</span><span class="token operator">:</span> <span class="token string">"20.1.3"</span><span class="token punctuation">,</span>
<span class="token property">"express"</span><span class="token operator">:</span> <span class="token string">"5.1.0"</span><span class="token punctuation">,</span>
<span class="token property">"rxjs"</span><span class="token operator">:</span> <span class="token string">"7.8.2"</span><span class="token punctuation">,</span>
<span class="token property">"tslib"</span><span class="token operator">:</span> <span class="token string">"2.8.1"</span><span class="token punctuation">,</span>
<span class="token property">"zone.js"</span><span class="token operator">:</span> <span class="token string">"0.15.1"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">"devDependencies"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"@angular/build"</span><span class="token operator">:</span> <span class="token string">"20.1.3"</span><span class="token punctuation">,</span>
<span class="token property">"@angular/cli"</span><span class="token operator">:</span> <span class="token string">"20.1.3"</span><span class="token punctuation">,</span>
<span class="token property">"@angular/compiler-cli"</span><span class="token operator">:</span> <span class="token string">"20.1.3"</span><span class="token punctuation">,</span>
<span class="token property">"@types/jasmine"</span><span class="token operator">:</span> <span class="token string">"5.1.8"</span><span class="token punctuation">,</span>
<span class="token property">"angular-eslint"</span><span class="token operator">:</span> <span class="token string">"20.1.1"</span><span class="token punctuation">,</span>
<span class="token property">"eslint"</span><span class="token operator">:</span> <span class="token string">"9.32.0"</span><span class="token punctuation">,</span>
<span class="token property">"jasmine-core"</span><span class="token operator">:</span> <span class="token string">"5.9.0"</span><span class="token punctuation">,</span>
<span class="token property">"karma"</span><span class="token operator">:</span> <span class="token string">"6.4.4"</span><span class="token punctuation">,</span>
<span class="token property">"karma-chrome-launcher"</span><span class="token operator">:</span> <span class="token string">"3.2.0"</span><span class="token punctuation">,</span>
<span class="token property">"karma-coverage"</span><span class="token operator">:</span> <span class="token string">"2.2.1"</span><span class="token punctuation">,</span>
<span class="token property">"karma-jasmine"</span><span class="token operator">:</span> <span class="token string">"5.1.0"</span><span class="token punctuation">,</span>
<span class="token property">"karma-jasmine-html-reporter"</span><span class="token operator">:</span> <span class="token string">"2.1.0"</span><span class="token punctuation">,</span>
<span class="token property">"typescript"</span><span class="token operator">:</span> <span class="token string">"5.8.3"</span><span class="token punctuation">,</span>
<span class="token property">"typescript-eslint"</span><span class="token operator">:</span> <span class="token string">"8.38.0"</span>
<span class="token punctuation">}</span></code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-58"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>Il suffit alors de tester tous les scripts pour vérifier que les mises à jour ont fonctionné.</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-59"><!----><div class="container-fluid green-lighten-1"><div class="container nga-container-tutorial"><div class="row d-flex justify-content-center"><div class="col-md-10"><div class="text-center text-white"><div class="h4 pt-4" id="true"> Etape 4</div><h2 class="pt-2 pb-2">Tests et déploiement</h2></div><hr class="nga-hr"><section><div class="row mt-3 mb-4"><div class="col-lg-7 col-md-12 nga-ellipsis"><div class="text-white"><p>Le développement est entré dans sa phase d'industrialisation.<br><br>Au même titre que les autres industries la qualité et la quantité doivent être au rendez-vous.</p><p><br>Des méthodes <strong>Agile </strong>ont été inventées pour cela.<br><br></p><p>Les <strong>tests </strong>en font partie intégrante.</p><p><br>Nous allons voir que les concepteurs d'Angular ont tout prévu.</p><p>Enfin nous déploierons notre application via plusieurs méthodes.</p></div></div><div class="col-lg-5 ml-auto col-md-12 mt-4 mb-5"><img class="z-depth-0 img-fluid" src="https://api.ganatan.com/tutorials/img/test-unit-endtoend.png" alt="Tests unitaires et end-to-end avec Angular" title="Tests et déploiement"></div></div></section></div></div></div></div><!----><!----><!----><!----></div><div id="element-60"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Les Tests : Le secret de mon succès </h2><!----><div class="pt-4"><p>Créer une application Web c'est comme créer n'importe quel objet.<br>On crée une voiture, une télévision ou un avion par exemple.<br>Et avant de le donner à quelqu'un on va tester son fonctionnement.<br><br>Les informaticiens se sont dit autant que ce soit simple et automatique.<br>Comme toujours c'est plus facile à dire qu'à faire.<br></p></div><!----></div></div></div><!----><!----><!----></div><div id="element-61"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/tests-faciles-difficiles.png" alt="Angular et les tests : facile ou difficile" title="Angular et les tests : facile ou difficile"></div></div></div></div></div><!----><!----></div><div id="element-62"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Un peu d'histoire avant de commencer </h2><!----><div class="pt-4"><p>Depuis ces débuts le monde informatique a cherché à s'améliorer.<br>Plusieurs méthodes de travail ont été adoptées.<br>En simplifiant on pourrait dire qu'on en est là<br><br>Méthode <strong>Cycle en V</strong> contre méthode <strong>Agile</strong>.<br></p></div><!----></div></div></div><!----><!----><!----></div><div id="element-63"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><p class="font-weight-bold"> La plus rapide est-elle vraiment celle qu'on croit ? </p><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/methodes-de-travail.png" alt="Angular et Cycle en V versus Agile" title="Angular et Cycle en V versus Agile"></div></div></div></div></div><!----><!----></div><div id="element-64"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Mais qui a fait quoi ? </h2><!----><div class="pt-4"><p>Si vous voulez travailler dans la programmation c'est sûr il va falloir <strong>se montrer agile</strong>.<br>La méthode Agile la plus utilisée actuellement est la <strong>méthode Scrum</strong>.<br><br>Ci dessous un petit historique des vingt dernières années.</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-65"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/tests-unitaires-origine.png" alt="Origine de la méthode Agile" title="Origine de la méthode Agile"></div></div></div></div></div><!----><!----></div><div id="element-66"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>En Novembre 2009 <strong>Mike Cohn</strong> décrit la <strong>pyramide des tests</strong> (<strong>The test pyramide</strong> en anglais) dans son livre<br><em>Succeeding with Agile: Software Development Using Scrum</em><br><br>Avec Angular nous nous intéresserons à une catégorie.</p><ul><li>Les test unitaires</li></ul><p><br>Faisons un survol en image de l'architecture d'Angular pour visualiser les tests.</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-67"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/tests-unitaires-angular.png" alt="Architecture Angular et Tests unitaires" title="Architecture Angular et Tests unitaires"></div></div></div></div></div><!----><!----></div><div id="element-68"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Les tests avec Angular </h2><!----><div class="pt-4"><p>Sans rentrer dans les détails Angular nous simplifie la vie avec les outils suivants.<br><br>Les tests unitaires utilisent</p><ul><li><strong>Karma</strong></li><li><strong>Jasmine</strong></li></ul><p>Les tests end-to-end utilisaient</p><ul><li><strong>Protractor</strong></li></ul><p>Remarque : Depuis angular 12 les tests end-to-end ont été désactivés.<br><br>La documentation Angular concernant la notion de couverture est accessible à cette adresse <a href="https://angular.dev/guide/testing/code-coverage">https://angular.dev/guide/testing/code-coverage</a><br>Je rajoute dans <strong>package.json</strong> un script supplémentaire pour tester la couverture<br><br> "<strong>coverage</strong>": "ng test --no-watch --code-coverage",<br><br>Pour les lancer on utilise les scripts correspondants contenus dans le fichier Package.json</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-69"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> </span></div><!----><div><app-prism-block ngh="1"><pre class="language-git" tabindex="0"><code class="language-git"><span class="token comment"># Tests unitaires</span>
npm run test
<span class="token comment"># Tests unitaires avec couverture</span>
npm run coverage</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-70"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Modifier et vérifier </h2><!----><div class="pt-4"><p>Effectuons<br><br>- Un test simple modification et de débuggage<br>- Un test de contrôle de code source.<br>- Débuggage.<br><br>Toute modification entraine une recompilation du code.<br><br>Par exemple Modifier le fichier app.component.html</p><p>Congratulations and Modifications! Your app is running.<br><br></p><p>La compilation est alors exécutée automatiquement et le navigateur se réactualise.<br><br>Remarque :<br>Le fichier favicon.ico représente l'icône de votre application.<br>Vous pouvez le personnaliser.<br>Dans cet exemple vous pouvez récupérer celui de ce dépôt.</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-71"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> </span></div><!----><div><app-prism-block ngh="1"><pre class="language-git" tabindex="0"><code class="language-git"><span class="token comment"># Executer</span>
npm run start
<span class="token comment"># Tester</span>
http://localhost:4200/
<span class="token comment"># Effectuer des modifications</span>
</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-72"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Vérification du code </h2><!----><div class="pt-4"><p>En tant qu'informaticien on essaiera de se simplifier la vie.<br>Autant avoir de l'aide pour écrire notre code.<br><br>L'un des outils utilisés est le linting qui permet d'améliorer la qualité du code.<br><br>Angular utilisait l’outil <strong>TSLint </strong>accessible à <br>cette adresse <a href="https://palantir.github.io/tslint/">https://palantir.github.io/tslint/</a><br><br>Remarque<br>Cette commande a été désactivée à partir d'Angular 12.<br>On attend le prochain outil préconisé par angular (probablement ESLint ?).<br><br><em>Comme l'équipe de Google ne s'est pas décidé nous intégrerons ESLint dans notre projet.</em><br><br>Pour cela nous utiliserons Schematics qui est un générateur de code Angular basé sur des templates de base.<br><br>La commande ng lint exécute l’analyse statique du code source TypeScript.<br><br></p></div><!----></div></div></div><!----><!----><!----></div><div id="element-73"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> </span></div><!----><div><app-prism-block ngh="1"><pre class="language-git" tabindex="0"><code class="language-git"><span class="token comment"># Installation via schematics</span>
ng add @angular-eslint/schematics
<span class="token comment"># Répondre oui à la question</span>
The package @angular-eslint/schematics@19.6.0 will be installed and executed.
<span class="token comment"># Test du code source</span>
npm run lint
</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-74"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>Schematics a rajouté un script dans le fichier<strong> package.json (lint)</strong><br>et a créé un fichier<strong> eslint.config.js</strong><br><br>Pour vérifier que notre linter fonctionne</p><p>Rajoutons des règles spécifiques dans le fichier <strong> eslint.config.js</strong><br><br>Remarque modifiez cette propriété</p><ul><li>"no-var": "<strong>error</strong>"<br>une erreur sera signalisée sur l'utilisation de <strong>var</strong></li><li>"no-var": "<strong>off</strong>"<br>Aucune erreur ne sera signalisée sur l'utilisation de <strong>var</strong></li></ul><p><br>Pour vérifier le comportement du linter.<br><br>Modifions un fichier par exemple <strong>app.component.ts</strong><br>Et écrivons du code qui ne correspond pas aux règles<br><br>On teste avec le script <em>npm run lint </em>qui donnera une erreur<br><br><strong>Unexpected var, use let or const instead no-var</strong></p></div><!----></div></div></div><!----><!----><!----></div><div id="element-75"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> eslint.config.js </span></div><!----><div><app-prism-block ngh="1"><pre class="language-json" tabindex="0"><code class="language-json"> rules<span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"@angular-eslint/directive-selector"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
<span class="token string">"error"</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
type<span class="token operator">:</span> <span class="token string">"attribute"</span><span class="token punctuation">,</span>
prefix<span class="token operator">:</span> <span class="token string">"app"</span><span class="token punctuation">,</span>
style<span class="token operator">:</span> <span class="token string">"camelCase"</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"@angular-eslint/component-selector"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
<span class="token string">"error"</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
type<span class="token operator">:</span> <span class="token string">"element"</span><span class="token punctuation">,</span>
prefix<span class="token operator">:</span> <span class="token string">"app"</span><span class="token punctuation">,</span>
style<span class="token operator">:</span> <span class="token string">"kebab-case"</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"@angular-eslint/component-class-suffix"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
<span class="token string">"error"</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
suffixes<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">""</span><span class="token punctuation">,</span> <span class="token string">"Component"</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"semi"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"error"</span><span class="token punctuation">,</span> <span class="token string">"always"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"comma-dangle"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"error"</span><span class="token punctuation">,</span> <span class="token string">"always-multiline"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"no-undefined"</span><span class="token operator">:</span> <span class="token string">"error"</span><span class="token punctuation">,</span>
<span class="token property">"no-var"</span><span class="token operator">:</span> <span class="token string">"error"</span><span class="token punctuation">,</span>
<span class="token property">"prefer-const"</span><span class="token operator">:</span> <span class="token string">"error"</span><span class="token punctuation">,</span>
<span class="token property">"func-names"</span><span class="token operator">:</span> <span class="token string">"error"</span><span class="token punctuation">,</span>
<span class="token property">"id-length"</span><span class="token operator">:</span> <span class="token string">"error"</span><span class="token punctuation">,</span>
<span class="token property">"newline-before-return"</span><span class="token operator">:</span> <span class="token string">"error"</span><span class="token punctuation">,</span>
<span class="token property">"space-before-blocks"</span><span class="token operator">:</span> <span class="token string">"error"</span><span class="token punctuation">,</span>
<span class="token property">"no-alert"</span><span class="token operator">:</span> <span class="token string">"error"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-76"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> app.ts </span></div><!----><div><app-prism-block ngh="1"><pre class="language-typescript" tabindex="0"><code class="language-typescript"><span class="token keyword">import</span> <span class="token punctuation">{</span> Component <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@angular/core'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> RouterOutlet <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@angular/router'</span><span class="token punctuation">;</span>
<span class="token decorator"><span class="token at operator">@</span><span class="token function">Component</span></span><span class="token punctuation">(</span><span class="token punctuation">{</span>
selector<span class="token operator">:</span> <span class="token string">'app-root'</span><span class="token punctuation">,</span>
imports<span class="token operator">:</span> <span class="token punctuation">[</span>RouterOutlet<span class="token punctuation">]</span><span class="token punctuation">,</span>
templateUrl<span class="token operator">:</span> <span class="token string">'./app.html'</span><span class="token punctuation">,</span>
styleUrl<span class="token operator">:</span> <span class="token string">'./app.css'</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token punctuation">{</span>
<span class="token keyword">protected</span> title <span class="token operator">=</span> <span class="token string">'angular-starter'</span><span class="token punctuation">;</span>
<span class="token function">checkError</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">var</span> err <span class="token operator">=</span> <span class="token number">10</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> err<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-77"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/tslint-test.png" alt="Tests angular avec TSLint" title="Tests angular avec TSLint"></div></div></div></div></div><!----><!----></div><div id="element-78"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Environment </h2><!----><div class="pt-4"><p>L'équipe Angular a décidé de ne plus intégrer automatiquement <strong>les paramètres d'environnement (environment en anglais).</strong><br>Les nouveaux développeurs moins portés sur les problèmes de configuration n'utilisaient pas ces paramètres.<br><br>La documentation Angular est accessible à cette adresse<br><a href="https://angular.dev/tools/cli/environments#configure-environment-specific-defaults">https://angular.dev/tools/cli/environments#configure-environment-specific-defaults</a><br><br>La commande est la suivante <strong>ng generate environments</strong><br><br>Les éléments nécessaires à son fonctionnement sont créés automatiquement.</p><ul><li>Création d'un répertoire <strong>src/environments</strong></li><li>Création d'un fichier<strong> environment.development.ts</strong></li><li>Création d'un fichier un fichier<strong> environment.ts</strong></li><li>Modification du fichier<strong> angular.json</strong></li></ul></div><!----></div></div></div><!----><!----><!----></div><div id="element-79"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> environment.development.ts </span></div><!----><div><app-prism-block ngh="1"><pre class="language-typescript" tabindex="0"><code class="language-typescript"><span class="token keyword">export</span> <span class="token keyword">const</span> environment <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-80"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> environment.ts </span></div><!----><div><app-prism-block ngh="1"><pre class="language-typescript" tabindex="0"><code class="language-typescript"><span class="token keyword">export</span> <span class="token keyword">const</span> environment <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-81"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> angular.json </span></div><!----><div><app-prism-block ngh="1"><pre class="language-json" tabindex="0"><code class="language-json"> <span class="token property">"configurations"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"production"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"budgets"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
<span class="token punctuation">{</span>
<span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"initial"</span><span class="token punctuation">,</span>
<span class="token property">"maximumWarning"</span><span class="token operator">:</span> <span class="token string">"500kB"</span><span class="token punctuation">,</span>
<span class="token property">"maximumError"</span><span class="token operator">:</span> <span class="token string">"1MB"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
<span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"anyComponentStyle"</span><span class="token punctuation">,</span>
<span class="token property">"maximumWarning"</span><span class="token operator">:</span> <span class="token string">"4kB"</span><span class="token punctuation">,</span>
<span class="token property">"maximumError"</span><span class="token operator">:</span> <span class="token string">"8kB"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"outputHashing"</span><span class="token operator">:</span> <span class="token string">"all"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">"development"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"optimization"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
<span class="token property">"extractLicenses"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
<span class="token property">"sourceMap"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
<span class="token property">"fileReplacements"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
<span class="token punctuation">{</span>
<span class="token property">"replace"</span><span class="token operator">:</span> <span class="token string">"src/environments/environment.ts"</span><span class="token punctuation">,</span>
<span class="token property">"with"</span><span class="token operator">:</span> <span class="token string">"src/environments/environment.development.ts"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-82"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Déploiement </h2><!----><div class="pt-4"><p>Tout ce que nous avons fait est bien sympathique.<br>Mais une application Web n'a d'intérêt que si nous la rendons accessible sur le Web.<br>C'est ce que l'on appelle le <strong>déploiement</strong>.<br>Nous allons voir comment le faire via deux méthodes de<strong> la plus simple </strong>à <strong>la plus compliquée.</strong><br><br>Mais tout d'abord parlons <strong>compilation</strong>.<br><br>Comme nous l'avons vu précédemment le fichier package.json contient un certain nombre de scripts (ou commandes).<br><br>Le script qui nous intéresse est <strong>npm run build</strong><br>Il permet de compiler notre application.<br><br>Ce script exécute la commande d'Angular CLI <strong>ng Build</strong><br><br></p><p>Sans rentrer dans les détails voilà comment ça fonctionne.</p><p>Via cette commande Angular utilise l'outil Webpack (un module bundler) pour créer le produit final.</p><p>L'exécution de cette commande va créer un répertoire dist.</p><p>Celui-ci contiendra ce que l'on peut appeler le produit final (ou livrable ou artefact).</p><p>C'est cette partie que l'on va déployer.</p><p>Les conseils donnés par Angular sont à l'adresse suivante<br><a href="https://angular.dev/tools/cli/deployment">https://angular.dev/tools/cli/deployment</a></p></div><!----></div></div></div><!----><!----><!----></div><div id="element-83"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Déploiement avec lite-server </h2><!----><div class="pt-4"><p>Le déploiement le plus simple est d'utiliser le serveur Http développé par John Papa.<br>Comment procéder ?</p><ul><li>On installe la librairie lite-server en global avec npm</li><li>On exécute l'application en mode production</li></ul></div><!----></div></div></div><!----><!----><!----></div><div id="element-84"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> </span></div><!----><div><app-prism-block ngh="1"><pre class="language-git" tabindex="0"><code class="language-git"><span class="token comment"># Compilation du projet !!!!!!!! Très important à ne pas oublier</span>
npm run build
<span class="token comment"># Installation du serveur de développement lite-server</span>
npm install -g lite-server
<span class="token comment"># Exécution de notre application</span>
lite-server --baseDir=<span class="token string">"dist/angular-starter/browser"</span>
<span class="token comment"># Tester l'application dans notre navigateur avec l'url suivante</span>
http://localhost:3000/</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-85"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Deploiement avec nginx </h2><!----><div class="pt-4"><p>Une solution plus complexe mais plus proche de la réalité.<br>Il nous faudra disposer d'un serveur virtuel ou VPS (Virtual private server).<br><br>Je vous conseille d'en acheter un chez un fournisseur de VPS.<br>Par exemple <strong>OVH </strong>ou <strong>Digital Ocean</strong> sont parmi les moins chers et les plus efficaces.<br><br>Le tutoriel suivant peut vous être utiles<br><br><a href="https://www.ganatan.com/tutorials/angular-sur-ubuntu">Installer Angular sur un serveur Ubuntu</a></p><br></div><!----></div></div></div><!----><!----><!----></div><div id="element-86"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>Sur notre serveur (exemple d'un serveur avec ubuntu et l'adresse ip 192.168.100.1)<br><br></p><ul><li>Installer nginx</li><li>Tester nginx</li><li>Copier notre répertoire dist sur /var/www/html</li><li>Tester le serveur</li></ul></div><!----></div></div></div><!----><!----><!----></div><div id="element-87"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> </span></div><!----><div><app-prism-block ngh="1"><pre class="language-git" tabindex="0"><code class="language-git"><span class="token comment"># connection sur le serveur en ssh</span>
ssh root@192.168.100.1
<span class="token comment"># installation de nginx sur le serveur</span>
sudo apt-get --yes install nginx
sudo apt-get update
<span class="token comment"># Démarre le service nginx</span>
sudo service nginx start
<span class="token comment"># Tester l'installation du serveur nginx</span>
http://localhost:192.168.100.1/
<span class="token comment"># Copier le contenu du répertoire dist/angular-starter/browser</span>
<span class="token comment"># sur le serveur dans le répertoire /var/www/html/</span>
<span class="token comment"># Tester l'application</span>
http://localhost:192.168.100.1/
</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-88"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Paramètrage de nginx </h2><!----><div class="pt-4"><p>Je vous rajoute deux fichiers qui vous seront utiles<br><br></p><ul><li>un exemple d'un fichier de configuration <strong>nginx.conf</strong><br></li><li>un exemple de fichier javascript <strong>server.js </strong>pour lancer en local votre application<br>A utiliser avec la commande <strong>node server.js</strong><br>Le script suivant est à rajouter dans package.json<br> <strong> "serve": "node server.js"</strong></li></ul></div><!----></div></div></div><!----><!----><!----></div><div id="element-89"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> fichier nginx.conf </span></div><!----><div><app-prism-block ngh="1"><pre class="language-nginx" tabindex="0"><code class="language-nginx"><span class="token directive"><span class="token keyword">user</span> www-data</span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">worker_processes</span> auto</span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">pid</span> /run/nginx.pid</span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">error_log</span> /var/log/nginx/error.log</span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">include</span> /etc/nginx/modules-enabled/*.conf</span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">events</span></span> <span class="token punctuation">{</span>
<span class="token directive"><span class="token keyword">worker_connections</span> <span class="token number">768</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token directive"><span class="token keyword">http</span></span> <span class="token punctuation">{</span>
<span class="token directive"><span class="token keyword">sendfile</span> <span class="token boolean">on</span></span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">tcp_nopush</span> <span class="token boolean">on</span></span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">types_hash_max_size</span> <span class="token number">2048</span></span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">include</span> /etc/nginx/mime.types</span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">default_type</span> application/octet-stream</span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">ssl_protocols</span> TLSv1 TLSv1.1 TLSv1.2 TLSv1.3</span><span class="token punctuation">;</span> <span class="token comment"># Dropping SSLv3, ref: POODLE</span>
<span class="token directive"><span class="token keyword">ssl_prefer_server_ciphers</span> <span class="token boolean">on</span></span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">access_log</span> /var/log/nginx/access.log</span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">gzip</span> <span class="token boolean">on</span></span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">include</span> /etc/nginx/conf.d/*.conf</span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">server</span></span> <span class="token punctuation">{</span>
<span class="token directive"><span class="token keyword">listen</span> <span class="token number">80</span> default_server</span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">listen</span> [::]:80 default_server</span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">root</span> /var/www/html</span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">index</span> index.html index.htm index.nginx-debian.html</span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">server_name</span> _</span><span class="token punctuation">;</span>
<span class="token directive"><span class="token keyword">location</span> /</span> <span class="token punctuation">{</span>
<span class="token directive"><span class="token keyword">try_files</span> <span class="token variable">$uri</span> <span class="token variable">$uri</span>/ =404</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-90"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> server.js </span></div><!----><div><app-prism-block ngh="1"><pre class="language-javascript" tabindex="0"><code class="language-javascript"><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> path <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">static</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'dist/angular-starter/browser'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/*'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
res<span class="token punctuation">.</span><span class="token function">sendFile</span><span class="token punctuation">(</span>path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'dist/angular-starter/browser'</span><span class="token punctuation">,</span> <span class="token string">'index.html'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> port <span class="token operator">=</span> <span class="token number">4000</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> host <span class="token operator">=</span> <span class="token string">'localhost'</span><span class="token punctuation">;</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span>port<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Server running at http://</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>host<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">:</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>port<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-91"><!----><div class="container-fluid grey-darken-1"><div class="container nga-container-tutorial"><div class="row d-flex justify-content-center"><div class="col-md-10"><div class="text-center text-white"><div class="h4 pt-4" id="true"> Etape 5</div><h2 class="pt-2 pb-2">Notre Code Source Angular</h2></div><hr class="nga-hr"><section><div class="row mt-3 mb-4"><div class="col-lg-7 col-md-12 nga-ellipsis"><div class="text-white"><p>Ce guide nous a permis de créer une application Web prête à fonctionner.<br><br>Pour vous simplifier la tâche vous pouvez utiliser directement le code source de cette application, pour la tester et vérifier qu'elle fonctionne.<br><br>Pour cela il suffit d'utiliser<strong> le logiciel Git</strong>.<br>Je vais vous montrer comment procéder.<br><br>Cette première application reste néanmoins basique.<br>Je vous proposerai pour terminer un certain nombre d'étapes qui vous permettront de créer une application plus complexe.</p></div></div><div class="col-lg-5 ml-auto col-md-12 mt-4 mb-5"><img class="z-depth-0 img-fluid" src="https://api.ganatan.com/tutorials/img/code-source.png" alt="Notre Code Source Angular" title="Notre Code Source Angular"></div></div></section></div></div></div></div><!----><!----><!----><!----></div><div id="element-92"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Utiliser Git avec le code source </h2><!----><div class="pt-4"><p>En suivant chacun des conseils que je vous ai donnés dans ce guide vous obtenez au final un code source Angular.<br>Ce code représente votre travail et doit faire l'objet de toute votre attention.</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-93"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>Comme nous l'avons vu précédemment, <strong>Git </strong>va nous permettre de gérer tous nos codes sources.<br><br>Un petit tour sur Wikipedia <a href="https://en.wikipedia.org/wiki/GitHub">https://en.wikipedia.org/wiki/GitHub</a> nous apprend que <br><strong>GitHub est </strong>le plus grand hébergeur de code source au monde.<br><br>En janvier 2023 on compte</p><ul><li>100 millions d'utilisateurs </li><li>Plus de 420 millions de dépôts (ou <strong>repositories </strong>en anglais)</li></ul><p>Je vous conseille donc de publier vos sources sur cet hébergeur.<br><br>Le <strong>code source </strong>de ce tutoriel est bien évidemment disponible sur GitHub.<br>Utilisez git pour récupérer ce code et vérifier son fonctionnement.<br><br>Il vous suffit de vous rendre à l'adresse suivante<br><a href="https://github.com/ganatan/angular-starter">https://github.com/ganatan/angular-starter</a><br><br><em>Si ce guide vous a plu et que vous allez sur GitHub pour consulter le code, n'hésitez pas à cliquer sur STAR .</em></p></div><!----></div></div></div><!----><!----><!----></div><div id="element-94"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/github-star.png" alt="Star sur Github et Angular" title="Star sur Github et Angular"></div></div></div></div></div><!----><!----></div><div id="element-95"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><!----><!----><div class="pt-4"><p>Sinon pour aller plus vite encore suivez les conseils suivants.<br><br>Utilisez la commande classique de<strong> prompt</strong> sous windows (cmd) ou linux.<br>Puis tapez la liste des commandes</p></div><!----></div></div></div><!----><!----><!----></div><div id="element-96"><!----><!----><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><div class="nga-blue-text d-flex justify-content-center"><span class="nga-text-code"> </span></div><!----><div><app-prism-block ngh="1"><pre class="language-git" tabindex="0"><code class="language-git"><span class="token comment"># Créez un répertoire demo (le nom est ici arbitraire)</span>
mkdir demo
<span class="token comment"># Allez dans ce répertoire</span>
cd demo
<span class="token comment"># Récupérez le code source sur votre poste de travail</span>
git clone https://github.com/ganatan/angular-react-starter.git
<span class="token comment"># Allez dans le répertoire qui a été créé</span>
cd angular-react-starter
cd frontend-angular
<span class="token comment"># Exécutez l'installation des dépendances (ou librairies)</span>
npm install
<span class="token comment"># Exécutez le programme</span>
npm run start
<span class="token comment"># Vérifiez son fonctionnement en lançant dans votre navigateur la commande</span>
http://localhost:4200/
</code></pre></app-prism-block></div></div></div></div><!----></div><div id="element-97"><!----><!----><div class="container nga-container-tutorial"><div class="row mb-2"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto nga-ellipsis"><hr><!----><h2 class="h2 nga-blue-text text-center" id> Pour aller plus loin </h2><!----><div class="pt-4"><p><br>Ce tutoriel nous a permis de créer notre première application.<br>Celle-ci reste relativement simple.</p><p><br>Si vous voulez créer une application plus complète, il vous faudra mettre en œuvre certains principes et fonctionnalités supplémentaires comme<br><br></p><ul><li>Le <strong>Routing </strong>(gestion de plusieurs pages)</li><li>Le <strong>Lazy loading</strong> (rapidité de l'application)</li><li>Les<strong> PWA</strong> (fonctionnement sur mobile et desktop)</li><li>Le <strong>Server Side Rendering</strong> (permettre le référencement)</li></ul><p><br><strong>L' étape suivante est logiquement la gestion du Routing.</strong><br>Elle nécessite un tutoriel complet qui est à l'adresse suivante</p><ul><li><a href="https://www.ganatan.com/tutorials/routing-avec-angular">Etape 2 : Routing avec Angular</a></li></ul><p><br>Les étapes suivantes vous permettront <strong>d'obtenir une application prototype.</strong></p><ul><li><a href="https://www.ganatan.com/tutorials/lazy-loading-avec-angular">Etape 3 : Lazy loading avec Angular</a><br><br></li><li><a href="https://www.ganatan.com/tutorials/bootstrap-avec-angular">Etape 4 : Bootstrap avec Angular</a><br><br></li><li><a href="https://www.ganatan.com/tutorials/modules-avec-angular">Etape 5 : Modules avec Angular</a><br><br></li><li><a href="https://www.ganatan.com/tutorials/server-side-rendering-avec-angular-universal">Etape 6 : Server Side Rendering avec angular</a><br><br></li><li><a href="https://www.ganatan.com/tutorials/progressive-web-app-avec-angular">Etape 7 : Progressive Web App avec Angular</a><br><br></li><li><a href="https://www.ganatan.com/tutorials/search-engine-optimization-avec-angular">Etape 8 : Search Engine Optimization avec Angular</a><br><br></li><li><a href="https://www.ganatan.com/tutorials/httpclient-avec-angular">Etape 9 : HttpClient avec Angular</a><br><a href="https://www.ganatan.com/tutorials/transfer-state-avec-angular"></a></li></ul><p>Les étapes suivantes vous permettront d'améliorer ce prototype</p><ul><li><a href="https://www.ganatan.com/tutorials/components-avec-angular">Components avec Angular</a><br><br></li><li><a href="https://www.ganatan.com/tutorials/services-avec-angular">Services avec Angular</a><br><br></li><li><a href="https://www.ganatan.com/tutorials/template-driven-forms-avec-angular">Template Driven Forms avec Angular</a></li><li><a href="https://www.ganatan.com/tutorials/charts-avec-angular">Charts avec Angular</a></li></ul><p><strong></strong><br>Cette dernière étape permet <strong>d'obtenir un exemple d'application </strong></p><ul><li><a href="https://www.ganatan.com/tutorials/creer-application-web-complete-avec-angular">Créer une application Web complète avec Angular</a></li></ul><p><br>Le <strong>code source de cette application finale </strong>est disponible sur GitHub<br><a href="https://github.com/ganatan/angular-node-java-ai">https://github.com/ganatan/angular-node-java-ai</a></p></div><!----></div></div></div><!----><!----><!----></div><div id="element-98"><!----><!----><!----><div class="container nga-container-tutorial"><div class="row pt-4 mb-4"><div class="col-sm-12 col-md-9 col-xl-9 col-lg-9 mx-auto"><div class="text-center"><p class="font-weight-bold"> The end </p><!----><div class="text-center"><img class="img-fluid" style="cursor: pointer;" src="https://api.ganatan.com/tutorials/img/cest-fini.png" alt="Angular c'est fini pour le moment" title="Angular c'est fini pour le moment"></div></div></div></div></div><!----><!----></div><div id="element-99"><!----><!----><!----><!----><!----></div><!----><!----><div id="element-0"><!----></div><div id="element-1"><!----></div><div id="element-2"><!----></div><div id="element-3"><!----></div><div id="element-4"><!----></div><div id="element-5"><!----></div><div id="element-6"><!----></div><div id="element-7"><!----></div><div id="element-8"><!----></div><div id="element-9"><!----></div><div id="element-10"><!----></div><div id="element-11"><!----></div><div id="element-12"><!----></div><div id="element-13"><!----></div><div id="element-14"><!----></div><div id="element-15"><!----></div><div id="element-16"><!----></div><div id="element-17"><!----></div><div id="element-18"><!----></div><div id="element-19"><!----></div><div id="element-20"><!----></div><div id="element-21"><!----></div><div id="element-22"><!----></div><div id="element-23"><!----></div><div id="element-24"><!----></div><div id="element-25"><!----></div><div id="element-26"><!----></div><div id="element-27"><!----></div><div id="element-28"><!----></div><div id="element-29"><!----></div><div id="element-30"><!----></div><div id="element-31"><!----></div><div id="element-32"><!----></div><div id="element-33"><!----></div><div id="element-34"><!----></div><div id="element-35"><!----></div><div id="element-36"><!----></div><div id="element-37"><!----></div><div id="element-38"><!----></div><div id="element-39"><!----></div><div id="element-40"><!----></div><div id="element-41"><!----></div><div id="element-42"><!----></div><div id="element-43"><!----></div><div id="element-44"><!----></div><div id="element-45"><!----></div><div id="element-46"><!----></div><div id="element-47"><!----></div><div id="element-48"><!----></div><div id="element-49"><!----></div><div id="element-50"><!----></div><div id="element-51"><!----></div><div id="element-52"><!----></div><div id="element-53"><!----></div><div id="element-54"><!----></div><div id="element-55"><!----></div><div id="element-56"><!----></div><div id="element-57"><!----></div><div id="element-58"><!----></div><div id="element-59"><!----></div><div id="element-60"><!----></div><div id="element-61"><!----></div><div id="element-62"><!----></div><div id="element-63"><!----></div><div id="element-64"><!----></div><div id="element-65"><!----></div><div id="element-66"><!----></div><div id="element-67"><!----></div><div id="element-68"><!----></div><div id="element-69"><!----></div><div id="element-70"><!----></div><div id="element-71"><!----></div><div id="element-72"><!----></div><div id="element-73"><!----></div><div id="element-74"><!----></div><div id="element-75"><!----></div><div id="element-76"><!----></div><div id="element-77"><!----></div><div id="element-78"><!----></div><div id="element-79"><!----></div><div id="element-80"><!----></div><div id="element-81"><!----></div><div id="element-82"><!----></div><div id="element-83"><!----></div><div id="element-84"><!----></div><div id="element-85"><!----></div><div id="element-86"><!----></div><div id="element-87"><!----></div><div id="element-88"><!----></div><div id="element-89"><!----></div><div id="element-90"><!----></div><div id="element-91"><!----></div><div id="element-92"><!----></div><div id="element-93"><!----></div><div id="element-94"><!----></div><div id="element-95"><!----></div><div id="element-96"><!----></div><div id="element-97"><!----></div><div id="element-98"><!----></div><div id="element-99"><div class="container-fluid blue-gradient pt-4 pb-4"><div class="container pt-4 pb-4"><div class="row d-flex justify-content-center"><div class="col-md-8"><div class="card p-4"><h2 class="h3 pb-2 text-center textguide"> Comment créer une application From scratch ? </h2><div class="row"><div class="col-lg-8 col-md-12 pb-4"><h3 class="h6 title pt-4 text-center"> Créez votre compte ganatan </h3><div class="mb-4 title pt-1 text-center"><h3 class="h6">Téléchargez gratuitement vos guides complets</h3><h4 class="h6 pt-3 textguide">Démarrez avec angular CLI <img width="28" height="28" alt="Démarrez avec angular CLI" src="https://api.ganatan.com/tutorials/img/logo-pdf.png"></h4><h4 class="h6 textguide">Gérez le routing <img width="28" height="28" alt="Gérez le routing" src="https://api.ganatan.com/tutorials/img/logo-pdf.png"></h4><h4 class="h6 textguide">Appliquez le Lazy loading <img width="28" height="28" alt="Appliquez le Lazy loading" src="https://api.ganatan.com/tutorials/img/logo-pdf.png"></h4><h4 class="h6 textguide">Intégrez Bootstrap <img width="28" height="28" alt="Intégrez Bootstrap" src="https://api.ganatan.com/tutorials/img/logo-pdf.png"></h4><hr><h4 class="h6 textguide">Utilisez Python avec Angular <img width="28" height="28" alt="Utilisez Python avec Angular" src="https://api.ganatan.com/tutorials/img/logo-pdf.png"></h4><h4 class="h6 textguide">Utilisez Django avec Angular <img width="28" height="28" alt="Utilisez Django avec Angular" src="https://api.ganatan.com/tutorials/img/logo-pdf.png"></h4><h4 class="h6 textguide">Utilisez Flask avec Angular <img width="28" height="28" alt="Utilisez Flask avec Angular" src="https://api.ganatan.com/tutorials/img/logo-pdf.png"></h4></div><div class="text-center w-responsive mx-auto"><a class="btn nga-btn-guide" href="/signup" jsaction="click:;"> JE CREE MON COMPTE ET JE TELECHARGE MES GUIDES<i class="d-none d-xl-inline-block fas fas fa-download mx-2"></i></a></div></div><div class="col-lg-4 ml-auto col-md-12 pb-4"><img alt="Ganatan site Web avec Angular" class="z-depth-0 img-fluid" src="https://api.ganatan.com/tutorials/img/quest-ce-que-ganatan.png"></div></div></div></div><div class="col-md-4"><section class="section widget-content mb-4"><div class="card card-body pb-0"><div class="single-post"><p class="font-weight-bold dark-grey-text text-center spacing grey lighten-4 py-2 mb-4"><strong>Tutoriels Backend</strong></p><div class="row mb-4"><div class="col-4"><div class="view overlay z-depth-1"><a href="/tutorials/python-avec-angular" jsaction="click:;"><img class="img-fluid z-depth-1 rounded-0" src="https://api.ganatan.com/tutorials/img/tutorial-python-avec-angular-thumb.png" alt="Python avec angular"></a></div></div><div class="col-8"><h4 class="h6 mt-0 font-small"><a class="text-hover font-weight-bold" href="/tutorials/python-avec-angular" jsaction="click:;">Python avec angular</a></h4></div></div><div class="row mb-4"><div class="col-4"><div class="view overlay z-depth-1"><a href="/tutorials/django-avec-angular" jsaction="click:;"><img class="img-fluid z-depth-1 rounded-0" src="https://api.ganatan.com/tutorials/img/tutorial-django-avec-angular-thumb.png" alt="Django avec angular"></a></div></div><div class="col-8"><h4 class="h6 mt-0 font-small"><a class="text-hover font-weight-bold" href="/tutorials/django-avec-angular" jsaction="click:;">Django avec angular</a></h4></div></div><div class="row mb-4"><div class="col-4"><div class="view overlay z-depth-1"><a href="/tutorials/flask-avec-angular" jsaction="click:;"><img class="img-fluid z-depth-1 rounded-0" src="https://api.ganatan.com/tutorials/img/tutorial-flask-avec-angular-thumb.png" alt="Flask avec angular"></a></div></div><div class="col-8"><h4 class="h6 mt-0 font-small"><a class="text-hover font-weight-bold" href="/tutorials/flask-avec-angular" jsaction="click:;">Flask avec angular</a></h4></div></div><!----></div><div class="single-post"><p class="font-weight-bold dark-grey-text text-center spacing grey lighten-4 py-2 mb-4"><strong>Tutoriels Frontend</strong></p><div class="row mb-4"><div class="col-4"><div class="view overlay z-depth-1"><a href="/tutorials/demarrer-avec-react" jsaction="click:;"><img class="img-fluid z-depth-1 rounded-0" src="https://api.ganatan.com/tutorials/img/tutorial-demarrer-avec-react-thumb.png" alt="Démarrer avec React"></a></div></div><div class="col-8"><h4 class="h6 mt-0 font-small"><a class="text-hover font-weight-bold" href="/tutorials/demarrer-avec-react" jsaction="click:;">Démarrer avec React</a></h4></div></div><div class="row mb-4"><div class="col-4"><div class="view overlay z-depth-1"><a href="/tutorials/routing-avec-react" jsaction="click:;"><img class="img-fluid z-depth-1 rounded-0" src="https://api.ganatan.com/tutorials/img/tutorial-routing-avec-react-thumb.png" alt="Routing avec React"></a></div></div><div class="col-8"><h4 class="h6 mt-0 font-small"><a class="text-hover font-weight-bold" href="/tutorials/routing-avec-react" jsaction="click:;">Routing avec React</a></h4></div></div><!----></div><!----></div></section></div></div></div></div><!----></div><!----></div><app-modal-ebook _nghost-ng-c429373045 ngh="2"><div _ngcontent-ng-c429373045 id="modalEbook" tabindex="-1" aria-labelledby="modalEbook" aria-hidden="true" class="modal fade"><div _ngcontent-ng-c429373045 class="modal-dialog modal-lg"><div _ngcontent-ng-c429373045 class="modal-content"><div _ngcontent-ng-c429373045 class="modal-header pt-4 pb-4 border-bottom-0"><button _ngcontent-ng-c429373045 type="button" data-bs-dismiss="modal" aria-label="Close" class="btn-close" jsaction="click:;"></button></div><div _ngcontent-ng-c429373045 class="modal-body p-5 pt-0"><div _ngcontent-ng-c429373045 class="text-center" style="font-size: 20px;"><p _ngcontent-ng-c429373045>Entrez votre email pour recevoir </p><p _ngcontent-ng-c429373045 class="h2 pt-1 pb-4"><strong _ngcontent-ng-c429373045>"Démarrer une Application Web avec Angular" </strong></p><div _ngcontent-ng-c429373045 class="row d-flex justify-content-center"><div _ngcontent-ng-c429373045 class="col-md-8"><div _ngcontent-ng-c429373045 class="md-form"><input _ngcontent-ng-c429373045 type="email" id="emailebook" class="form-control ng-untouched ng-pristine ng-valid" value jsaction="input:;blur:;compositionstart:;compositionend:;"></div><div _ngcontent-ng-c429373045 class="nga-edit-error pt-4 pb-4" style="font-size: 22px;"><strong _ngcontent-ng-c429373045>Veuillez entrez votre adresse email</strong></div></div></div><div _ngcontent-ng-c429373045 class="row d-flex justify-content-center"><div _ngcontent-ng-c429373045 class="col-md-8"><button _ngcontent-ng-c429373045 type="button" class="btn nga-btn-guide" jsaction="click:;"><!----><span _ngcontent-ng-c429373045 class="text-white mx-4">Je reçois mon Guide</span></button></div></div><div _ngcontent-ng-c429373045 class="row d-flex justify-content-center"><div _ngcontent-ng-c429373045 class="col-md-10"><br _ngcontent-ng-c429373045><p _ngcontent-ng-c429373045 class="nga-text-guide" style="font-size: 13px;"><strong _ngcontent-ng-c429373045> Vous pouvez vous désinscrire en 1 clic depuis n'importe lequel de mes emails</strong></p></div></div></div></div></div></div></div></app-modal-ebook></app-item><!----></main><app-footer _nghost-ng-c4014730536 ngh="4"><footer _ngcontent-ng-c4014730536 class="nga-footer"><div _ngcontent-ng-c4014730536 class="nga-hint"></div><div _ngcontent-ng-c4014730536 class="container py-5 text-center text-lg-start"><div _ngcontent-ng-c4014730536 class="row"><div _ngcontent-ng-c4014730536 class="col-12 col-lg-5 mb-3"><h2 _ngcontent-ng-c4014730536 class="h5"><img _ngcontent-ng-c4014730536 width="25" height="25" class="mb-1 me-1" src="https://api.ganatan.com/assets/img/ganatan-logo.png" srcset="https://api.ganatan.com/assets/img/ganatan-logo.png, https://api.ganatan.com/assets/img/ganatan-logo@2x.png 2x" alt="Logo Ganatan"> Ganatan </h2><hr _ngcontent-ng-c4014730536 class="text-white mb-4 mt-0 d-inline-block" style="width: 120px;"><p _ngcontent-ng-c4014730536>Application Web : Angular 21, Bootstrap 5</p><!----><!----><p _ngcontent-ng-c4014730536>Lazy Loading, SSR, PWA, SEO</p><a _ngcontent-ng-c4014730536 type="button" class="nga-btn-social nga-btn-github" href="https://github.com/ganatan" aria-label="Github Ganatan"><i _ngcontent-ng-c4014730536 class="fab fa-github"></i></a><a _ngcontent-ng-c4014730536 type="button" class="nga-btn-social nga-btn-linkedin" href="https://www.linkedin.com/in/dannyganatan/" aria-label="Linkedin Ganatan"><i _ngcontent-ng-c4014730536 class="fab fa-linkedin-in"></i></a><a _ngcontent-ng-c4014730536 role="button" aria-label="YouTube Ganatan" class="nga-btn-social nga-btn-youtube" href="https://www.youtube.com/@ganatan"><i _ngcontent-ng-c4014730536 class="fa-brands fa-youtube"></i></a><!----></div><div _ngcontent-ng-c4014730536 class="col-6 col-lg-3 mb-3"><h2 _ngcontent-ng-c4014730536 class="h5">Outils</h2><!----><!----><hr _ngcontent-ng-c4014730536 class="text-white mt-0 d-inline-block" style="width: 70px;"><ul _ngcontent-ng-c4014730536 class="list-unstyled"><li _ngcontent-ng-c4014730536 class="mb-2"><a _ngcontent-ng-c4014730536 href="https://angular.io/" class="nga-footer-link">Angular</a></li><li _ngcontent-ng-c4014730536 class="mb-2"><a _ngcontent-ng-c4014730536 href="https://getbootstrap.com/" class="nga-footer-link">Bootstrap</a></li><li _ngcontent-ng-c4014730536 class="mb-2"><a _ngcontent-ng-c4014730536 href="https://nodejs.org/en/" class="nga-footer-link">Node.js</a></li><li _ngcontent-ng-c4014730536 class="mb-2"><a _ngcontent-ng-c4014730536 href="https://www.postgresql.org/" class="nga-footer-link">PostgreSQL</a></li></ul></div><div _ngcontent-ng-c4014730536 class="col-6 col-lg-3 mb-3"><h2 _ngcontent-ng-c4014730536 class="h5">Apprendre</h2><!----><!----><hr _ngcontent-ng-c4014730536 class="text-white mt-0 d-inline-block" style="width: 70px;"><ul _ngcontent-ng-c4014730536 class="list-unstyled"><li _ngcontent-ng-c4014730536 class="mb-2"><a _ngcontent-ng-c4014730536 class="nga-footer-link" href="https://www.ganatan.com/tutorials">Tutoriels</a></li><!----><!----><li _ngcontent-ng-c4014730536 class="mb-2"><a _ngcontent-ng-c4014730536 class="nga-footer-link" href="https://www.ganatan.com/about">A propos</a></li><!----><!----></ul></div></div></div><div _ngcontent-ng-c4014730536 class="nga-footer-bottom py-3 text-center"><div _ngcontent-ng-c4014730536 class="container"><a _ngcontent-ng-c4014730536 class="nga-footer-link-bottom" href="https://www.ganatan.com">https://www.ganatan.com</a></div></div></footer></app-footer></app-root>
<noscript>Please enable JavaScript to continue using this application.</noscript>
<link rel="modulepreload" href="chunk-UXVU3F7Z.js"><link rel="modulepreload" href="chunk-VUAOLVD5.js"><link rel="modulepreload" href="chunk-SQ4QVZ4K.js"><link rel="modulepreload" href="chunk-4BVLIMKH.js"><link rel="modulepreload" href="chunk-EJG4AXY2.js"><link rel="modulepreload" href="chunk-SZCTIGTC.js"><link rel="modulepreload" href="chunk-3BMA26TX.js"><script src="polyfills-5CFQRCPP.js" type="module"></script><script src="scripts-TTWY4XDY.js" defer></script><script src="main-IW4LCEEE.js" type="module"></script>
<link rel="modulepreload" href="chunk-FLO6KH6R.js">
<link rel="modulepreload" href="chunk-4EQB6F2J.js">
<link rel="modulepreload" href="chunk-AHDVGANS.js">
<script id="ng-state" type="application/json">{"2394830388":{"b":{"id":1007,"code":"0001","title":"Démarrer une Application Web avec Angular","name":"demarrer-avec-angular","langueid":1,"releaseDate":"23/12/2025","shared":false,"facebook":true,"twitter":true,"linkedin":true,"tutorialformation":false,"tutorialemailing":false,"guide":true,"description":"Un guide complet pour créer un projet Angular, comprenant l'installation, la configuration, \nla gestion de l'environnement, du déploiement et des tests.\nCode source fourni en exemple.","canonical":"demarrer-avec-angular","descriptionshort":"Introduction rapide et pratique pour démarrer un projet Angular facilement.","alternate":"demarrer-avec-angular","alternatelang":"getting-started-with-angular","ogurl":"demarrer-avec-angular","ogtitle":"Démarrer avec Angular | Tutoriel Complet pour Débutants","oglocale":"","ogimagewidth":"","ogimageheight":"","ogimagealt":"","ogdeterminer":"","oglocalealternate":"","ogarticlepublishedtime":"","ogarticlemodifiedtime":"","ogarticleexpirationtime":"","ogarticleauthor":"","ogarticlesection":"","ogarticletag":"","ogarticlepublisher":"","twitterimagealt":"","twitterplayer":"","twitterplayerwidth":"","twitterplayerheight":"","twitterappnameiphone":"","twitterappidiphone":"","twitterappnameipad":"","twitterappidipad":"","twitterappnamegoogleplay":"","twitterappidgoogleplay":"","twittertitle":"","ogimage":"","twitterimage":"","ogdescription":"","ogtype":"","ogsitename":"","ogvideo":"","ogaudio":"","twittercard":"","twittersite":"","twittercreator":"","twitterdescription":"","elements":[{"name":"introduction","title":"Démarrer une Application Web avec Angular","linkable":true,"intro":{"src":"https://api.ganatan.com/tutorials/img/demarrer-avec-angular-intro.png","alt":"Démarrer avec Angular","title":"Démarrer avec Angular","color":"blue-gradient","content":"\u003Cp>Nous allons réaliser une \u003Cstrong>Application Web.\u003C/strong>\u003Cbr>\u003Cbr>Dans ce tutoriel, nous utiliserons \u003Cstrong>Angular version 21.0.6\u003C/strong>\u003Cbr>\u003Cbr>Pour commencer notre application nous partirons de zéro (\u003Cstrong>from scratch\u003C/strong>) en nous efforçant de suivre les meilleures pratiques (\u003Cstrong>best practices) \u003C/strong>d'Angular.\u003Cbr>\u003Cbr>\u003C/p>\u003Cul>\u003Cli>Angular a été créé par \u003Cstrong>Google\u003C/strong>.\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>Angular est \u003Cstrong>open source\u003C/strong>, son utilisation est donc gratuite.\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>Angular utilise \u003Cstrong>Typescript\u003C/strong>.\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>Angular est un framework \u003Cstrong>Javascript Frontend\u003C/strong>.\u003C/li>\u003C/ul>"},"guide":{"src":"https://api.ganatan.com/tutorials/img/demarrer-avec-angular-guide.png","alt":"Téléchargez le guide Démarrer avec Angular","title":"Téléchargez le guide Démarrer avec Angular"}},{"name":"how01","title":"Comment le faire ?","linkable":true,"text":{"content":"\u003Cp>Pour débuter notre projet voici un résumé de ce que nous allons faire.\u003Cbr>\u003Cbr>\u003C/p>\u003Cul>\u003Cli>\u003Cstrong>Installation des outils nécessaires\u003C/strong>\u003Cbr>\u003Cbr>\u003Cstrong>Node.js\u003C/strong> sera notre plateforme de développement javascript.\u003Cbr>Pas le choix, sans Node.js ça ne marchera pas.\u003Cbr>\u003Cbr>\u003Cstrong>Visual studio Code\u003C/strong> sera notre éditeur de code.\u003Cbr>Le choix est totalement arbitraire mais pour un outil Microsoft c'est une petite merveille\u003Cbr>\u003Cbr>\u003Cstrong>Git \u003C/strong>sera notre gestionnaire de logiciel.\u003Cbr>Grâce à lui vous pourrez utiliser le code source de ce tutoriel.\u003Cbr>\u003Cbr>\u003Cstrong>Angular CLI \u003C/strong>sera notre homme à tout faire.\u003Cbr>Sans doute l'outil le plus connu et le plus utilisé du Framework Angular.\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Cstrong>Initialisation du projet\u003C/strong>\u003Cbr>Nous utiliserons Angular CLI pour la mise en place de l'architecture du projet,\u003Cbr>en utilisant les meilleures pratiques (best practices) préconisées par Google.\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Cstrong>Mise à jour du projet\u003C/strong>\u003Cbr>Vérifier les dépendances utilisées et les mettre à jour.\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Cstrong>Effectuer les Tests\u003C/strong>\u003Cbr>Les tests Unitaires et les outils qui leur sont dédiés Karma et Jasmine.\u003Cbr>Le linting et l' amélioration du code avec ESLint.\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Cstrong>Environment\u003C/strong>\u003Cbr>Depuis la version 15 l'équipe d'Angular n'intègre plus les paramètres d'environnement (environment en anglais).\u003Cbr>Très utiles nous verrons comment les déclarer et les utiliser.\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Cstrong>Déploiement\u003C/strong>\u003Cbr>Comment déployer votre application sur internet.\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Cstrong>Code source\u003C/strong>\u003Cbr>Le code complet du projet est disponible sur Github.\u003Cbr>\u003Cbr>\u003C/li>\u003C/ul>\u003Cbr>"}},{"name":"resume01","title":"Une image vaut mille mots","linkable":true,"text":{"content":"\u003Cp>Le résumé en image de ce que nous allons faire\u003Cbr>\u003C/p>"}},{"name":"resume02","title":"Résumé en images","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/resume-en-images.png","alt":"Creer une application web avec Angular résumé en image","title":"Creer une application web avec Angular résumé en image","libelle":""}},{"name":"resume03","title":"resume03","linkable":false,"text":{"content":"\u003Cp>Si vous êtes du genre très pressé ci-dessous un résumé en commandes sinon passez à l'étape suivante.\u003C/p>"}},{"code":{"language":"git","filename":"Commandes à éxécuter","filesize":0,"content":"# Désinstallez Angular CLI (au cas ou une ancienne version d'Angular aurait été installée)\nnpm uninstall -g @angular/cli\n\n# Installez Angular CLI version spécifique (la dernière si possible)\nnpm install -g @angular/cli@21.0.6\n\n# Créez un répertoire demo (le nom est ici arbitraire)\nmkdir demo\n\n# Allez dans ce répertoire\ncd demo\n\n# Générez un projet appelé angular-starter avec choix manuel des options\n# Sélectionnez les options par défaut\nng new angular-starter\n\n# Positionnez vous dans le projet\ncd angular-starter\n\n# Exécutez l'application\nnpm run start\n\n# Testez l'application dans votre navigateur\nhttp://localhost:4200"},"name":"resume04","title":"resume04","linkable":true},{"name":"getting-started01","title":"Et si vous êtes moins pressé ça va commencer","linkable":true,"text":{"content":"\u003Cp>On va faire les choses sérieusement mais on ne va pas se prendre au sérieux.\u003Cbr>Donc c'est parti pour \u003Cstrong>un peu d'humour\u003C/strong> et \u003Cstrong>beaucoup de technique.\u003C/strong>\u003C/p>"}},{"name":"getting-started02","title":"getting-started02","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/ca-va-commencer.png","alt":"Angular ça va fonctionner","title":"Angular ça va fonctionner","libelle":"sans IA"}},{"name":"getting-started03","title":"getting-started03","linkable":true,"image":{"src":"https://api.ganatan.com/tutorials/img/avec-ia.png","alt":"avec IA","title":"avec IA","libelle":"avec IA"}},{"name":"installation-outils","title":"Installation des outils nécessaires","linkable":true,"chapter":{"src":"https://api.ganatan.com/tutorials/img/installation-outils.png","alt":"Installation des outils nécessaires pour Angular","title":"Installation des outils nécessaires pour Angular","step":"Etape 1","color":"blue-gradient2","content":"\u003Cp>Avant d'utiliser Angular il nous faut installer un certain nombre de logiciels\u003Cbr>\u003Cbr>\u003C/p>\u003Cul>\u003Cli>\u003Cstrong>Node.js\u003C/strong>\u003Cbr>Impossible de faire fonctionner Angular sans lui.\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Cstrong>Visual Studio Code\u003C/strong>\u003Cbr>Ce choix est arbitraire.\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Cstrong>Git\u003C/strong>\u003Cbr>Très utile mais pas essentiel\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Cstrong>Angular CLI\u003C/strong>\u003Cbr>C'est l'homme à tout faire d'Angular\u003C/li>\u003C/ul>"}},{"name":"installation-nodejs01","title":"Installation de Node.js","linkable":true,"text":{"content":"\u003Cp>\u003Cstrong>Si vous ne l'installez pas, Angular ne fonctionnera pas.\u003C/strong>\u003Cbr>\u003Cbr>A ce propos Angular, React et Vuejs ont besoin tous trois de Node.js.\u003Cbr>\u003Cbr>Le site officiel c'est ici \u003Ca href=\"https://nodejs.org/en\">https://nodejs.org/en\u003C/a> \u003Cbr>\u003Cbr>Voilà ce qu'il nous dit:\u003Cbr>\u003Cstrong>Node.js est un environnement d’exécution JavaScript construit sur le moteur JavaScript V8 de Chrome.\u003C/strong>\u003Cbr>\u003Cbr>Son inventeur Ryan Lienhart Dahl l'a créé le 27 mai 2009.\u003Cbr>Il avait une idée précise derrière la tête : \u003Cem>la simplicité et la rapidité d'exécution de programmes écrits en javascript\u003C/em>.\u003Cbr>\u003Cbr>Le choix du nom n'est donc pas anodin.\u003Cbr>\u003Cbr>\u003C/p>\u003Cul>\u003Cli>\u003Cstrong>Node \u003C/strong>signifie \u003Cstrong>noeud\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>JS \u003C/strong>signifie \u003Cstrong>javascript\u003C/strong>\u003C/li>\u003C/ul>\u003Cp>Node.js est ainsi le \u003Cstrong>point central \u003C/strong>qui va permettre d'\u003Cstrong>exécuter des programmes écrits\u003C/strong> en javascript \u003Cstrong>côté serveur.\u003C/strong>\u003C/p>"}},{"name":"installation-nodejs02","title":"Element Title 00013","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/nodejs-fonctionne.png","alt":"Node.js et Angular","title":"Node.js et Angular","libelle":"Mon Dieu ! C'est plein d'étoiles !"}},{"name":"installation-nodejs03","title":"Element Title 00014","linkable":false,"text":{"content":"\u003Cp>Node.js utilise un outil \u003Cstrong>npm \u003C/strong>(Node Package Manager)\u003Cbr>Npm simplifie la vie du développeur en permettant de publier et de partager des librairies Node.js.\u003Cbr>Npm permet notamment de simplifier l'installation, la mise à jour ou la désinstallation de ces librairies.\u003Cbr>\u003Cbr>On pourra parler de librairies, de paquets ou de dépendances (en anglais packages ou dependencies).\u003Cbr>\u003Cbr>Comment l'installer ?\u003Cbr>\u003Cbr>Sur le site officiel le téléchargement est accessible à l'adresse\u003Cbr>\u003Ca href=\"https://nodejs.org/en\">https://nodejs.org/en\u003C/a>\u003Cbr>\u003Cbr>Nous allons utiliser la version\u003Cstrong> LTS\u003C/strong> (\u003Cstrong>Long Term Support\u003C/strong> ou Support à long terme).\u003Cbr>LTS signifie que l'éditeur nous garantit en général une période de maintenance d'au moins deux ans,\u003Cbr>\u003Cbr>\u003C/p>\u003Cul>\u003Cli>\u003Cstrong>Node.js\u003C/strong> version 24.12.0 LTS\u003C/li>\u003Cli>\u003Cstrong>npm\u003C/strong> (node package manager) version 11.4.1\u003C/li>\u003C/ul>\u003Cp>Il s'agit d'une installation classique.\u003Cbr>\u003Cbr>\u003C/p>\u003Cul>\u003Cli>Sélectionnez \u003Cstrong>Download Node.js (LTS)\u003C/strong>.\u003C/li>\u003Cli>Téléchargez le programme et éxécutez le.\u003C/li>\u003C/ul>\u003Cp>Une fois l'installation effectuée on peut vérifier que Node.js est installé sur notre poste de travail.\u003C/p>"}},{"code":{"language":"git","filename":"Commandes à éxécuter","filesize":0,"content":"# Vérification de la version de Node.js et de npm (méthode 1)\nnode --version\nnpm --version\n\n# Vérification de la version de Node.js et de npm (méthode 2)\nnode -v\nnpm -v\n\n# Mise à jour de npm\nnpm install npm -g\n\n# Vérification de la mise à jour de npm\nnpm -v"},"name":"installation-nodejs04","title":"Element Title 00015","linkable":true},{"name":"installation-nodejs05","title":"Comment savoir que Node.js fonctionne ?","linkable":true,"text":{"content":"On va vérifier que Node.js fonctionne et qu'il permet d'exécuter un programme javascript."}},{"name":"installation-nodejs06","title":"installation-nodejs06","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/nodejs-fonctionne-vraiment.png","alt":"Comment marchent Node.js et Angular","title":"Comment marchent Node.js et Angular","libelle":""}},{"name":"installation-nodejs07","title":"installation-nodejs07","linkable":false,"text":{"content":"\u003Cp>Allons sur Wikipedia \u003Ca href=\"https://fr.wikipedia.org/wiki/Node.js\">https://fr.wikipedia.org/wiki/Node.js\u003C/a>\u003Cbr>Testons le programme d'exemple \u003Cem>\"un Hello Word\"\u003C/em> qu'il nous propose.\u003Cbr>\u003Cbr>Créez un fichier index.js avec un éditeur de code (bloc-notes fera l'affaire).\u003Cbr>Copiez le code exemple suivant\u003C/p>"}},{"code":{"language":"javascript","filename":"hello.js","filesize":0,"content":"const { createServer } = require('http');\n\n// Création du serveur\nconst server = createServer((request, response) => {\n response.writeHead(200, {'Content-Type': 'text/plain'});\n response.end('Hello World\\n');\n});\n\nserver.listen(3000, () => console.log(`Adresse du serveur : http://localhost:3000`));"},"name":"installation-nodejs08","title":"Element Title 00019","linkable":false},{"name":"installation-nodejs09","title":"installation-nodejs09","linkable":false,"text":{"content":"Il ne reste plus qu'à procéder aux tests"}},{"code":{"language":"git","filename":"Test à éxécuter","filesize":0,"content":"# Exécution du programme javascript\nnode index.js\n\n# Vérification dans le navigateur\nhttp://localhost:3000"},"name":"installation-nodejs10","title":"installation-nodejs10","linkable":true},{"name":"installation-vscode01","title":"Installation de Visual studio code","linkable":true,"text":{"content":"\u003Cp>\u003Cstrong>Visual Studio Code \u003C/strong>est l'éditeur utilisé dans la plupart des conférences sur Angular.\u003Cbr>Il est notamment utilisé par \u003Cstrong>John Papa\u003C/strong> l'un des meilleurs conférenciers Angular et auteur des guides Angular\u003Cbr>\u003Ca href=\"https://github.com/johnpapa/angular-styleguide\">https://github.com/johnpapa/angular-styleguide\u003C/a>\u003Cbr>\u003Cbr>Dans la suite du tutoriel nous utiliserons donc \u003Cstrong>Visual Studio Code\u003C/strong>.\u003Cbr>\u003Cstrong>VS code\u003C/strong> est un éditeur de code développé par Microsoft pour Windows, Linux et OS X.\u003Cbr>\u003C/p>"}},{"name":"installation-vscode02","title":"installation-vscode02","linkable":false,"text":{"content":"\u003Cp>Procédons à l'installation.\u003Cbr>\u003Cbr>Le site officiel est là \u003Ca href=\"https://code.visualstudio.com/\">https://code.visualstudio.com/\u003C/a>\u003Cbr>\u003Cbr>Nous utiliserons la dernière version \u003Cstrong>1.100.2 \u003C/strong>à télécharger ici\u003Cbr>\u003Cbr>\u003Ca href=\"https://code.visualstudio.com/updates/v1_100\">https://code.visualstudio.com/updates/v1_100\u003C/a>\u003Cbr>\u003Cbr>\u003C/p>\u003Cp>L'installation est simple comme celle de Node.js.\u003Cbr>\u003Cbr>Cliquez sur \u003Cstrong>Download for Windows\u003C/strong>\u003Cbr>Téléchargez et exécutez \u003Cbr>\u003C/p>"}},{"name":"installation-git01","title":"Installation de Git","linkable":true,"text":{"content":"\u003Cp>Ecrire une Application Web c'est un peu comme écrire un livre.\u003Cbr>Plus le temps passe plus le \u003Cstrong>nombre de pages\u003C/strong> augmentent.\u003Cbr>De quelques centaines vous pouvez passer à des milliers de pages.\u003Cbr>Le\u003Cstrong> nombre de modifications \u003C/strong>devient considérable et pour s'y retrouver ce n'est pas une mince affaire.\u003C/p>"}},{"name":"installation-git02","title":"installation-git02","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/installation-git.png","alt":"Git Angular et les versions","title":"Git Angular et les versions","libelle":"Des questions, des questions, trop de questions"}},{"name":"installation-git03","title":"installation-git03","linkable":false,"text":{"content":"\u003Cp>Pour gérer ce problème, des outils ont été développés.\u003Cbr>Ce sont les \u003Cstrong>logiciels de gestion de versions\u003C/strong> (ou \u003Cstrong>VCS\u003C/strong> en anglais, pour version control system).\u003Cbr>\u003Cbr>Le plus connu est \u003Cstrong>Git\u003C/strong>. Il a été créé par \u003Cstrong>Linus Torval \u003C/strong>le créateur de Linux.\u003Cbr>\u003Cbr>Il va nous permettre de gérer notre code source et ses différentes versions.\u003Cbr>Et surtout de pouvoir partager ce code source, permettant ainsi de travailler à plusieurs.\u003Cbr>\u003Cbr>Git vous permettra aussi d'utiliser et de tester le code source de ce tutoriel.\u003Cbr>\u003Cbr>Passons à l'installation.\u003C/p>"}},{"name":"installation-git04","title":"installation-git04","linkable":false,"text":{"content":"\u003Cp>Le site officiel est à l'adresse suivante \u003Ca href=\"https://git-scm.com/\">https://git-scm.com/\u003C/a>\u003Cbr>\u003Cbr>L'installation est accessible ici \u003Ca href=\"https://git-scm.com/download/win\">https://git-scm.com/download/win\u003C/a>\u003Cbr>\u003Cbr>Téléchargez l'application puis exécutez la.\u003Cbr>\u003Cbr>Pour vérifier que Git est installé sur votre poste de travail il suffit de lancer une ligne de commande.\u003C/p>"}},{"code":{"language":"git","filename":"","filesize":0,"content":"# Test de la version\ngit --version\n"},"name":"installation-git05","title":"installation-git05","linkable":false},{"name":"installation-angularcli01","title":"Installation d' Angular CLI","linkable":true,"text":{"content":"\u003Cp>\u003Cstrong>Angular CLI \u003C/strong>ça veut dire \u003Cstrong>Angular \u003C/strong>\u003Cstrong>Command Line Interface.\u003C/strong>\u003Cbr>Mais c'est surtout ça.\u003C/p>"}},{"name":"installation-angularcli02","title":"installation-angularcli02","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/anguarl-cli-installation.png","alt":"Angular CLI l'homme orchestre","title":"Angular CLI l'homme orchestre","libelle":"L' homme à tout faire d'Angular"}},{"name":"installation-angularcli03","title":"installation-angularcli03","linkable":false,"text":{"content":"\u003Cp>Et autant utiliser la version la plus récente.\u003Cbr>\u003Cbr>\u003Cstrong>Angular\u003C/strong> version \u003Cstrong>20.1.3\u003C/strong>\u003Cbr>\u003Cstrong>Angular CLI\u003C/strong> version \u003Cstrong>20.1.3\u003C/strong>\u003Cbr>\u003Cbr>Les dernières versions de ces outils sont disponibles ci-dessous\u003Cbr>\u003Ca href=\"https://github.com/angular/angular/releases\">https://github.com/angular/angular/releases\u003C/a>\u003Cbr>\u003Ca href=\"https://github.com/angular/angular-cli/releases\">https://github.com/angular/angular-cli/releases\u003C/a>\u003Cbr>\u003Cbr>La procédure d'installation est détaillée sur le site officiel d'Angular\u003Cbr>\u003Cbr>\u003Ca href=\"https://angular.dev/tools/cli/setup-local#dependencies\">https://angular.dev/tools/cli/setup-local#dependencies\u003C/a>\u003Cbr>\u003Cbr>La méthode est décrite sur la page du site officiel.\u003Cbr>\u003Cbr>Je vais détailler celle-ci.\u003Cbr>\u003Cbr>\u003Cem>- Si une version précédente était installée sur votre poste vous pouvez la désinstaller avec la commande suivante\u003C/em>\u003Cbr>\u003C/p>"}},{"code":{"language":"git","filename":"","filesize":0,"content":"# Désinstallation d'angular-cli\nnpm uninstall -g @angular/cli"},"name":"installation-angularcli04","title":"installation-angularcli04","linkable":false},{"name":"installation-angularcli05","title":"installation-angularcli05","linkable":false,"text":{"content":"\u003Cp>Angular CLI est une librairie (ou package).\u003Cbr>Nous allons l'installer avec npm le gestionnaire de node.js\u003Cbr>\u003Cbr>Vous pouvez installer une version spécifique d'angular ou installer par défaut la dernière disponible.\u003C/p>"}},{"code":{"language":"git","filename":"","filesize":0,"content":"# Installation d'angular-cli dernière version disponible\nnpm install -g @angular/cli\n\n# Installation d'angular-cli version spécifique\nnpm install -g @angular/cli@20.1.3\n\n# Test de version installée\nng version"},"name":"installation-angularcli06","title":"installation-angularcli06","linkable":false},{"name":"initialization01","title":"Initialisation du projet avec Angular CLI","linkable":true,"chapter":{"src":"https://api.ganatan.com/tutorials/img/initialization-avec-angularcli.png","alt":"Initialisation avec Angular CLI","title":"Initialisation du projet avec Angular CLI","step":"Etape 2","color":"red-darken-1","content":"\u003Cp>Angular est un framework complet qui couvre un grand nombre de fonctionnalités.\u003Cbr>La documentation est particulièrement fournie et détaillée.\u003Cbr>\u003Cbr>Nous essaierons le plus souvent possible de respecter les meilleures pratiques (\u003Cstrong>best practices\u003C/strong>) préconisées par l'équipe d'angular.\u003C/p>\u003Cp>\u003Cbr>Nous pouvons créer manuellement chaque élément de notre application mais le plus simple est d'utiliser \u003Cstrong>Angular CLI\u003C/strong>\u003C/p>"}},{"name":"initialization02","title":"Créer notre application avec Angular CLI","linkable":true,"text":{"content":"\u003Cp>\u003Cbr>\u003Cstrong>Angular CLI \u003C/strong>est un outil pour initialiser, développer et maintenir des applications Angular.\u003Cbr>\u003Cbr>Le site officiel est ici \u003Ca href=\"https://angular.dev/cli\">https://angular.dev/cli\u003C/a>\u003Cbr>Et si vous voulez avoir la liste des commandes Angular CLI\u003Cbr>\u003Cbr>\u003Ca href=\"https://github.com/angular/angular-cli/wiki\">https://github.com/angular/angular-cli/wiki\u003C/a>\u003C/p>"}},{"name":"initialization03","title":"initialization03","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/angularcli-site.png","alt":"Le site Angular CLI","title":"Le site Angular CLI","libelle":""}},{"name":"initialization04","title":"initialization04","linkable":false,"text":{"content":"\u003Cp>Pour aller plus vite je vous fais un résumé essentiel.\u003Cbr>\u003Cbr>Angular CLI nous offre un certain nombre de commandes.\u003Cbr>Ces commandes nous évitent d'effectuer des tâches répétitives.\u003Cbr>\u003Cbr>La première commande que nous allons utiliser est \u003Cstrong>ng new \u003C/strong>ou \u003Cstrong>ng n\u003C/strong>\u003C/p>\u003Cul>\u003Cli>Elle va créer notre application.\u003C/li>\u003Cli>Elle va générer tous les fichiers nécessaires à cette application.\u003C/li>\u003Cli>Elle va évidemment suivre les best practices préconisées par l'équipe de Google.\u003C/li>\u003C/ul>\u003Cp>\u003Cbr>On choisit le nom de notre application (arbitrairement ce sera ici \u003Cstrong>angular-starter\u003C/strong>)\u003Cbr>On tape la commande ng new avec les paramètres correspondants\u003Cbr>\u003Cbr>- On génère le projet (\u003Cem>cette partie prend quelques minutes\u003C/em>)\u003C/p>\u003Cul>\u003Cli>\u003Cem>Pour une compréhension plus simple nous gérerons le routing et le sass dans un autre tutoriel.\u003C/em>\u003C/li>\u003Cli>\u003Cstrong>Choisir le type CSS\u003C/strong> (valeur par défaut Yes)\u003C/li>\u003Cli>\u003Cstrong>Désactiver le Server side Rendering\u003C/strong> (valeur par défaut Non)\u003C/li>\u003C/ul>\u003Cp>- On se positionne dans le projet\u003Cbr>- On exécute le projet\u003C/p>\u003Cp>Ce qui donne\u003C/p>"}},{"code":{"language":"git","filename":"","filesize":0,"content":"# Générer un projet appelé angular-starter avec choix manuel des options\nng new angular-starter\n\n# Générer un projet appelé angular-starter avec options par défaut\nng new angular-starter --defaults\n\n# Se positionner dans le projet\ncd angular-starter\n\n# Exécuter\nng serve\n\n# Exécuter et lancer automatiquement l'application dans le navigateur\nng serve -o"},"name":"initialization05","title":"initialization05","linkable":false},{"name":"initialization06","title":"initialization06","linkable":false,"text":{"content":"\u003Cp>Angular CLI via la commande \u003Cstrong>ng serve \u003C/strong>execute le projet sur un port par défaut (4200).\u003Cbr>\u003Cbr>Il ne reste qu'à tester le fonctionnement dans un navigateur en lançant l'url suivante.\u003C/p>"}},{"code":{"language":"git","filename":"","filesize":0,"content":"# Tester\nhttp://localhost:4200"},"name":"initialization07","title":"initialization07","linkable":false},{"name":"initialization08","title":"Utiliser notre application avec Visual Studio Code","linkable":true,"text":{"content":"\u003Cp>Lancez \u003Cstrong>VS Code\u003C/strong>.\u003Cbr>\u003Cbr>Ouvrez un dossier dans le répertoire \u003Cstrong>angular-starter \u003C/strong>que nous avons créé lors de l'initialisation.\u003Cbr>\u003Cbr>Ouvrez ensuite le fichier \u003Cstrong>package.json\u003C/strong>.\u003Cbr>Celui-ci contient un certain nombre de commandes (ou scripts) que nous utiliserons tout au long de ce tutoriel.\u003Cbr>\u003Cbr>Ouvrez une console VS code (sélectionnez Afficher/Terminal) pour exécuter les scripts suivants\u003Cbr>\u003Cbr>\u003C/p>\u003Cul>\u003Cli>\u003Cstrong>npm run start\u003C/strong> : Exécute l'application en mode développement.\u003C/li>\u003Cli>\u003Cstrong>npm run build\u003C/strong> : Compile l'application dans le répertoire\u003Cstrong> dist.\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>npm run test\u003C/strong> : Exécute les tests unitaires en utilisant le framework \u003Cstrong>Karma.\u003C/strong>\u003C/li>\u003C/ul>\u003Cp>Remarque pour les nostalgiques des versions précédentes\u003C/p>\u003Cp>La commande ng eject (permettant de générer la configuration webpack) a été désactivée.\u003C/p>\u003Cp>Elle a été supprimée depuis la version 8\u003C/p>\u003Cp>Projet exemple de gestion du format de configuration\u003C/p>\u003Cp>\u003Cbr>\u003Ca href=\"https://github.com/manfredsteyer/ngx-build-plus\">https://github.com/manfredsteyer/ngx-build-plus\u003C/a>\u003Cbr>\u003Cbr>\u003C/p>\u003Cp>En mode développement si nous voulons personnaliser le port il suffit de modifier le script start dans le fichier package.json.\u003Cbr>\u003Cbr>Par exemple pour utiliser le port 4201 le script serait le suivant \"start\": \"\u003Cstrong>ng serve --port 4201\u003C/strong>\"\u003C/p>\u003Cp>Nous laisserons le port 4200 modifiable à volonté pour la suite du tutoriel.\u003C/p>"}},{"code":{"language":"json","filename":"package.json","filesize":0,"content":" \"scripts\": {\n \"ng\": \"ng\",\n \"start\": \"ng serve --port 4200\",\n \"build\": \"ng build\",\n \"watch\": \"ng build --watch --configuration development\",\n \"test\": \"ng test\"\n }\n"},"name":"initialization09","title":"initialization09","linkable":false},{"name":"update-packagejson","title":"Mise à jour du package.json","linkable":true,"chapter":{"src":"https://api.ganatan.com/tutorials/img/update.png","alt":"Mise à jour du package.json","title":"Mise à jour du package.json","step":"Etape 3","color":"blue-gradient","content":"\u003Cp>Node.js est la \u003Cstrong>plateforme \u003C/strong>pour développer notre application.\u003Cbr>Node.js est basée sur l'utilisation de librairies ou dépendances.\u003Cbr>\u003Cbr>Npm est le gestionnaire des \u003Cstrong>librairies \u003C/strong>(packages en anglais)\u003Cbr>\u003Cbr>La mise à jour d'une application et donc de ses librairies est une question périlleuse.\u003Cbr>\u003Cbr>Je vais vous montrer qu'avec Angular la notion de \u003Cstrong>mise à jour\u003C/strong> des versions est essentielle.\u003Cbr>Elle doit être menée avec prudence.\u003C/p>"}},{"name":"update01","title":"Update or not update","linkable":true,"text":{"content":"\u003Cp>Les\u003Cstrong> librairies javascript\u003C/strong> sont constamment \u003Cstrong>modifiées \u003C/strong>et \u003Cstrong>mises à jour\u003C/strong> par leur concepteur.\u003Cbr>Lorsqu'une nouvelle version est disponible elle porte le nom de \u003Cstrong>release \u003C/strong>(sortie en anglais) et dispose d'un numéro spécifique.\u003Cbr>\u003Cbr>Si la librairie est open-source vous pouvez voir les dernières versions disponibles en allant sur le dépôt correspondant sur Github puis allez sur Releases.\u003Cbr>\u003Cbr>Par exemple les différentes versions d'Angular sont accessibles ici\u003Cbr>\u003Ca href=\"https://github.com/angular/angular/releases\">https://github.com/angular/angular/releases\u003C/a>\u003Cbr>\u003Cbr>Le calendrier des mises à jour est ici\u003Cbr>\u003Ca href=\"https://angular.dev/reference/releases#versioning\">https://angular.dev/reference/releases#versioning\u003C/a>\u003Cbr>\u003Cbr>Votre passé, votre présent et votre futur.\u003C/p>"}},{"name":"update02","title":"update02","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/angular-releases.png","alt":"Les releases Angular","title":"Les releases Angular","libelle":""}},{"name":"update03","title":"update03","linkable":false,"text":{"content":"\u003Cp>\u003Cem>Remarquez que les versions 2 à 17 ne sont plus supportées.\u003C/em>\u003Cbr>\u003Cbr>Et le danger est évidemment que toutes ces mises à jour altèrent le fonctionnement de notre application.\u003Cbr>Dans tous les cas on ne pourra y échapper il faudra un jour ou l'autre essayer de les intégrer dans nos projets.\u003Cbr>\u003Cbr>Je vais vous expliquer comment je procède personnellement.\u003C/p>"}},{"name":"update04","title":"update04","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/update-or-not-update.png","alt":"Les mises à jour Angular","title":"Les mises à jour Angular","libelle":"Je n'ai pas pensé aussi loin"}},{"name":"update05","title":"Comment fait-on ?","linkable":true,"text":{"content":"\u003Cp>Utilisons npm (Node Package Manager) le gestionnaire de librairies de Node.js.\u003C/p>\u003Cp>\u003Cbr>La documentation complète est \u003Cbr>ici \u003Ca href=\"https://docs.npmjs.com/cli/outdated.html\">https://docs.npmjs.com/cli/outdated.html\u003C/a>\u003Cbr>\u003Cbr>\u003C/p>\u003Cp>Deux commandes nous seront utiles\u003Cbr>\u003Cbr>\u003C/p>\u003Cp>Vérifier les versions effectivement installées\u003Cbr>\u003Cbr>\u003C/p>\u003Cul>\u003Cli>npm list --depht=0\u003Cbr>\u003Cbr>Cette commande vérifie les dépendances effectivement installées dans le répertoire node_modules.\u003Cbr>Elle nous fournit une liste que l'on peut renseigner dans package.json (voir Remarque)\u003C/li>\u003C/ul>\u003Cp>\u003Cbr>Vérifier les versions de nos librairies via la commande\u003Cbr>\u003Cbr>\u003C/p>\u003Cul>\u003Cli>npm outdated\u003Cbr>\u003Cbr>Cette commande vérifie le registre des dépendances pour vérifier si les packages installés sont à jour.\u003Cbr>Elle nous fournit ainsi une liste que l'on peut contrôler.\u003C/li>\u003C/ul>\u003Cp>\u003Cbr>Remarque\u003C/p>\u003Cp>Avant de vérifier les dépendances mettons à jour le fichier package.json en fonction des versions fournies\u003C/p>\u003Cp>par la commande npm list\u003C/p>\u003Cp>\u003Cbr>Pour chaque dépendance indiquée supprimez le caractère ~ ou ^\u003C/p>\u003Cp>\u003Cbr>Par exemple remplacez\u003C/p>\u003Cul>\u003Cli>\"rxjs\": \"~7.8.0\",\u003C/li>\u003Cli>\"tslib\": \"^2.3.0\",\u003C/li>\u003C/ul>\u003Cp>\u003Cbr>par\u003C/p>\u003Cstrong>\u003Cul>\u003Cli>\"rxjs\": \"7.8.2\",\u003C/li>\u003Cli>\"tslib\": \"2.8.1\",\u003C/li>\u003C/ul>\u003C/strong>\u003Cp>\u003Cbr>Pour éviter les erreurs éventuelles supprimer au préalable \u003Cbr>le fichier \u003Cstrong>package-lock.json\u003C/strong> et le répertoire \u003Cstrong>node_modules\u003C/strong>.\u003C/p>\u003Cp>\u003Cbr>Puis réinstallez les dépendances avec npm install (package-lock.json et node_modules sont alors recréés automatiquement).\u003C/p>"}},{"code":{"language":"git","filename":"","filesize":0,"content":"# Vérification des versions des dépendances installées dans node_modules\n npm list --depth=0\n\n# Vérification des dépendances disponibles\nnpm outdated"},"name":"update06","title":"Résultats de la mise à jour !","linkable":false},{"name":"update07","title":"Résultats de la mise à jour !","linkable":true,"text":{"content":"\u003Cp>Si je mets à jour le fichier package.json je me retrouve confronté à 3 cas de figure\u003Cbr>\u003Cbr>\u003C/p>\u003Cul>\u003Cli>1/ Ca marche\u003Cbr>C'est pas tous les jours la fête mais depuis Angular 8 c'est de plus en plus souvent\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>2/ Ca ne marche pas on essaie de debugger sans y passer trop de temps.\u003Cbr>Ca dépend de votre patience et du temps que vous avez devant vous\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>3/ Ca marche pas et on attend.\u003Cbr>Souvent (mais pas toujours) Angular résout votre problème avec la mise à jour suivante.\u003Cbr>De toute façon ce n'est la peine d'attendre indéfiniment, il faudra bien trouver une solution.\u003Cbr>Ou alors on se retrouve avec AngularJS en 2022 et là on n'est pas dans le pétrin.\u003C/li>\u003C/ul>"}},{"name":"update08","title":"update08","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/resultats-des-courses.png","alt":"Mise à jour angular : Résultat des courses","title":"Mise à jour angular : Résultat des courses","libelle":""}},{"name":"update09","title":"Notre prototype Angular","linkable":true,"text":{"content":"\u003Cp>L'idéal est d'avoir un prototype d'application qui contienne suffisamment de fonctionnalités.\u003Cbr>Vous pouvez être à-peu-près sûr que la mise à jour pourra s'effectuer sur la plupart de vos applications.\u003Cbr>Bien sûr ça ne vous épargnera pas d'optimiser votre CI/CD et de veiller à vos tests.\u003Cbr>\u003C/p>"}},{"name":"update10","title":"update10","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/un-prototype-angular.png","alt":"Un prototype Angular","title":"Un prototype Angular","libelle":""}},{"name":"update11","title":"Un prototype d'enfer","linkable":false,"text":{"content":"\u003Cp>En tout cas voici une liste des fonctionnalités essentielles à une application selon moi.\u003C/p>\u003Cul>\u003Cli>\u003Cstrong>Routing\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>Lazy Loading\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>Bootstrap\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>Httpclient\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>SSR\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>PWA\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>SEO\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>Components\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>Services\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>Observables\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>Directives\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>Pagination\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>ScrollBox\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>Charts\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>Authentification (authentication/Route guard/Role guard/Jwt)\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>Ngrx\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>Reactiveform / Tempate Driven form\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>Form Modal\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>Internationalization\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>Tests (unit et end-to-end)\u003C/strong>\u003C/li>\u003C/ul>\u003Cp>Le dépôt qui me sert pour l'instant de prototype est le suivant.\u003Cbr>\u003Ca href=\"https://github.com/ganatan/angular-app\">https://github.com/ganatan/angular-app\u003C/a>\u003C/p>"}},{"name":"update12","title":"Donc c'est parti pour la mise à jour","linkable":true,"text":{"content":"\u003Cp>Pour l'exemple nous allons utiliser cette méthode sur notre application angular-starter.\u003Cbr>\u003Cbr>Le fichier package.json contient les différentes \u003Cstrong>dépendances\u003C/strong> de votre projet.\u003Cbr>Les dépendances sont en quelque sorte toutes les librairies que vous avez décidé d'utiliser dans votre projet.\u003Cbr>Elles sont gérées par \u003Cstrong>npm\u003C/strong> (node package manager) le gestionnaire de dépendances de \u003Cstrong>Node.js\u003C/strong>.\u003Cbr>\u003Cbr>Concernant les dépendances et leur version la documentation npm est la suivante\u003Cbr>\u003Ca href=\"https://docs.npmjs.com/files/package.json#dependencies\">https://docs.npmjs.com/files/package.json#dependencies\u003C/a>\u003Cbr>\u003Cbr>Les spécificateurs de version sont nombreux.\u003Cbr>\u003Cbr>Nous pouvons utiliser par exemple\u003C/p>\u003Cul>\u003Cli>\u003Cstrong>version\u003C/strong> Doit correspondre à la version exactement\u003C/li>\u003Cli>\u003Cstrong>~version\u003C/strong> \"Approximativement équivalente à la version\"\u003C/li>\u003Cli>\u003Cstrong>^version\u003C/strong> “Compatible avec la version”\u003C/li>\u003C/ul>\u003Cp>\u003Cbr>Nous opterons quant à nous pour le premier spécificateur \"\u003Cstrong>version\u003C/strong>\", qui est le plus simple, le plus explicite mais aussi le plus restrictif.\u003Cbr>\u003Cbr>Nous allons mettre à jour le fichier package.json avec les dernières dépendances\u003C/p>"}},{"name":"update13","title":"update13","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/update-packagejson.png","alt":"Mise à jour du fichier Package.json pour Angular","title":"Mise à jour du fichier Package.json pour Angular","libelle":""}},{"name":"update14","title":"update14","linkable":false,"text":{"content":"\u003Cp>- Pour contrôler les dépendances à mettre à jour lancez la commande\u003C/p>\u003Cp>npm outdated\u003C/p>\u003Cp>- Dans certains cas toutes les dépendances peuvent être mises à jour à l'exception de typescript\u003C/p>\u003Cp>Angular 20.1.3 accepte par exemple TypeScript supérieur ou égal à 5.8.3\u003C/p>\u003Cp>Vous pouvez le vérifier après la mise à jour en exécutant le script npm run build\u003C/p>\u003Cp>- Dans le cas donc d'Angular 20.1.3 toutes les dépendances peuvent être mises.\u003C/p>\u003Cp>- Supprimez le fichier package-lock.json et le répertoire node_modules\u003C/p>\u003Cp>Modifiez le fichier package.json comme suit puis executez le script\u003C/p>\u003Cp>npm install\u003C/p>"}},{"code":{"language":"json","filename":"package.json","filesize":0,"content":" \"dependencies\": {\n \"@angular/common\": \"20.1.3\",\n \"@angular/compiler\": \"20.1.3\",\n \"@angular/core\": \"20.1.3\",\n \"@angular/forms\": \"20.1.3\",\n \"@angular/platform-browser\": \"20.1.3\",\n \"@angular/router\": \"20.1.3\",\n \"express\": \"5.1.0\",\n \"rxjs\": \"7.8.2\",\n \"tslib\": \"2.8.1\",\n \"zone.js\": \"0.15.1\"\n },\n \"devDependencies\": {\n \"@angular/build\": \"20.1.3\",\n \"@angular/cli\": \"20.1.3\",\n \"@angular/compiler-cli\": \"20.1.3\",\n \"@types/jasmine\": \"5.1.8\",\n \"angular-eslint\": \"20.1.1\",\n \"eslint\": \"9.32.0\",\n \"jasmine-core\": \"5.9.0\",\n \"karma\": \"6.4.4\",\n \"karma-chrome-launcher\": \"3.2.0\",\n \"karma-coverage\": \"2.2.1\",\n \"karma-jasmine\": \"5.1.0\",\n \"karma-jasmine-html-reporter\": \"2.1.0\",\n \"typescript\": \"5.8.3\",\n \"typescript-eslint\": \"8.38.0\" \n }"},"name":"update15","title":"update15","linkable":false},{"name":"update16","title":"update16","linkable":false,"text":{"content":"\u003Cp>Il suffit alors de tester tous les scripts pour vérifier que les mises à jour ont fonctionné.\u003C/p>"}},{"name":"tests-unit-end","title":"Tests et déploiement","linkable":true,"chapter":{"src":"https://api.ganatan.com/tutorials/img/test-unit-endtoend.png","alt":"Tests unitaires et end-to-end avec Angular","title":"Tests et déploiement","step":"Etape 4","color":"green-lighten-1","content":"\u003Cp>Le développement est entré dans sa phase d'industrialisation.\u003Cbr>\u003Cbr>Au même titre que les autres industries la qualité et la quantité doivent être au rendez-vous.\u003C/p>\u003Cp>\u003Cbr>Des méthodes \u003Cstrong>Agile \u003C/strong>ont été inventées pour cela.\u003Cbr>\u003Cbr>\u003C/p>\u003Cp>Les \u003Cstrong>tests \u003C/strong>en font partie intégrante.\u003C/p>\u003Cp>\u003Cbr>Nous allons voir que les concepteurs d'Angular ont tout prévu.\u003C/p>\u003Cp>Enfin nous déploierons notre application via plusieurs méthodes.\u003C/p>"}},{"name":"tests01","title":"Les Tests : Le secret de mon succès","linkable":true,"text":{"content":"\u003Cp>Créer une application Web c'est comme créer n'importe quel objet.\u003Cbr>On crée une voiture, une télévision ou un avion par exemple.\u003Cbr>Et avant de le donner à quelqu'un on va tester son fonctionnement.\u003Cbr>\u003Cbr>Les informaticiens se sont dit autant que ce soit simple et automatique.\u003Cbr>Comme toujours c'est plus facile à dire qu'à faire.\u003Cbr>\u003C/p>"}},{"name":"tests02","title":"tests02","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/tests-faciles-difficiles.png","alt":"Angular et les tests : facile ou difficile","title":"Angular et les tests : facile ou difficile","libelle":""}},{"name":"tests03","title":"Un peu d'histoire avant de commencer","linkable":true,"text":{"content":"\u003Cp>Depuis ces débuts le monde informatique a cherché à s'améliorer.\u003Cbr>Plusieurs méthodes de travail ont été adoptées.\u003Cbr>En simplifiant on pourrait dire qu'on en est là\u003Cbr>\u003Cbr>Méthode \u003Cstrong>Cycle en V\u003C/strong> contre méthode \u003Cstrong>Agile\u003C/strong>.\u003Cbr>\u003C/p>"}},{"name":"tests04","title":"tests04","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/methodes-de-travail.png","alt":"Angular et Cycle en V versus Agile","title":"Angular et Cycle en V versus Agile","libelle":"La plus rapide est-elle vraiment celle qu'on croit ?"}},{"name":"tests05","title":"Mais qui a fait quoi ?","linkable":true,"text":{"content":"\u003Cp>Si vous voulez travailler dans la programmation c'est sûr il va falloir \u003Cstrong>se montrer agile\u003C/strong>.\u003Cbr>La méthode Agile la plus utilisée actuellement est la \u003Cstrong>méthode Scrum\u003C/strong>.\u003Cbr>\u003Cbr>Ci dessous un petit historique des vingt dernières années.\u003C/p>"}},{"name":"tests06","title":"tests06","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/tests-unitaires-origine.png","alt":"Origine de la méthode Agile","title":"Origine de la méthode Agile","libelle":""}},{"name":"tests07","title":"tests07","linkable":false,"text":{"content":"\u003Cp>En Novembre 2009 \u003Cstrong>Mike Cohn\u003C/strong> décrit la \u003Cstrong>pyramide des tests\u003C/strong> (\u003Cstrong>The test pyramide\u003C/strong> en anglais) dans son livre\u003Cbr>\u003Cem>Succeeding with Agile: Software Development Using Scrum\u003C/em>\u003Cbr>\u003Cbr>Avec Angular nous nous intéresserons à une catégorie.\u003C/p>\u003Cul>\u003Cli>Les test unitaires\u003C/li>\u003C/ul>\u003Cp>\u003Cbr>Faisons un survol en image de l'architecture d'Angular pour visualiser les tests.\u003C/p>"}},{"name":"tests08","title":"tests08","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/tests-unitaires-angular.png","alt":"Architecture Angular et Tests unitaires","title":"Architecture Angular et Tests unitaires","libelle":""}},{"name":"tests09","title":"Les tests avec Angular","linkable":true,"text":{"content":"\u003Cp>Sans rentrer dans les détails Angular nous simplifie la vie avec les outils suivants.\u003Cbr>\u003Cbr>Les tests unitaires utilisent\u003C/p>\u003Cul>\u003Cli>\u003Cstrong>Karma\u003C/strong>\u003C/li>\u003Cli>\u003Cstrong>Jasmine\u003C/strong>\u003C/li>\u003C/ul>\u003Cp>Les tests end-to-end utilisaient\u003C/p>\u003Cul>\u003Cli>\u003Cstrong>Protractor\u003C/strong>\u003C/li>\u003C/ul>\u003Cp>Remarque : Depuis angular 12 les tests end-to-end ont été désactivés.\u003Cbr>\u003Cbr>La documentation Angular concernant la notion de couverture est accessible à cette adresse \u003Ca href=\"https://angular.dev/guide/testing/code-coverage\">https://angular.dev/guide/testing/code-coverage\u003C/a>\u003Cbr>Je rajoute dans \u003Cstrong>package.json\u003C/strong> un script supplémentaire pour tester la couverture\u003Cbr>\u003Cbr> \"\u003Cstrong>coverage\u003C/strong>\": \"ng test --no-watch --code-coverage\",\u003Cbr>\u003Cbr>Pour les lancer on utilise les scripts correspondants contenus dans le fichier Package.json\u003C/p>"}},{"code":{"language":"git","filename":"","filesize":0,"content":"# Tests unitaires\nnpm run test\n\n# Tests unitaires avec couverture\nnpm run coverage"},"name":"tests10","title":"tests10","linkable":false},{"name":"testscompil01","title":"Modifier et vérifier","linkable":true,"text":{"content":"\u003Cp>Effectuons\u003Cbr>\u003Cbr>- Un test simple modification et de débuggage\u003Cbr>- Un test de contrôle de code source.\u003Cbr>- Débuggage.\u003Cbr>\u003Cbr>Toute modification entraine une recompilation du code.\u003Cbr>\u003Cbr>Par exemple Modifier le fichier app.component.html\u003C/p>\u003Cp>Congratulations and Modifications! Your app is running.\u003Cbr>\u003Cbr>\u003C/p>\u003Cp>La compilation est alors exécutée automatiquement et le navigateur se réactualise.\u003Cbr>\u003Cbr>Remarque :\u003Cbr>Le fichier favicon.ico représente l'icône de votre application.\u003Cbr>Vous pouvez le personnaliser.\u003Cbr>Dans cet exemple vous pouvez récupérer celui de ce dépôt.\u003C/p>"}},{"code":{"language":"git","filename":"","filesize":0,"content":"# Executer\nnpm run start\n\n# Tester\nhttp://localhost:4200/\n\n# Effectuer des modifications\n"},"name":"testscompil02","title":"testscompil02","linkable":true},{"name":"tests-tslint01","title":"Vérification du code","linkable":true,"text":{"content":"\u003Cp>En tant qu'informaticien on essaiera de se simplifier la vie.\u003Cbr>Autant avoir de l'aide pour écrire notre code.\u003Cbr>\u003Cbr>L'un des outils utilisés est le linting qui permet d'améliorer la qualité du code.\u003Cbr>\u003Cbr>Angular utilisait l’outil \u003Cstrong>TSLint \u003C/strong>accessible à \u003Cbr>cette adresse \u003Ca href=\"https://palantir.github.io/tslint/\">https://palantir.github.io/tslint/\u003C/a>\u003Cbr>\u003Cbr>Remarque\u003Cbr>Cette commande a été désactivée à partir d'Angular 12.\u003Cbr>On attend le prochain outil préconisé par angular (probablement ESLint ?).\u003Cbr>\u003Cbr>\u003Cem>Comme l'équipe de Google ne s'est pas décidé nous intégrerons ESLint dans notre projet.\u003C/em>\u003Cbr>\u003Cbr>Pour cela nous utiliserons Schematics qui est un générateur de code Angular basé sur des templates de base.\u003Cbr>\u003Cbr>La commande ng lint exécute l’analyse statique du code source TypeScript.\u003Cbr>\u003Cbr>\u003C/p>"}},{"code":{"language":"git","filename":"","filesize":0,"content":"# Installation via schematics\nng add @angular-eslint/schematics\n\n# Répondre oui à la question\nThe package @angular-eslint/schematics@19.6.0 will be installed and executed.\n\n# Test du code source\nnpm run lint\n\n"},"name":"tests-tslint02","title":"tests-tslint02","linkable":false},{"name":"tests-tslint03","title":"tests-tslint03","linkable":false,"text":{"content":"\u003Cp>Schematics a rajouté un script dans le fichier\u003Cstrong> package.json (lint)\u003C/strong>\u003Cbr>et a créé un fichier\u003Cstrong> eslint.config.js\u003C/strong>\u003Cbr>\u003Cbr>Pour vérifier que notre linter fonctionne\u003C/p>\u003Cp>Rajoutons des règles spécifiques dans le fichier \u003Cstrong> eslint.config.js\u003C/strong>\u003Cbr>\u003Cbr>Remarque modifiez cette propriété\u003C/p>\u003Cul>\u003Cli>\"no-var\": \"\u003Cstrong>error\u003C/strong>\"\u003Cbr>une erreur sera signalisée sur l'utilisation de \u003Cstrong>var\u003C/strong>\u003C/li>\u003Cli>\"no-var\": \"\u003Cstrong>off\u003C/strong>\"\u003Cbr>Aucune erreur ne sera signalisée sur l'utilisation de \u003Cstrong>var\u003C/strong>\u003C/li>\u003C/ul>\u003Cp>\u003Cbr>Pour vérifier le comportement du linter.\u003Cbr>\u003Cbr>Modifions un fichier par exemple \u003Cstrong>app.component.ts\u003C/strong>\u003Cbr>Et écrivons du code qui ne correspond pas aux règles\u003Cbr>\u003Cbr>On teste avec le script \u003Cem>npm run lint \u003C/em>qui donnera une erreur\u003Cbr>\u003Cbr>\u003Cstrong>Unexpected var, use let or const instead no-var\u003C/strong>\u003C/p>"}},{"code":{"language":"json","filename":"eslint.config.js","filesize":0,"content":" rules: {\n \"@angular-eslint/directive-selector\": [\n \"error\",\n {\n type: \"attribute\",\n prefix: \"app\",\n style: \"camelCase\",\n },\n ],\n \"@angular-eslint/component-selector\": [\n \"error\",\n {\n type: \"element\",\n prefix: \"app\",\n style: \"kebab-case\",\n },\n ],\n \"@angular-eslint/component-class-suffix\": [\n \"error\",\n {\n suffixes: [\"\", \"Component\"]\n }\n ],\n \"semi\": [\"error\", \"always\"],\n \"comma-dangle\": [\"error\", \"always-multiline\"],\n \"no-undefined\": \"error\",\n \"no-var\": \"error\",\n \"prefer-const\": \"error\",\n \"func-names\": \"error\",\n \"id-length\": \"error\",\n \"newline-before-return\": \"error\",\n \"space-before-blocks\": \"error\",\n \"no-alert\": \"error\"\n },\n"},"name":"tests-tslint04","title":"tests-tslint04","linkable":false},{"code":{"language":"typescript","filename":"app.ts","filesize":0,"content":"import { Component } from '@angular/core';\nimport { RouterOutlet } from '@angular/router';\n\n@Component({\n selector: 'app-root',\n imports: [RouterOutlet],\n templateUrl: './app.html',\n styleUrl: './app.css'\n})\nexport class App {\n protected title = 'angular-starter';\n\n \n checkError() {\n var err = 10;\n \n return err;\n }\n}\n"},"name":"tests-tslint05","title":"tests-tslint05","linkable":false},{"name":"tests-tslint06","title":"tests-tslint06","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/tslint-test.png","alt":"Tests angular avec TSLint","title":"Tests angular avec TSLint","libelle":""}},{"name":"environment01","title":"Environment","linkable":true,"text":{"content":"\u003Cp>L'équipe Angular a décidé de ne plus intégrer automatiquement \u003Cstrong>les paramètres d'environnement (environment en anglais).\u003C/strong>\u003Cbr>Les nouveaux développeurs moins portés sur les problèmes de configuration n'utilisaient pas ces paramètres.\u003Cbr>\u003Cbr>La documentation Angular est accessible à cette adresse\u003Cbr>\u003Ca href=\"https://angular.dev/tools/cli/environments#configure-environment-specific-defaults\">https://angular.dev/tools/cli/environments#configure-environment-specific-defaults\u003C/a>\u003Cbr>\u003Cbr>La commande est la suivante \u003Cstrong>ng generate environments\u003C/strong>\u003Cbr>\u003Cbr>Les éléments nécessaires à son fonctionnement sont créés automatiquement.\u003C/p>\u003Cul>\u003Cli>Création d'un répertoire \u003Cstrong>src/environments\u003C/strong>\u003C/li>\u003Cli>Création d'un fichier\u003Cstrong> environment.development.ts\u003C/strong>\u003C/li>\u003Cli>Création d'un fichier un fichier\u003Cstrong> environment.ts\u003C/strong>\u003C/li>\u003Cli>Modification du fichier\u003Cstrong> angular.json\u003C/strong>\u003C/li>\u003C/ul>"}},{"code":{"language":"typescript","filename":"environment.development.ts","filesize":0,"content":"export const environment = {};"},"name":"environment02","title":"environment02","linkable":false},{"code":{"language":"typescript","filename":"environment.ts","filesize":0,"content":"export const environment = {};\n"},"name":"environment03","title":"environment03","linkable":false},{"code":{"language":"json","filename":"angular.json","filesize":0,"content":" \"configurations\": {\n \"production\": {\n \"budgets\": [\n {\n \"type\": \"initial\",\n \"maximumWarning\": \"500kB\",\n \"maximumError\": \"1MB\"\n },\n {\n \"type\": \"anyComponentStyle\",\n \"maximumWarning\": \"4kB\",\n \"maximumError\": \"8kB\"\n }\n ],\n \"outputHashing\": \"all\"\n },\n \"development\": {\n \"optimization\": false,\n \"extractLicenses\": false,\n \"sourceMap\": true,\n \"fileReplacements\": [\n {\n \"replace\": \"src/environments/environment.ts\",\n \"with\": \"src/environments/environment.development.ts\"\n }\n ]\n }\n },\n"},"name":"environment04","title":"environment04","linkable":false},{"name":"deploiement01","title":"Déploiement","linkable":true,"text":{"content":"\u003Cp>Tout ce que nous avons fait est bien sympathique.\u003Cbr>Mais une application Web n'a d'intérêt que si nous la rendons accessible sur le Web.\u003Cbr>C'est ce que l'on appelle le \u003Cstrong>déploiement\u003C/strong>.\u003Cbr>Nous allons voir comment le faire via deux méthodes de\u003Cstrong> la plus simple \u003C/strong>à \u003Cstrong>la plus compliquée.\u003C/strong>\u003Cbr>\u003Cbr>Mais tout d'abord parlons \u003Cstrong>compilation\u003C/strong>.\u003Cbr>\u003Cbr>Comme nous l'avons vu précédemment le fichier package.json contient un certain nombre de scripts (ou commandes).\u003Cbr>\u003Cbr>Le script qui nous intéresse est \u003Cstrong>npm run build\u003C/strong>\u003Cbr>Il permet de compiler notre application.\u003Cbr>\u003Cbr>Ce script exécute la commande d'Angular CLI \u003Cstrong>ng Build\u003C/strong>\u003Cbr>\u003Cbr>\u003C/p>\u003Cp>Sans rentrer dans les détails voilà comment ça fonctionne.\u003C/p>\u003Cp>Via cette commande Angular utilise l'outil Webpack (un module bundler) pour créer le produit final.\u003C/p>\u003Cp>L'exécution de cette commande va créer un répertoire dist.\u003C/p>\u003Cp>Celui-ci contiendra ce que l'on peut appeler le produit final (ou livrable ou artefact).\u003C/p>\u003Cp>C'est cette partie que l'on va déployer.\u003C/p>\u003Cp>Les conseils donnés par Angular sont à l'adresse suivante\u003Cbr>\u003Ca href=\"https://angular.dev/tools/cli/deployment\">https://angular.dev/tools/cli/deployment\u003C/a>\u003C/p>"}},{"name":"deploiement02","title":"Déploiement avec lite-server","linkable":true,"text":{"content":"\u003Cp>Le déploiement le plus simple est d'utiliser le serveur Http développé par John Papa.\u003Cbr>Comment procéder ?\u003C/p>\u003Cul>\u003Cli>On installe la librairie lite-server en global avec npm\u003C/li>\u003Cli>On exécute l'application en mode production\u003C/li>\u003C/ul>"}},{"code":{"language":"git","filename":"","filesize":0,"content":"# Compilation du projet !!!!!!!! Très important à ne pas oublier\nnpm run build\n\n# Installation du serveur de développement lite-server\nnpm install -g lite-server\n\n# Exécution de notre application\nlite-server --baseDir=\"dist/angular-starter/browser\"\n\n# Tester l'application dans notre navigateur avec l'url suivante\nhttp://localhost:3000/"},"name":"deploiement03","title":"deploiement03","linkable":false},{"name":"deploiement-nginx01","title":"Deploiement avec nginx","linkable":true,"text":{"content":"\u003Cp>Une solution plus complexe mais plus proche de la réalité.\u003Cbr>Il nous faudra disposer d'un serveur virtuel ou VPS (Virtual private server).\u003Cbr>\u003Cbr>Je vous conseille d'en acheter un chez un fournisseur de VPS.\u003Cbr>Par exemple \u003Cstrong>OVH \u003C/strong>ou \u003Cstrong>Digital Ocean\u003C/strong> sont parmi les moins chers et les plus efficaces.\u003Cbr>\u003Cbr>Le tutoriel suivant peut vous être utiles\u003Cbr>\u003Cbr>\u003Ca href=\"https://www.ganatan.com/tutorials/angular-sur-ubuntu\">Installer Angular sur un serveur Ubuntu\u003C/a>\u003C/p>\u003Cbr>"}},{"name":"deploiement-nginx02","title":"deploiement-nginx02","linkable":false,"text":{"content":"\u003Cp>Sur notre serveur (exemple d'un serveur avec ubuntu et l'adresse ip 192.168.100.1)\u003Cbr>\u003Cbr>\u003C/p>\u003Cul>\u003Cli>Installer nginx\u003C/li>\u003Cli>Tester nginx\u003C/li>\u003Cli>Copier notre répertoire dist sur /var/www/html\u003C/li>\u003Cli>Tester le serveur\u003C/li>\u003C/ul>"}},{"code":{"language":"git","filename":"","filesize":0,"content":"# connection sur le serveur en ssh\nssh root@192.168.100.1\n\n# installation de nginx sur le serveur\nsudo apt-get --yes install nginx\nsudo apt-get update\n\n# Démarre le service nginx\nsudo service nginx start\n\n# Tester l'installation du serveur nginx\nhttp://localhost:192.168.100.1/\n\n# Copier le contenu du répertoire dist/angular-starter/browser\n# sur le serveur dans le répertoire /var/www/html/\n\n# Tester l'application\nhttp://localhost:192.168.100.1/\n"},"name":"deploiement-nginx03","title":"deploiement-nginx03","linkable":false},{"name":"deploiement-nginx04","title":"Paramètrage de nginx","linkable":true,"text":{"content":"\u003Cp>Je vous rajoute deux fichiers qui vous seront utiles\u003Cbr>\u003Cbr>\u003C/p>\u003Cul>\u003Cli>un exemple d'un fichier de configuration \u003Cstrong>nginx.conf\u003C/strong>\u003Cbr>\u003C/li>\u003Cli>un exemple de fichier javascript \u003Cstrong>server.js \u003C/strong>pour lancer en local votre application\u003Cbr>A utiliser avec la commande \u003Cstrong>node server.js\u003C/strong>\u003Cbr>Le script suivant est à rajouter dans package.json\u003Cbr> \u003Cstrong> \"serve\": \"node server.js\"\u003C/strong>\u003C/li>\u003C/ul>"}},{"code":{"language":"nginx","filename":"fichier nginx.conf","filesize":0,"content":"user www-data;\nworker_processes auto;\npid /run/nginx.pid;\nerror_log /var/log/nginx/error.log;\ninclude /etc/nginx/modules-enabled/*.conf;\n\nevents {\n worker_connections 768;\n}\n\nhttp {\n sendfile on;\n tcp_nopush on;\n types_hash_max_size 2048;\n\n include /etc/nginx/mime.types;\n default_type application/octet-stream;\n\n ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE\n ssl_prefer_server_ciphers on;\n\n access_log /var/log/nginx/access.log;\n gzip on;\n include /etc/nginx/conf.d/*.conf;\n server {\n listen 80 default_server;\n listen [::]:80 default_server;\n\n root /var/www/html;\n index index.html index.htm index.nginx-debian.html;\n server_name _;\n location / {\n try_files $uri $uri/ =404;\n }\n\n }\n}\n\n"},"name":"deploiement-nginx05","title":"deploiement-nginx05","linkable":true},{"code":{"language":"javascript","filename":"server.js","filesize":0,"content":"const express = require('express');\nconst path = require('path');\nconst app = express();\n\napp.use(express.static(path.join(__dirname, 'dist/angular-starter/browser')));\n\napp.get('/*', function (req, res) {\n res.sendFile(path.join(__dirname, 'dist/angular-starter/browser', 'index.html'));\n});\n\nconst port = 4000;\nconst host = 'localhost';\napp.listen(port, () => {\n console.log(`Server running at http://${host}:${port}`);\n})\n\n"},"name":"deploiement-nginx06","title":"deploiement-nginx06","linkable":true},{"name":"source-code01","title":"Code Source","linkable":true,"chapter":{"src":"https://api.ganatan.com/tutorials/img/code-source.png","alt":"Notre Code Source Angular","title":"Notre Code Source Angular","step":"Etape 5","color":"grey-darken-1","content":"\u003Cp>Ce guide nous a permis de créer une application Web prête à fonctionner.\u003Cbr>\u003Cbr>Pour vous simplifier la tâche vous pouvez utiliser directement le code source de cette application, pour la tester et vérifier qu'elle fonctionne.\u003Cbr>\u003Cbr>Pour cela il suffit d'utiliser\u003Cstrong> le logiciel Git\u003C/strong>.\u003Cbr>Je vais vous montrer comment procéder.\u003Cbr>\u003Cbr>Cette première application reste néanmoins basique.\u003Cbr>Je vous proposerai pour terminer un certain nombre d'étapes qui vous permettront de créer une application plus complexe.\u003C/p>"}},{"name":"source-code02","title":"Utiliser Git avec le code source","linkable":true,"text":{"content":"\u003Cp>En suivant chacun des conseils que je vous ai donnés dans ce guide vous obtenez au final un code source Angular.\u003Cbr>Ce code représente votre travail et doit faire l'objet de toute votre attention.\u003C/p>"}},{"name":"source-code03","title":"source-code03","linkable":false,"text":{"content":"\u003Cp>Comme nous l'avons vu précédemment, \u003Cstrong>Git \u003C/strong>va nous permettre de gérer tous nos codes sources.\u003Cbr>\u003Cbr>Un petit tour sur Wikipedia \u003Ca href=\"https://en.wikipedia.org/wiki/GitHub\">https://en.wikipedia.org/wiki/GitHub\u003C/a> nous apprend que \u003Cbr>\u003Cstrong>GitHub est \u003C/strong>le plus grand hébergeur de code source au monde.\u003Cbr>\u003Cbr>En janvier 2023 on compte\u003C/p>\u003Cul>\u003Cli>100 millions d'utilisateurs \u003C/li>\u003Cli>Plus de 420 millions de dépôts (ou \u003Cstrong>repositories \u003C/strong>en anglais)\u003C/li>\u003C/ul>\u003Cp>Je vous conseille donc de publier vos sources sur cet hébergeur.\u003Cbr>\u003Cbr>Le \u003Cstrong>code source \u003C/strong>de ce tutoriel est bien évidemment disponible sur GitHub.\u003Cbr>Utilisez git pour récupérer ce code et vérifier son fonctionnement.\u003Cbr>\u003Cbr>Il vous suffit de vous rendre à l'adresse suivante\u003Cbr>\u003Ca href=\"https://github.com/ganatan/angular-starter\">https://github.com/ganatan/angular-starter\u003C/a>\u003Cbr>\u003Cbr>\u003Cem>Si ce guide vous a plu et que vous allez sur GitHub pour consulter le code, n'hésitez pas à cliquer sur STAR .\u003C/em>\u003C/p>"}},{"name":"source-code04","title":"source-code04","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/github-star.png","alt":"Star sur Github et Angular","title":"Star sur Github et Angular","libelle":""}},{"name":"source-code05","title":"source-code05","linkable":false,"text":{"content":"\u003Cp>Sinon pour aller plus vite encore suivez les conseils suivants.\u003Cbr>\u003Cbr>Utilisez la commande classique de\u003Cstrong> prompt\u003C/strong> sous windows (cmd) ou linux.\u003Cbr>Puis tapez la liste des commandes\u003C/p>"}},{"code":{"language":"git","filename":"","filesize":0,"content":"# Créez un répertoire demo (le nom est ici arbitraire)\nmkdir demo\n\n# Allez dans ce répertoire\ncd demo\n\n# Récupérez le code source sur votre poste de travail\ngit clone https://github.com/ganatan/angular-react-starter.git\n\n# Allez dans le répertoire qui a été créé\ncd angular-react-starter\ncd frontend-angular\n\n# Exécutez l'installation des dépendances (ou librairies)\nnpm install\n\n# Exécutez le programme\nnpm run start\n\n# Vérifiez son fonctionnement en lançant dans votre navigateur la commande\nhttp://localhost:4200/\n"},"name":"source-code06","title":"source-code06","linkable":false},{"name":"source-code07","title":"Pour aller plus loin","linkable":true,"text":{"content":"\u003Cp>\u003Cbr>Ce tutoriel nous a permis de créer notre première application.\u003Cbr>Celle-ci reste relativement simple.\u003C/p>\u003Cp>\u003Cbr>Si vous voulez créer une application plus complète, il vous faudra mettre en œuvre certains principes et fonctionnalités supplémentaires comme\u003Cbr>\u003Cbr>\u003C/p>\u003Cul>\u003Cli>Le \u003Cstrong>Routing \u003C/strong>(gestion de plusieurs pages)\u003C/li>\u003Cli>Le \u003Cstrong>Lazy loading\u003C/strong> (rapidité de l'application)\u003C/li>\u003Cli>Les\u003Cstrong> PWA\u003C/strong> (fonctionnement sur mobile et desktop)\u003C/li>\u003Cli>Le \u003Cstrong>Server Side Rendering\u003C/strong> (permettre le référencement)\u003C/li>\u003C/ul>\u003Cp>\u003Cbr>\u003Cstrong>L' étape suivante est logiquement la gestion du Routing.\u003C/strong>\u003Cbr>Elle nécessite un tutoriel complet qui est à l'adresse suivante\u003C/p>\u003Cul>\u003Cli>\u003Ca href=\"https://www.ganatan.com/tutorials/routing-avec-angular\">Etape 2 : Routing avec Angular\u003C/a>\u003C/li>\u003C/ul>\u003Cp>\u003Cbr>Les étapes suivantes vous permettront \u003Cstrong>d'obtenir une application prototype.\u003C/strong>\u003C/p>\u003Cul>\u003Cli>\u003Ca href=\"https://www.ganatan.com/tutorials/lazy-loading-avec-angular\">Etape 3 : Lazy loading avec Angular\u003C/a>\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Ca href=\"https://www.ganatan.com/tutorials/bootstrap-avec-angular\">Etape 4 : Bootstrap avec Angular\u003C/a>\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Ca href=\"https://www.ganatan.com/tutorials/modules-avec-angular\">Etape 5 : Modules avec Angular\u003C/a>\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Ca href=\"https://www.ganatan.com/tutorials/server-side-rendering-avec-angular-universal\">Etape 6 : Server Side Rendering avec angular\u003C/a>\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Ca href=\"https://www.ganatan.com/tutorials/progressive-web-app-avec-angular\">Etape 7 : Progressive Web App avec Angular\u003C/a>\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Ca href=\"https://www.ganatan.com/tutorials/search-engine-optimization-avec-angular\">Etape 8 : Search Engine Optimization avec Angular\u003C/a>\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Ca href=\"https://www.ganatan.com/tutorials/httpclient-avec-angular\">Etape 9 : HttpClient avec Angular\u003C/a>\u003Cbr>\u003Ca href=\"https://www.ganatan.com/tutorials/transfer-state-avec-angular\">\u003C/a>\u003C/li>\u003C/ul>\u003Cp>Les étapes suivantes vous permettront d'améliorer ce prototype\u003C/p>\u003Cul>\u003Cli>\u003Ca href=\"https://www.ganatan.com/tutorials/components-avec-angular\">Components avec Angular\u003C/a>\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Ca href=\"https://www.ganatan.com/tutorials/services-avec-angular\">Services avec Angular\u003C/a>\u003Cbr>\u003Cbr>\u003C/li>\u003Cli>\u003Ca href=\"https://www.ganatan.com/tutorials/template-driven-forms-avec-angular\">Template Driven Forms avec Angular\u003C/a>\u003C/li>\u003Cli>\u003Ca href=\"https://www.ganatan.com/tutorials/charts-avec-angular\">Charts avec Angular\u003C/a>\u003C/li>\u003C/ul>\u003Cp>\u003Cstrong>\u003C/strong>\u003Cbr>Cette dernière étape permet \u003Cstrong>d'obtenir un exemple d'application \u003C/strong>\u003C/p>\u003Cul>\u003Cli>\u003Ca href=\"https://www.ganatan.com/tutorials/creer-application-web-complete-avec-angular\">Créer une application Web complète avec Angular\u003C/a>\u003C/li>\u003C/ul>\u003Cp>\u003Cbr>Le \u003Cstrong>code source de cette application finale \u003C/strong>est disponible sur GitHub\u003Cbr>\u003Ca href=\"https://github.com/ganatan/angular-node-java-ai\">https://github.com/ganatan/angular-node-java-ai\u003C/a>\u003C/p>"}},{"name":"source-code08","title":"source-code08","linkable":false,"image":{"src":"https://api.ganatan.com/tutorials/img/cest-fini.png","alt":"Angular c'est fini pour le moment","title":"Angular c'est fini pour le moment","libelle":"The end"}},{"name":"signup","title":"signup","linkable":true,"signup":{"src":"https://api.ganatan.com/tutorials/img/signup-default.png","alt":"signup alt","title":"signup title"}}]},"h":{},"s":200,"st":"OK","u":"https://api.ganatan.com/tutorials/0001","rt":"json"},"__nghData__":[{"t":{"2":"t0","4":"t1","9":"t2","11":"t3","13":"t4","16":"t5","18":"t6","23":"t7","24":"t8"},"c":{"2":[{"i":"t0","r":1}],"4":[],"9":[],"11":[{"i":"t3","r":1}],"13":[],"16":[{"i":"t5","r":1}],"18":[],"23":[],"24":[{"i":"t8","r":1,"t":{"1":"t9","3":"t10","5":"t11","7":"t12","9":"t13","11":"t14"},"c":{"1":[{"i":"t9","r":1}],"3":[],"5":[],"7":[],"9":[],"11":[]}}]}},{},{"t":{"22":"t53"},"c":{"22":[]}},{"t":{"0":"t28","2":"t29","3":"t48","4":"t49"},"c":{"0":[],"2":[{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[{"i":"t30","r":1,"t":{"8":"t31","9":"t32","14":"t33","15":"t34","22":"t35","23":"t36","24":"t37"},"c":{"8":[{"i":"t31","r":1}],"9":[],"14":[{"i":"t33","r":1}],"15":[],"22":[],"23":[{"i":"t36","r":1}],"24":[{"i":"t37","r":1,"t":{"4":"t38","5":"t39"},"c":{"4":[{"i":"t38","r":1}],"5":[]}}]}}],"2":[],"3":[],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]},"x":2},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[{"i":"t54","r":1}]}}],"5":[]},"x":2},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[{"i":"t40","r":1}],"3":[],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[{"i":"t54","r":1}]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[{"i":"t54","r":1}]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]},"x":2},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[{"i":"t54","r":1}]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[{"i":"t40","r":1}],"3":[],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[{"i":"t40","r":1}],"3":[],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[{"i":"t54","r":1}]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[{"i":"t40","r":1}],"3":[],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[{"i":"t54","r":1}]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]},"x":2},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]},"x":3},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]},"x":2},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]},"x":2},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[{"i":"t40","r":1}],"3":[],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[],"4":[],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[{"i":"t43","r":1,"t":{"3":"t47"},"c":{"3":[{"i":"t47","r":1}]}}]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[{"i":"t41","r":1,"t":{"3":"t44","4":"t45","5":"t46"},"c":{"3":[{"i":"t44","r":1}],"4":[{"i":"t45","r":1}],"5":[{"i":"t46","r":1}]}}],"4":[],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[{"i":"t42","r":1,"t":{"4":"t54"},"c":{"4":[{"i":"t54","r":1}]}}],"5":[]}},{"i":"t29","r":1,"t":{"1":"t30","2":"t40","3":"t41","4":"t42","5":"t43"},"c":{"1":[],"2":[],"3":[],"4":[],"5":[]}}],"3":[],"4":[{"i":"t49","r":1,"t":{"1":"t50"},"c":{"1":[]},"x":99},{"i":"t49","r":1,"t":{"1":"t50"},"c":{"1":[{"i":"t50","r":1,"t":{"45":"t51"},"c":{"45":[{"i":"t51","r":1,"t":{"4":"t52"},"c":{"4":[{"i":"t52","r":1,"x":3}]}},{"i":"t51","r":1,"t":{"4":"t52"},"c":{"4":[{"i":"t52","r":1,"x":2}]}}]}}]}}]}},{"t":{"9":"t17","11":"t18","19":"t19","21":"t20","23":"t21","40":"t22","42":"t23","46":"t24","48":"t25","50":"t26","52":"t27"},"c":{"9":[{"i":"t17","r":1}],"11":[],"19":[{"i":"t19","r":1}],"21":[{"i":"t20","r":1}],"23":[],"40":[{"i":"t22","r":1}],"42":[],"46":[{"i":"t24","r":1}],"48":[],"50":[{"i":"t26","r":1}],"52":[]}},{"c":{"2":[{"i":"c3006561385","r":1}]}}]}</script></body></html>