Full Trust European Hosting

BLOG about Full Trust Hosting and Its Technology - Dedicated to European Windows Hosting Customer

AngularJS Hosting Europe - HostForLIFE :: Angular 17 New Features

clock February 16, 2024 08:10 by author Peter

As part of its new movement, Angular 17 provides Signals and Standalone Components. You can anticipate an enhanced Angular Renaissance with Angular 17. It features enhanced support for Server-Side Rendering (SSR), a new control flow syntax, and greater support for lazy loading of page components. Furthermore, the CLI now uses ESBuild, which greatly improves the build procedure.

Integrated Control Flow Automated Transfer
The @angular/core package contains a schematic that you can use to automatically convert your code to the new control flow syntax.

ng g @angular/core:control-flow

Technical Updates in Angular

New looping syntax

  • If-then-else
  • Switch
  • Block directives
  • Deferred rendering
  • SSR and SSG
  • New build system
  • Improved debugging for dependency injection

New Looping Syntax
You can see a live example of the new looping capability in the Angular playground. In this example, we loop over an array of to-do items.

@for (todo of todos; track $index) {
    ...
}


That’s pretty succinct. We expose the todo variable for each element of todos, and we “track” the built-in $index field. The $index variable will show the automatically generated row number for the element (there are other implicit variables like $first, $odd, and $count). You can also use a field on the elements you want to track.
@for (todo of todos; track todo.id) {...}


In this new syntax, the track variable is required, by design. In previous incarnations, the tracking variable was optional, which led to performance degradation. The tracking key on a loop enables the rendering engine to optimize the list display and know what has changed.

If-then-else

@if (todo.done) {
    <s>{{ todo.text }}</s>
} @else {
    <span>{{ todo.text }}</span>
}


Being able to provide the content for @else directly is a major simplification compared to the else clause of the legacy *ngIf alternative. The current control flow also makes it trivial to have @else if, which historically has been impossible.

Switch

Angular’s new switch syntax applies typical JavaScript syntax to templates.

@switch (condition) {

  @case (caseA) {
    <span>Case A.</span>
  }

  @case (caseB) {
    <span>Case B.</span>
  }

  @default {
    <span>Default case.</span>
  }

}


The new control flow enables significantly better type-narrowing in the individual branches in @switch which is not possible in *ngSwitch.

Deferred Rendering
Angular now supports deferred rendering via the block syntax. This gives you a simple and powerful mechanism for defining ways to tell the browser what to display along with instructions for doing it in a non-linear way. The Angular 17 tutorial has some good examples of using @defer.

Here's an example of the simplest @defer.
@defer {
    <span>My deferred content</span>
}


This tells the browser to render the rest of the page first, and then the deferred content. It's a very simple syntax for the times when you want to avoid front-loading everything.

You can also provide @placeholder and @loading blocks.
@defer {
    <span>My deferred content</span>
}

@placeholder {
    <span>Placeholder content</span>
}

@loading {
    <span>Loading deferred content...</span>
}


Placeholder and loading both provide a static layout for the coming content, @placeholder first, then @loading.

Several different strategies are supported by @defer out of the box, like viewport (when the user scrolls it into view), idle (browser is idle), interaction (user interacts with the element), and hover (pointer hovers on the element). Here's an example using hover.
@defer (on hover) {
    <span>My hover content</span>
}

There’s even a @defer(when <expression>) that takes a promise, so you can really defer on any conceivable situation. All in all, the new @defer mechanism is impressive. Deferred rendering is usually persnickety and really interferes with the flow of a developer's thoughts and the resulting code. This latest version of Angular makes it easy.

Note that @defer is still a developer preview in Angular 17, but is considered production-ready.

New Build System

Angular has joined the Vite movement, and Angular 17 uses Vite with Esbuild as its build engine. This was a required change for underpinning the new SSR system. For developers, the main impact is that it's faster, including for serving and updating in dev mode.

Block Directives
@for, @if, and @switch are new “block” directives. They allow us to inject chunks of markup into the template using JavaScript syntax. These new directives replace previous approaches like *ngIf. You can still use *ngIf and other older syntax, and an automated command in the CLI lets you change over to the block syntax.

ng generate @angular/core:control-flow




AngularJS Hosting Europe - HostForLIFE :: Configuring Micro Frontend with the Most Recent Angular Version

clock February 12, 2024 06:39 by author Peter

A micro frontend is what?
A frontend application is divided into smaller, independent, modular components that may be built, deployed, and maintained independently in a micro frontend architecture. Since each component (micro frontend) concentrates on a particular area of the application, it is easier to scale and maintain, particularly in complicated and large-scale projects.


This architectural approach divides the user interface into more manageable, autonomous, and independently deployable components in order to construct web applications. Each of these parts—often called micro frontends—represents a particular application feature, page, or capability.

A web application is developed and implemented as a single unit in a classic monolithic design. Conversely, micro frontends disassemble the frontend into smaller components that can be independently developed, tested, and deployed. A distinct release cycle, technology stack, and development team may be assigned to every micro frontend.

Module Federation addresses several challenges in this context:

Decentralized Development

  • Challenge: Micro frontends need to be developed independently by different teams.
  • Solution: Module Federation allows each micro frontend to have its own codebase, dependencies, and build process, enabling decentralized development.

Dynamic Module Loading

  • Challenge: Loading all modules upfront can lead to slow initial page loads.
  • Solution: Module Federation supports dynamic module loading, where modules are loaded on-demand as users interact with the application. This optimizes the initial loading time.

Loose Coupling

  • Challenge: Micro frontends should communicate without tightly coupling their codebases.
  • Solution: Module Federation ensures loose coupling by defining clear module boundaries and communication interfaces. Micro frontends can interact via APIs or messaging without direct dependencies on internal details.

Versioning and Compatibility

  • Challenge: Coordinating versions of shared dependencies is complex.
  • Solution: Module Federation provides a mechanism for sharing and managing dependencies. Each micro frontend specifies its dependencies, and the build system ensures compatibility.

Loose Coupling

  • Challenge: Micro frontends should communicate without tightly coupling their codebases.
  • Solution: Module Federation ensures loose coupling by defining clear module boundaries and communication interfaces. Micro frontends can interact via APIs or messaging without direct dependencies on internal details.
Seamless Integration
  • Challenge: Micro frontends must seamlessly integrate when necessary.
  • Solution: Module Federation allows for shared components or functionality, ensuring that micro frontends can work together seamlessly when needed.
Optimized Code Splitting
  • Challenge: Efficiently splitting code into smaller, manageable chunks is crucial for performance.
  • Solution: Module Federation optimizes code splitting by intelligently sharing common code among micro frontends while preserving their autonomy.
In technical terms, Module Federation facilitates a modular, dynamic, and loosely coupled architecture, providing a scalable solution for large and complex web applications built with a micro frontend approach.

Getting started

Structuring a system that operates on a micro frontend architecture can be broken down into 2 main parts.

The host application
  • This is also referred to as 'main app' or 'shell app'. It is the application that will consume the micro frontend. You can consider it as the application that the user will use and for it to be fully working, it needs to use the micro services.
  • The microservice
  • Micro frontends are independent, self-contained applications or modules that contribute to the overall user interface.Each micro frontend is developed and maintained by a separate team, allowing for decentralized development. Micro frontends can be features, sections, or components of the larger application. They communicate with the host app and other micro frontends using defined APIs or messaging mechanisms. Micro frontends can be developed using different technologies, frameworks, or even languages, providing flexibility to development teams.
Creating the host app
Generate a new angular project called host app using the command below
ng new host-app --standalone false

Angular will ask for your preferred style sheet format and if you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering). For the latter, I selected "No". The answer to these two questions are up to you.

Once your project is generated, move into the host app. Below is the command in the terminal to do so:
cd host-app

Then, run the following command to all module federation in your host app:
ng add @angular-architects/module-federation
  • You will be asked if you want to proceed. Obviously, say "Yes" !!
  • You will also be asked your project name. You can enter the same name as your angular project, that is, "host-app".
  • You will have to choose on which port to run the project. I chose "5000".
  • Once the command is completed, the host-app is 'micro frontend' ready.

NOTE

You will notice that 2 new files have been created.
The first one is webpack.config.ts and the second one is webpack.prod.config.ts.

The webpack.config.ts and webpack.prod.config.ts files are configuration files for Webpack, a popular JavaScript module bundler. These files define how Webpack should process, bundle, and output your project's assets, such as JavaScript files, stylesheets, and images.

The file contains the configuration for development (or sometimes referred to as the "dev" configuration). The development configuration is optimized for speed and provides additional tools for debugging.

The second one contains the same configuration but for production.

Creating a micro frontend
Generate a new angular project called host app using the command below
ng new mfe-one --standalone false

Angular will ask for your preferred style sheet format and if you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering). Here again, I selected 'No'. The answers to these two questions will depend on you.

Once your project is generated, move into the host app
cd mfe-one

Then, run the following command to all module federation in your host app:
ng add @angular-architects/module-federation

You will be asked the same questions as for the host app. Answer the same way except for the port. All ports to be used should be unique and different be it the host app and all the micro frontends. For our case, we will use port 7000.

In webpack.config.js, you will see a comment 'For remotes'.
It is under this that you will configure how the micro frontend will be exposed.
Following this comment, the next 4-5 commented lines are an example already given to you when you install module federation.
To get started, uncomment the lines starting with: 'name', 'filename' and 'exposes'.
The property 'name' can stay the same.
The property 'filename' must remain 'remoteEntry.js'.

The property 'exposes' should contain an array of a list of how to expose the micro frontend to the host application.

For our micro frontend, we do the following:
// For remotes (please adjust)
   name: "mfeOne",
   filename: "remoteEntry.js",
   exposes: {
       './my-first-mfe': './/src/app/app.module.ts',
  },

In the app-routing.module.ts file, modify the routes constant to the following:
const routes: Routes = [
{
path: '',
component: AppComponent,
pathMatch: 'full',
}
];


Also, change the imports list to the following:
imports: [RouterModule.forChild(routes)],

In the app.component.ts, update the 'selector name' to the following
selector: 'app-root:not(p)'

Also, change the name of the export class from 'AppComponent' to something more unique. We have changed ours to 'MyFirstMfeAppComponent'. This will result in making some updates in the app.module.ts, where the App Component is imported and needs to be changed to the new name.

NOTE: The first part of the key value pair in the 'exposes' array is user defined. You get to choose it, but its value needs to be a module. It can be the module file for a component or the app module component like in our case.

These steps are all the steps required to create a micro frontend. Now we need to connect the micro frontend and the host app.
Connecting the micro frontend and the host app

All of the following steps will be done in the host app.
In the assets folder, create a file and call it 'mf.manifest.json'. This file will contain an array of all the micro frontends that the host app will consume. Remember to add all your micro frontend here. Below is ours:
{
   "my-first-mfe": "http://localhost:3000/remoteEntry.js"
}

In the src folder, create a 'decl.d.ts' file.
In this file, declare the path of the module of the micro frontend.
The path is in the form <name of the micro frontend project>/<name in the 'exposes' part of the webpack config in the micro frontend project>

Ours will look like below:
declare 'mfe-one/my-first-mfe'

Modify the main.ts file to add the following code:
import { loadManifest } from '@angular-architects/module-federation';

import('./bootstrap')
.catch(err => console.error(err));

loadManifest("/assets/mf.manifest.json")
.catch(err => console.error(err))
.then(_ => import('./bootstrap'))
.catch(err => console.error(err));


In the app-routing.module.ts, add the path for the micro frontend in the 'routes' list. Do not forget to add the following import:
import { loadRemoteModule } from '@angular-architects/module-federation';

The 'routes' list should look like below:
const routes: Routes = [
{
path: 'my-first-mfe',
loadChildren: () =>
 loadRemoteModule(
   {
   type: 'module',
   remoteEntry: 'http://localhost:7000/remoteEntry.js',
   exposedModule: './my-first-mfe',
 }
 ).then((m) => m.AppModule),
}
];

The 'path' is the url path to access the page from the micro frontend. For example here, http://localhost:5000/my-first-mfe. The value of the path is up to you.
The 'remoteEntry' is the path of the remoteEntry.js file for your micro frontend. Typically, it is the url of your micro frontend,i.e. Localhost:<<port you chose when add module federation in your micro frontend>>/remoteEntry.js.

The 'exposedModule' is the one defined in the webpack.config.js of your micro frontend.

In the webpack.config.js file, uncomment the lines after the comment (For hosts (please adjust)). In 'remotes', we need to add the url to the remoteEntry.js files for the micro frontend. Below is how to do it for our example:
remotes: {
       "mfeOne": "http://localhost:7000/remoteEntry.js",

   },

Note that port 7000 is used here as it is the port we defined when adding module federation in our micro frontend.

Running the project

The ng serve command can be used to serve your host app.
Make use of the ng serve command to serve the micro frontend project.
Open the host application. It is localhost:5000 in our instance.

Add a '/' and the name of the micro frontend after it to access the micro frontend. It will be 'localhost:5000/my-first-mfe' for us. The micro frontend's HTML will show up at the bottom of the host application's content.

Conclusion

Even while the initial setup could seem time-consuming, the process is worthwhile in the end.
Among other benefits, the frontend becomes more tested and reusable when it is as modular as feasible.



AngularJS Hosting Europe - HostForLIFE :: Create a Calculator Application with Bootstrap and Angular

clock February 5, 2024 06:15 by author Peter

I'll walk you through the process of quickly creating a calculator application with Angular and Bootstrap in this post.


Note: Before beginning this session, please read my earlier essay (linked below) about Angular applications.

Step 1 of the Angular Application: Create Component
Make a component called calculator first.
ng g c calculator

Under the calculator folder, this generates calculator.component.ts & calculator.component.html.

Step 2: In calculator.component.ts, add the angular calculator logic.
The selector 'ng-calculator' is used here. in order to use the <ng-calculator></ng-calculator> calculator component anywhere in our code.

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'ng-calculator',
  templateUrl: './calculator.component.html',
  styleUrls: ['./calculator.component.css']
})
export class CalculatorComponent implements OnInit {

I attach the operand or number that the user clicks to the input variable. For instance, I designate it as the input variable if the user inputs 31+210+40. It makes it simpler to compute the result by simply calling the built-in JavaScript function eval(input). I have some matters to attend to. The user could, for instance, repeat the operands (54++23). or a decimal value that isn't correct, like 54.23.5, etc. Also, if the number starts with 0, eval will generate an error.

The code that follows is prohibited. on multiple occasions. The integers and decimal points are captured here by pressNum. and adds it to the variable used for input. This case has two validations.

input:string = '';
  result:string = '';

  pressNum(num: string) {

    //Do Not Allow . more than once
    if (num==".") {
      if (this.input !="" ) {

        const lastNum=this.getLastOperand()
        console.log(lastNum.lastIndexOf("."))
        if (lastNum.lastIndexOf(".") >= 0) return;
      }
    }

The code below will fail in strict mode since it does not allow 0 at the beginning and Javascript will throw an error. There can be just one decimal place in an integer.
If the integer starts with 0, Eval will throw an error (Octal literals are not allowed in strict mode). Thus, we eliminate it.
if (num=="0") {
      if (this.input=="" ) {
        return;
      }
      const PrevKey = this.input[this.input.length - 1];
      if (PrevKey === '/' || PrevKey === '*' || PrevKey === '-' || PrevKey === '+')  {
          return;
      }
    }
    this.input = this.input + num
    this.calcAnswer();
  }

getLastOperand returns the last operand. For example, if the user input is 921+18 then the last operand is 18.
getLastOperand() {
    let pos:number;
    console.log(this.input)
    pos=this.input.toString().lastIndexOf("+")
    if (this.input.toString().lastIndexOf("-") > pos) pos=this.input.lastIndexOf("-")
    if (this.input.toString().lastIndexOf("*") > pos) pos=this.input.lastIndexOf("*")
    if (this.input.toString().lastIndexOf("/") > pos) pos=this.input.lastIndexOf("/")
    console.log('Last '+this.input.substr(pos+1))
    return this.input.substr(pos+1)
  }


The pressOperator captures the operators. It again appends it to the input variable. We make sure that that operator is followed by a number and not another operator (18++).
pressOperator(op: string) {

    //Do not allow operators more than once
    const lastKey = this.input[this.input.length - 1];
    if (lastKey === '/' || lastKey === '*' || lastKey === '-' || lastKey === '+')  {
      return;
    }

    this.input = this.input + op
    this.calcAnswer();
  }


Here clear removes the last input.
clear() {
    if (this.input !="" ) {
      this.input=this.input.substr(0, this.input.length-1)
    }
  }


Here allClear clears everything.
allClear() {
    this.result = '';
    this.input = '';
  }


Here calcAnswer is where the calculation happens. We check the last character. If it is a decimal point (.) then we remove it (Example in 15+13.). We also remove the last character if it is an operator. (Example 15+13+).
calcAnswer() {
    let formula = this.input;

    let lastKey = formula[formula.length - 1];

    if (lastKey === '.')  {
      formula=formula.substr(0,formula.length - 1);
    }
    lastKey = formula[formula.length - 1];

    if (lastKey === '/' || lastKey === '*' || lastKey === '-' || lastKey === '+' || lastKey === '.')  {
      formula=formula.substr(0,formula.length - 1);
    }

    console.log("Formula " +formula);
    this.result = eval(formula);
  }


Here getAnswer calculates and assigns the result to the input variable.
getAnswer() {
    this.calcAnswer();
    this.input = this.result;
    if (this.input=="0") this.input="";
  }


Then use of constructor() and ngOnInit().
constructor() { }
  ngOnInit(): void {
  }
}


The Code as shown below,
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'ng-calculator',
  templateUrl: './calculator.component.html',
  styleUrls: ['./calculator.component.css']
})
export class CalculatorComponent implements OnInit {

  input:string = '';
  result:string = '';

  pressNum(num: string) {

    if (num==".") {
      if (this.input !="" ) {

        const lastNum=this.getLastOperand()
        console.log(lastNum.lastIndexOf("."))
        if (lastNum.lastIndexOf(".") >= 0) return;
      }
    }
    if (num=="0") {
      if (this.input=="" ) {
        return;
      }
      const PrevKey = this.input[this.input.length - 1];
      if (PrevKey === '/' || PrevKey === '*' || PrevKey === '-' || PrevKey === '+')  {
          return;
      }
    }
    this.input = this.input + num
    this.calcAnswer();
  }

  getLastOperand() {
    let pos:number;
    console.log(this.input)
    pos=this.input.toString().lastIndexOf("+")
    if (this.input.toString().lastIndexOf("-") > pos) pos=this.input.lastIndexOf("-")
    if (this.input.toString().lastIndexOf("*") > pos) pos=this.input.lastIndexOf("*")
    if (this.input.toString().lastIndexOf("/") > pos) pos=this.input.lastIndexOf("/")
    console.log('Last '+this.input.substr(pos+1))
    return this.input.substr(pos+1)
  }

  pressOperator(op: string) {
    const lastKey = this.input[this.input.length - 1];
    if (lastKey === '/' || lastKey === '*' || lastKey === '-' || lastKey === '+')  {
      return;
    }

    this.input = this.input + op
    this.calcAnswer();
  }

  clear() {
    if (this.input !="" ) {
      this.input=this.input.substr(0, this.input.length-1)
    }
  }
  allClear() {
    this.result = '';
    this.input = '';
  }
  calcAnswer() {
    let formula = this.input;

    let lastKey = formula[formula.length - 1];

    if (lastKey === '.')  {
      formula=formula.substr(0,formula.length - 1);
    }
    lastKey = formula[formula.length - 1];

    if (lastKey === '/' || lastKey === '*' || lastKey === '-' || lastKey === '+' || lastKey === '.')  {
      formula=formula.substr(0,formula.length - 1);
    }

    console.log("Formula " +formula);
    this.result = eval(formula);
  }
  getAnswer() {
    this.calcAnswer();
    this.input = this.result;
    if (this.input=="0") this.input="";
  }
  constructor() { }
  ngOnInit(): void {
  }
}

Step 3. Add Angular template code in calculator.component.html using Bootstrap
<div class="container-fluid">
    <div class="jumbotron col-sm-9 p-2 m-0 bg-warning">
      <h2 class="text-center">Angular Calculator Application</h2>
      <div class="form-group">
        <label for="usr">Displays the User Input</label>
        <div class="form-control" type="text">{{input}}</div>
      </div>
      <div class="form-group">
        <label for="pwd">Displays the Results</label>
        <div class="form-control" type="text">{{result}}</div>
      </div>
      <div class="col-sm-12 p-1 m-0">
        <button class="btn btn-info col-sm-6" type="button" (click)="allClear()">C</button>
        <button class="btn btn-danger col-sm-3" type="button" (click)="clear()">x</button>
        <button class="btn btn-secondary col-sm-3" type="button" (click)="pressOperator('/')">/</button>
      </div>
      <div class="col-sm-12 p-1 m-0">
        <button class="btn btn-primary col-sm-3 p-1" type="button" (click)="pressNum('7')">7</button>
        <button class="btn btn-primary col-sm-3 p-1" type="button" (click)="pressNum('8')">8</button>
        <button class="btn btn-primary col-sm-3 p-1" type="button" (click)="pressNum('9')">9</button>
        <button class="btn btn-secondary col-sm-3 p-1" type="button" (click)="pressOperator('*')">X</button>
      </div>
      <div class="col-sm-12 p-1 m-0">
        <button class="btn btn-primary col-sm-3 p-1" type="button" (click)="pressNum('4')">4</button>
        <button class="btn btn-primary col-sm-3 p-1" type="button" (click)="pressNum('5')">5</button>
        <button class="btn btn-primary col-sm-3 p-1" type="button" (click)="pressNum('6')">6</button>
        <button class="btn btn-secondary col-sm-3 p-1" type="button" (click)="pressOperator('-')">-</button>
      </div>
      <div class="col-sm-12 p-1 m-0">
        <button class="btn btn-primary col-sm-3 p-1" type="button" (click)="pressNum('1')">1</button>
        <button class="btn btn-primary col-sm-3 p-1" type="button" (click)="pressNum('2')">2</button>
        <button class="btn btn-primary col-sm-3 p-1" type="button" (click)="pressNum('3')">3</button>
        <button class="btn btn-secondary col-sm-3 p-1" type="button" (click)="pressOperator('+')">+</button>
      </div>
      <div class="col-sm-12 p-1 m-0">
        <button class="btn btn-primary col-sm-3 p-1" type="button" (click)="pressNum('.')">.</button>
        <button class="btn btn-primary col-sm-3 p-1" type="button" (click)="pressNum('0')">0</button>
        <button class="btn btn-lg btn-success col-sm-6 p-1" type="button" (click)="getAnswer()">=</button>
      </div>
    </div>
    </div>


The first textbox displays the user input including the operators.

<div class="container-fluid">
    <div class="jumbotron col-sm-9 p-2 m-0 bg-warning">
      <h2 class="text-center">Angular Calculator Application</h2>
      <h3 class="text-center">By Satyaprakash</h3>
      <div class="form-group">
        <label for="usr">Displays the User Input</label>
        <div class="form-control" type="text">{{input}}</div>
      </div>

Markup

The second textbox displays the result as the user type.
<div class="form-group">
        <label for="pwd">Displays the Results</label>
        <div class="form-control" type="text">{{result}}</div>
      </div>


C clears every display, and x deletes, or clears, the most recent input. Our four operators for division, multiplication, subtraction, addition, and use are /, X,-, and +. to input the digits in decimal. = Computes and resets the input from the user. I'm mapping user clicks to the component class through the usage of event binding. PressNum() records the buttons for numbers and decimals. The button clicks for /, X,-, and + are recorded by the pressOperator() method. All inputs are cleared using allClear. To remove the last input, use clear(). Calculator is reset after calculation using getAnswer().

Step 4. Add the selector of calculator.component.html in app.component.html
<ng-calculator></ng-calculator>

Step 5. Add the CalculatorComponent in the declaration array of app.module.ts
import { CalculatorComponent } from './calculator/calculator.component';

@NgModule({
  declarations: [
    AppComponent,
    CalculatorComponent
  ],


Step 6. Add Bootstrap CDN url in the index.html to make the application responsive design
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Angular Application Real-Time</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body>
  <app-root></app-root>
</body>
</html>


Output
Use the below command to run the Angular application.
ng serve



AngularJS Hosting Europe - HostForLIFE :: Which Angular Modifiers Are Important?

clock January 22, 2024 07:12 by author Peter

In Angular, key modifiers are special keys that you can use in combination with other keys to capture specific keyboard events. These modifiers help you distinguish between different key combinations and provide more flexibility in handling user input.


Key modifiers in Angular
Here are some key modifiers commonly used in Angular.
$event: This is a special variable that you can use to access the native event object in your event handler. For example.

<input (keyup)="onKeyUp($event)">

In the component:

onKeyUp(event: KeyboardEvent): void {
    // Access event properties, such as event.keyCode, event.key, etc.
}

(keyup.enter) and (keyup.esc): These are examples of key modifiers for specific keys. They allow you to handle events triggered by the Enter key or the Escape key.

<input (keyup.enter)="onEnterKey()" (keyup.esc)="onEscapeKey()">

In the component
onEnterKey(): void {
    // Handle Enter key press
}

onEscapeKey(): void {
    // Handle Escape key press
}


(keydown.space): Similar to (keyup.enter), this allows you to handle events triggered by the Space key.
<button (keydown.space)="onSpaceKey()">Click me with Space</button>

In the component
onSpaceKey(): void {
    // Handle Space key press
}

(keyup.shift): You can use this to handle events triggered when the Shift key is released.
<input (keyup.shift)="onShiftKeyUp()">

In the component
onShiftKeyUp(): void {
    // Handle Shift key release
}


(keydown.ctrl) and (keydown.meta): These modifiers allow you to handle events when the Ctrl (Control) key or the Meta key (Command key on Mac) is pressed.
<input (keydown.ctrl)="onCtrlKeyDown()" (keydown.meta)="onMetaKeyDown()">

In the component:
onCtrlKeyDown(): void {
    // Handle Ctrl key press
}

onMetaKeyDown(): void {
    // Handle Meta key press
}

With the help of these key modifiers, it is possible to record particular key-related events and carry out actions in response to user input. They make your Angular applications more interactive by enabling you to react to keyboard inputs in a more sophisticated



AngularJS Hosting Europe - HostForLIFE :: Observable Management Using NgIf and Async Pipe

clock January 18, 2024 08:01 by author Peter

When the component loads, Angular's async pipe subscribes to an Observable or Promise and returns the value that was last emitted. Every time a new value is emitted, the async pipe designates the component that needs to be examined for modifications. When the component is destroyed, it will automatically unsubscribe. Additionally, the async pipe immediately unsubscribes from the current Observable or Promise and subscribes to a new one when the reference of an expression changes.

An illustration of an observable-based async pipe


Our basic component subscribes to the currentTime$ observable via the async pipe. Every time the observable emits a new value, the value that is displayed is automatically updated.

import { Component } from '@angular/core';
import { Observable, interval } from 'rxjs';

@Component({
  selector: 'app-root',
  template: `
    <h1>Async Pipe Example</h1>
    <p>Current time: {{ currentTime$ | async }}</p>
  `
})
export class AppComponent {
  currentTime$: Observable<Date>;

  constructor() {
    this.currentTime$ = interval(1000).pipe(
      map(() => new Date())
    );
  }
}

The currentTime$ observable is created using the interval an operator from RxJS, which emits a sequential number every 1 second.
We then use the map operator to transform the emitted number into a Date object representing the current time.
In the template, we use the async pipe to directly bind the value of currentTime$ to the {{ currentTime$ | async }} expression, which will automatically handle subscribing and unsubscribing from the observable.
This way, the template will always display the current time, updating every second as new values are emitted by the observable.

When should I use Async Pipe with ngIf?
When you wish to conditionally show content based on the outcome of an asynchronous operation or the existence of data from an asynchronous source, you can use the ngIf directive and async pipe.

Here are some typical situations in which ngIf and async pipe might be used.

  • Data Loading: ngIf with async pipe can be used to display a loading message or spinner until the data is loaded and ready to be displayed when retrieving data from an API or carrying out an asynchronous action.
  • Authentication and Authorization: ngIf with async pipe can conditionally show or hide specific UI components based on the user's permissions and access privileges when implementing authentication and authorization in an application.
  • Conditional Rendering: ngIf with async pipe is used to conditionally render different sections of a template based on the status of the asynchronous operation if you have conditional logic in your template that depends on the outcome of an asynchronous operation.

Example of ngIf and Async Pipe

Here, we have an AppComponent that declares an Observables called data$. The data$ observable simulates an asynchronous data retrieval using the of operator and delay operator from RxJS.
import { Component } from '@angular/core';
import { Observable, of } from 'rxjs';
import { delay } from 'rxjs/operators';
>
@Component({
  selector: 'app-root',
  template: `
    <div *ngIf="data$ | async as data; else loading">
      <h1>Data is loaded:</h1>
      <p>{{ data }}</p>
    </div>

    <ng-template #loading>
      <h1>Loading data...</h1>
    </ng-template>
  `,
})
export class AppComponent {
  data$: Observable<string>;

  constructor() {
    // Simulating an asynchronous data retrieval
    this.data$ = of('Hello, world!').pipe(delay(2000));
  }
}


TypeScript

  • We conditionally display content in the template based on the completion of the data$ observable by using the ngIf directive.
  • Before assigning the value to the data variable using the as syntax, the data$ observable must be subscribed to and retrieved using the async pipe.
  • The loaded data is shown inside the ngIf block, and a loading message is shown inside the ng-template with the #loading reference.
  • The template will show the value that is emitted by the data$ observable. The loading notice will appear until then.
  • The async pipe handles subscription and automatically updates the UI when the observable emits new values or when it completes.

By using ngIfwith asyncpipe, you can simplify your code and let Angular handle the management of subscriptions and automated changes of the view when the asynchronous operation finishes or emits new values. In general, you can write more succinct and clear code for managing asynchronous operations and conditional rendering in Angular applications by utilizing ngIf with async pipe.



AngularJS Hosting Europe - HostForLIFE :: What Does an Angular Protractor Mean?

clock January 5, 2024 06:44 by author Peter

Angular Protractor
An end-to-end (E2E) testing framework created especially for Angular applications is called Protractor. It is a popular open-source tool for automating Angular application testing that was created by the Google Angular team. Here are a few additional Protractor details:


Built on WebDriverJS
WebDriverJS, the JavaScript binding for Selenium WebDriver, is the foundation upon which Protractor is constructed. A popular framework for browser automation, Selenium WebDriver enables programmers to create scripts that automate browser interactions.

Features Specific to Angles
With capabilities that make testing Angular-specific functionality easier, Protractor is designed with Angular apps in mind. It is aware of the inner workings of Angular apps, including how asynchronous activities are handled and the Angular digest cycle.

Automated Holding
The automated waiting mechanism of Protractor is one of its primary characteristics. As asynchronous operations are common in Angular apps, Protractor automatically waits for Angular to stabilize before carrying out commands. This aids in managing situations where page elements are still loading or updating.

Declarative Grammar
Protractor tests are created in a behavior-driven development (BDD) methodology, usually with a declarative syntax. For developers who are familiar with popular testing frameworks like Jasmine or Mocha, Protractor can be utilized with them.

Support for Page Object Models
The Page Object Model (POM) is a design pattern that Protractor recommends using to manage and organize the structure of your automation code. This aids in developing a test codebase that is more modular and maintainable.

Testing Across Browsers
Cross-browser testing is supported by Protractor, enabling you to run your tests across various browsers, including Chrome, Firefox, and Safari. This makes it more likely that your Angular application will function properly in different browsers.

Combining Testing Frameworks with Integration
Popular testing frameworks such as Mocha and Jasmine are easily integrated with Protractor. This makes it possible for developers to take advantage of the testing tools offered by these frameworks, such as test reporting, assertions, and descriptive test names.

Configuration File: Protractor uses a configuration file, usually called protractor.conf.js, in which you can set up the browser's configurations, the testing framework, and other parameters. This facilitates test suite configuration and management.

This is a basic illustration of a file used to configure Protractor:

exports.config = {
  framework: 'jasmine',
  capabilities: {
    browserName: 'chrome'
  },
  specs: ['spec.js'],
  baseUrl: 'http://localhost:4200'
};

An effective solution for automating Angular application end-to-end testing is Protractor. It is a great option for large-scale Angular application testing because of its features and design, which are well suited to the subtleties of Angular development.



Node.js Hosting - HostForLIFE :: Using Express to Create a Node.js API with Swagger Support

clock January 2, 2024 06:50 by author Peter

Overview of Swagger in Node.js
An effective tool for planning, creating, and documenting APIs is Swagger. It gives developers a consistent vocabulary to define RESTful APIs, which facilitates their comprehension, consumption, and interaction with API endpoints. Swagger can be very helpful when producing documentation for Node.js applications that is both machine- and human-readable.

Essential Elements of Swagger
Swagger Specification/OpenAPI: A standard for characterizing RESTful APIs, the Swagger Specification is now the OpenAPI Specification. It establishes a format for machine-readable documentation of the architecture and operation of APIs.

The specification describes parameters, authentication techniques, request/response formats, API endpoints, and more in JSON or YAML.

A user-friendly interface for visualizing and interacting with the Swagger/OpenAPI documentation is called Swagger UI. It enables developers to test endpoints, investigate the API, and comprehend the typical formats for requests and responses.

The Swagger Specification is used to automatically construct the User Interface (UI), which offers an interactive method of interacting with the API.

Swagger Codegen: Based on the Swagger Specification, this tool creates client libraries, server stubs, and API documentation. This can be especially useful for preserving consistency between an API's client and server components.

Integrating Swagger in a Node.js API

To integrate Swagger into a Node.js API, you can follow these step-by-step:
Step 1. Install Necessary Packages

Use npm to install the two required packages, such as express, swagger-jsdoc, and swagger-ui-express.

1. Swagger-jsdoc

npm install swagger-jsdoc --save

2. Swagger-ui-express
npm install swagger-ui-express --save

Go to the project folder and open the terminal to install the required packages.

You can verify whether the package.json package was added or not after installation.

Step 2. Create Swagger Configuration
Write a Swagger configuration file that describes the API using JSDoc comments in the code. This configuration includes information such as API title, version, paths, parameters, and responses.

index.js

const options = {
  definition: {
    openapi: '3.0.0',
    info: {
      title: 'Student Management System',
      version: '1.0.0',
      description: 'Student Management System covered Create, Read, Update, and Delete operations using a Node.js API',
    },
    servers:[
      {url:'http://localhost:5000/api'}, //you can change you server url
    ],
  },

  apis: ['./routes/*.js'], //you can change you swagger path
};

Step 3: Use Swagger Middleware Integration
For your Express.js application, you can use middleware packages such as swagger-jsdoc and swagger-ui-express to integrate Swagger. This middleware serves the Swagger UI and dynamically creates the Swagger Specification.

index.js
1. Import the middleware packages that are needed.

const swaggerUi = require('swagger-ui-express');
const swaggerJsdoc = require('swagger-jsdoc');

JavaScript

2 . Initialize Swagger-jsdoc.

const specs = swaggerJsdoc(options);

JavaScript

3. Serve Swagger documentation using Swagger UI.

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs));

JavaScript
Step 4. Define API Routes

Define the API routes using Express.js as usual. Swagger will automatically pick up the route information from the code comments.

Add the Swagger in studentRoute.js

1. API route : router.get("/student", getAllStudents);
Get all students
/**
 * @swagger
 * /student:
 *   get:
 *     summary: Get a list of all students
 *     tags: [Students]
 *     responses:
 *       200:
 *         description: Successful response
 *         content:
 *           application/json:
 *             example:
 *               data: [{}]
 *       400:
 *         description: Bad Request
 *         content:
 *          application/json:
 *            example:
 *             error:
 *              message: "Bad Request"
 */
//Get All Students
router.get("/student", getAllStudents);


2. API route: router.get("/student/:id", getStudent);

Get the Student by ID
/**
 * @swagger
 * /student/{id}:
 *   get:
 *     summary: Get a student by ID
 *     tags: [Students]
 *     parameters:
 *       - name: id
 *         in: path
 *         required: true
 *         description: The ID of the student
 *         schema:
 *           type: string
 *         example:
 *             658918e852a0131af4c0aab1
 *     responses:
 *       200:
 *         description: Successful response
 *         content:
 *           application/json:
 *             example:
 *               data: [{}]
 *       404:
 *         description: Student not found
 */


//Get the Student
router.get("/student/:id", getStudent);


3. API route: router.post("/student", createStudent);
Create a new student
/**
 * @swagger
 * /student:
 *   post:
 *     summary: Create a new student
 *     tags: [Students]
 *     requestBody:
 *       description: Student object to be added
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             properties:
 *               name:
 *                 type: string
 *               address:
 *                 type: string
 *               dateOfBirth:
 *                 type: date
 *               gender:
 *                 type: string
 *               phoneNum:
 *                 type: integer
 *             example:
 *                name: "John Doe"
 *                address: "Colombo - Srilanka "
 *                dateOfBirth: 07/14/1990
 *                gender: "male"
 *                phoneNum: 01145252525
 *     responses:
 *       201:
 *         description: Successful response
 *         content:
 *           application/json:
 *             example:
 *               data: [{}]
 *       400:
 *         description: Invalid request
 */


//Create Student
router.post("/student", createStudent);


4. API route: router.put("/student/:id", updateStudent);
Update a student by ID

/**
 * @swagger
 * /student/{id}:
 *   put:
 *     summary: Update a student by ID
 *     description: Update the details of a student by providing the student ID.
 *     tags: [Students]
 *     parameters:
 *       - in: path
 *         name: id
 *         description: The ID of the student to be updated.
 *         required: true
 *         schema:
 *           type: string
 *     requestBody:
 *       description: Updated student information
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             properties:
 *               name:
 *                 type: string
 *               address:
 *                 type: string
 *               dateOfBirth:
 *                 type: string
 *                 format: date
 *               gender:
 *                 type: string
 *               phoneNum:
 *                 type: integer
 *     responses:
 *       200:
 *         description: Successful update
 *         content:
 *           application/json:
 *             example:
 *               message: 'Student updated successfully'
 *       404:
 *         description: Student not found
 *         content:
 *           application/json:
 *             example:
 *               message: 'Student not found'
 */


//put the Student
router.put("/student/:id", updateStudent);


5. API route: router.delete("/student/:id", deleteStudent);
Delete a student by ID
/**
 * @swagger
 * /student/{id}:
 *   delete:
 *     summary: Delete a student by ID
 *     tags: [Students]
 *     parameters:
 *       - name: id
 *         in: path
 *         required: true
 *         description: The ID of the student
 *         schema:
 *           type: integer
 *         example:
 *             658918e852a0131af4c0aab1
 *     responses:
 *       204:
 *         description: Student deleted successfully
 *       404:
 *         description: Student not found
 */
//Delete the Student
router.delete("/student/:id", deleteStudent);


Step 5. Run The Application
Start the Node.js application, npm start
Access the Swagger documentation by visiting the specified endpoint, usually /api-docs or a custom path. Example:  http://localhost:5000/api-docs/

Following these steps, you can enhance your Node.js API with interactive and well-documented Swagger/OpenAPI documentation, making it easier for developers to understand, test, and integrate with your API.

1. Go to the swagger path  http://localhost:5000/api-docs/

2. Click on the Try it out button.

3. Click on the Execute button, and get the response.

4. Get the Response.

 

The tutorial walks readers through the process of using Express to create a Node.js API that supports Swagger. To include Swagger into a Node.js API, install the required libraries, make a Swagger configuration file, then use Express.js to define the API routes.

With an emphasis on using Swagger annotations in JSDoc comments to automatically generate interactive Swagger documentation, the book offers thorough code examples for every step. The last section explains how to launch the application and use Swagger UI to view the documentation, which enables developers to easily comprehend, test, and work with the API. The procedures are illustrated clearly in the accompanying photos, which also show how to use the Swagger UI and submit API queries.



AngularJS Hosting Europe - HostForLIFE :: Using Angular CLI 17.0.6, Node: 20.0.1, and npm 10.2.3 on Windows, Create Your First Angular

clock December 19, 2023 06:08 by author Peter

On November 6, 2023, Angular 17 was launched, and I wanted to create my first application with it. These instructions will help you create your first Angular 17 application. With the exception of a few advanced capabilities that must be enabled, this is essentially the same if you have expertise with earlier Angular versions. In addition to a fresh style, Angular 17 introduces several new capabilities for developers and performance. Additionally, Angular17 has well-managed documentation.

Developing an Angular 17 Application
Required conditions

Install the most recent LTS version of NODE JS. I've utilized 20.10.0. Installing and downloading this can be done at https://nodejs.org/en.
During installation, make sure to tick the set Path in the Environment Variables option.

Installing Angular CLI is a required that will be done concurrently with node js installation.
After the installation is complete, use CMD to verify the installed version of the node.

Enter "node -v" in the command window. This screen grab below displays the version that I have installed.

After Node js has been successfully installed, Typescript needs to be installed. Try using the admin version of cmd. Given that folder rights were restricted, I knew I had to take this action. I've included some instructions below in case you're operating through a proxy.

CMD "npm install –g typescript" should be run.

if any of the following mistakes happen. CERT_IN_CHAIN_SELF SIGNED.

I got around the certificate, which is the above error, with this cmd. "npm config set strict-ssl false" Strict SSL configuration will now be set to false. If the installation goes well, it will seem like the screen below, which indicates that the installation was successful.

Run the command "npm install -g @angular/cli@latest" as shown above the screen. It does say about funding which is to ask for funds.
Some of these packages installed are probably asking for funds. (optional)

You can check the version installed using the command "ng version"

Now that the prerequisites have been met, use the command "ng new {APPName}" to begin building a new Angular17 application. The CLI will inquire about the type of styling you want to use and whether you need to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering) when you create a new application.

When user interaction with the backend is required, server-side rendering is employed.

To launch the ng serve –o application, use this command. Your browser will launch it at http://localhost:4200/.


Thank you, and Hopefully, this article helped you get started with creating an angular 17 application.



AngularJS Hosting Europe - HostForLIFE :: In an Angular Application, Create a Custom Search Filter Pipeline

clock December 13, 2023 06:14 by author Peter

This post will teach us how to use an Angular application to design a custom search filter pipe.


Required conditions

Basic familiarity with Angular 2 or later; installation of Node and NPM; Visual Studio Code; Bootstrap (Optional)
The command to create an Angular project is as follows.
ng new angapp

Now install Bootstrap by using the following command.
npm install bootstrap --save

Now open the styles.css file and add Bootstrap file reference. To add a reference in the styles.css file add this line.
@import '~bootstrap/dist/css/bootstrap.min.css';

Create Search Filter Pipe
Now create a custom pipe by using the following command.
ng generate pipe searchfilter

Now open searchfilter.pipe.ts file and add following code.
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ name: 'searchFilter' })
export class FilterPipe implements PipeTransform {
   transform(value: any, args?: any): any {
    if (!value) return null;
    if (!args) return value;

    args = args.toLowerCase();
    debugger;
    return value.filter(function(item:any) {
      return JSON.stringify(item)
        .toLowerCase()
        .includes(args);
    });
  }
}

Now import this pipe into the app module.Add following code in app.module.ts.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { FilterPipe } from './searchfilter.pipe';
import { SearchlistComponent } from './searchlist/searchlist.component';
@NgModule({
  declarations: [
    AppComponent,FilterPipe,SearchlistComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }


Now create a new component by using the following command.
ng g c searchlist

Now open searchlist.component.html file and add the following code.
<div class="container">
    <div class="card">
        <div class="form-group">
            <label for="search-text">Search Text</label>
            <input type="email" class="form-control" id="search-text" aria-describedby="search-text"
                [(ngModel)]="searchText" placeholder="Enter text to search" autofocus>
        </div>
        <ul class="list-group list-group-flush">
            <li class="list-group-item" *ngFor="let user of userlist | searchFilter: searchText">
                {{user.firstName}}
            </li>
        </ul>
    </div>
</div>

Now open searchlist.component.ts file and add the following code.
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
  selector: 'app-searchlist',
  templateUrl: './searchlist.component.html',
  styleUrls: ['./searchlist.component.css']
})
export class SearchlistComponent implements OnInit {
  data: any;
  searchText = '';
  userlist: any;
  constructor(private httpclient: HttpClient) {
  }
  ngOnInit(): void {
    this.httpclient.get('https://dummyjson.com/users').subscribe((res: any) => {
      this.data = res
      this.userlist = this.data.users;
      console.log(this.userlist);
    })
  }
}


Now open app.component.html file and add the following code.
<div class="container" style="margin-top:10px;margin-bottom: 24px;">
  <div class="col-sm-12 btn btn-info">
    Create Custom Search filter pipe in Angular Application
  </div>
</div>
<app-searchlist></app-searchlist>


Now run the application using npm start and check the result.

Now type some text into the box and run a search.




AngularJS Hosting Europe - HostForLIFE :: Essentials of Dependency Injection in Angular

clock December 8, 2023 08:06 by author Peter

Dependency Injection (DI) is a powerful front-end framework developed by Google that makes it easy to manage services and components inside an application. Dependencies can be received by components instead of being created directly thanks to DI, a design paradigm that encourages loose coupling. In order to better understand DI in Angular, this post will go through its core ideas, benefits, and real-world application using code samples.

Injecting Dependency in Angular
A software design technique called dependency injection makes it possible to create easily maintained, loosely linked components. DI is a method used with Angular that allows a component to obtain its dependencies from outside sources instead of generating them on its own. The Angular Injector, which is in charge of instantiating and maintaining the dependencies of different components, is usually this external source.

Dependency Injection's Advantages in Angular

  • Loose Coupling: DI encourages loose coupling, which makes it simpler to update or replace dependencies without impacting the whole program.
  • Testability: Dependencies can be easily injected to mock or test during unit testing, making DI-patterned components more testable.
  • Reusability: DI makes services and components more reusable because it makes it simple to inject them into various application sections without requiring any changes.
  • Maintainability: The codebase is more maintainable because to the concern separation made possible by DI. It is less probable for changes made to one section of the application to affect other sections.

How Dependency Injection Operates in Angular?
The Angular Injector is used in Angular to construct the DI system. In order to control the scope of dependencies, the Injector upholds a hierarchical structure while generating instances of components, services, and other objects.

Here's a quick example to help you grasp how DI functions in Angular. Think about a service known as DataService.

// data.service.ts

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})

export class DataService {
  getData(): string {
    return 'This is data from the DataService';
  }
}

To indicate that the DataService in this example is a service that may be injected into other components or services, the @Injectable decorator is used. Throughout the application, there will only be one instance of DataService thanks to the providedIn: 'root' setting.

Let's use this service to create an AppComponent component now.

// app.component.ts

import { Component } from '@angular/core';
import { DataService } from './data.service';

@Component({
  selector: 'app-root',
  template: '<h1>{{ data }}</h1>',
})

export class AppComponent {
  data: string;
  constructor(private dataService: DataService) {
    this.data = this.dataService.getData();
  }
}


In this example, the AppComponent class has a constructor that takes an instance of DataService as a parameter. The Angular Injector automatically injects the appropriate instance when creating an AppComponent.

import { Component, Injector } from '@angular/core';
import { DataService } from './data.service';

@Component({

  selector: 'app-root',
  template: '<h1>{{ data }}</h1>',

})

export class AppComponent {
  data: string;
  constructor(private injector: Injector) {
    const dataService = this.injector.get(DataService);
    this.data = dataService.getData();
  }
}


In this example, we inject the Injector itself and then use it to manually get an instance of the DataService. While manual injection is rarely needed, it provides a way to have more control over the injection process.

In summary
A key idea in Angular that enhances the framework's adaptability, testability, and maintainability is dependency injection. You may build scalable and modular Angular applications by comprehending DI and applying it into your application architecture. The hierarchical structure enables for fine-tuning the scope of dependencies, while the automatic injection offered by the Angular Injector makes dependency management easier.

Adopting and understanding Dependency Injection will definitely improve the overall architecture and code quality as you continue to develop Angular applications.



About HostForLIFE

HostForLIFE is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Tag cloud

Sign in