Full Trust European Hosting

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

Node.js Hosting Europe - HostForLIFE :: Difference Between Node Cache And Redis Cache

clock July 26, 2022 10:15 by author Peter

What is Caching and why it is required?
When the same response needs to be served multiple times, store the data in a temporary memory cache and it can be retrieved faster than the data retrieved from the storage layer for every single call. Caching is an ability of an application to duplicate the values for a specified period of time and serve the web request instantly.


These techniques will be effective when
    There is a need to call for a 3rd party API and the call counts
    Cost of data transfer between cloud and the server.
    Server response is critical based on the concurrent requests.

Types of server caching available in Node JS
    In-app memory Cache
    Distributed Cache

In-app memory Cache

Data storage and retrieval will be in the process of the app memory cache. In-app caching is achieved through NodeJS packages such as node-cache, memory-cache, api-cache, etc.,


Distributed Cache
Data storage and retrieval will be carried out in centralized distributed systems. Though many options are available in this category the most popular ones are Redis and Memcached.


Other aspects of these cache techniques
In the Node Cache, the cached data are accessible only in the current process. If there is a cluster deployed with load balancer then multiple caches need to be stored which leads to constant updating of the data in every system or otherwise the user fetches the wrong information.

Also, if the stored cache is not properly maintained it may result in out of memory failures since the same memory space is utilized. On the other hand if the application is restarted the cached data will be disposed.

Redis can handle the above limitations easily, still it increases the dependency of the system. And that system needs to be monitored constantly not only for the availability but also for the performance degradations, outages.

Though Redis offers features like replication, level of durability, clustering and high availability (HA) but simple node-cache will be easy if the application needs to be scaled up and down easily and quickly.

Static information stored in cache does not require a network call dependency. Node cache is faster to store and retrieve data with a TTL (Time To Live).

Things to consider before choosing the right Caching technique:
    Security risks for storing and retaining the data in the cache.
    Data object serialization is really required for storing the data.
    Prevention of App crash by handling cache failures due to memory leaks or unavailability.
    Policy creation for cache maximum size, expiration of the cached memory, frequency of writing data to cache.
    Calculating the advantages of using cached data for the application.

 



AngularJS Hosting Europe - HostForLIFE :: Angular HTTP (Web API Integration)

clock July 18, 2022 10:42 by author Peter

HttpClient is used to make HTTP requests like GET | POST | PUT | DELETE to back end server.


The Angular HTTP client module is firstly introduced in the Angular 4.3 version.

This new API is available in the package @angular/common/http. This is a replacement for the old HttpModule.

The HTTP Client makes use of the RxJs Observables. The Response from the HttpClient Is observable, hence it needs to be Subscribed.

Import HttpClient Module in Root Module

STEP 1
The first thing is to import the HttpClientModule in app.module.ts
import {
    HttpClientModule
} from '@angular/common/http';
imports: [
    HttpClientModule
],


Import Required Module in Component/Service and then Inject HttpClient service
import {
    HttpClient
} from '@angular/common/http';
constructor(public http: HttpClient) {}


STEP 2
Define your base URL of API and inject the HttpClient in service constructor then define your GET/POST/PUT/DELETE calls as shown below
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';

import {  Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { User } from '../User';

@Injectable({
  providedIn: 'root'
})
export class UserService {
    private apiURL = "http://localhost:56299/api/"; //YOUR API URL
    httpOptions = {
        headers: new HttpHeaders({
            'Content-Type': 'application/json'
        })
    }
    constructor(private httpClient: HttpClient) {}
    getUsers(): Observable < User[] > {
        return this.httpClient.get < User[] > (this.apiURL + 'userapi/').pipe(catchError(this.errorHandler));
    }
    addUser(user: User): Observable < User > {
        return this.httpClient.post < User > (this.apiURL + 'userapi/', JSON.stringify(user), this.httpOptions).pipe(catchError(this.errorHandler))
    }
    getUsersByID(id: number): Observable < User > {
        return this.httpClient.get < User > (this.apiURL + '/userapi/' + id).pipe(catchError(this.errorHandler))
    }
    updateUser(user: User): Observable < User > {
        return this.httpClient.put < User > (this.apiURL + '/userapi/' + user.id, JSON.stringify(user), this.httpOptions).pipe(catchError(this.errorHandler))
    }
    removeUser(id: number) {
        return this.httpClient.delete < User > (this.apiURL + 'userapi/' + id, this.httpOptions).pipe(catchError(this.errorHandler));
    }
    errorHandler(error: {
        error: {
            message: string;
        };status: any;message: any;
    }) {
        let errorMessage = '';
        if (error.error instanceof ErrorEvent) {
            errorMessage = error.error.message;
        } else {
            errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
        }
        return throwError(errorMessage);
    }
}


STEP 3
In your component file subscribe to the service to get the response
//GET
this.userService.getUsers().subscribe((data: User[]) => {
    this.userList = data;
});
//DELETE
this.userService.removeUser(id).subscribe(() => {
    this.refreshUser();
});
//POST
this.userService.addUser(this.userform.value).subscribe((data: User) => {
    //Redirecting to user List page after save or update
    this.router.navigate(['/user']);
});
//PUT
this.userService.updateUser(this.userform.value).subscribe((data: User) => {
    //Redirecting to user List page after save or update
    this.router.navigate(['/user']);
});



AngularJS Hosting Europe - HostForLIFE :: Angular Forms

clock July 13, 2022 08:43 by author Peter

User INPUT data are collected using Angular forms.

There are two approaches by which we can create forms in angular.
    Template Driven Forms
    Model Driven Forms

1. TEMPLATE DRIVEN FORMS
First, we build a simple Contact form. The ngForm directive will convert it to the Template-driven form and create the top-level FormGroup control.\
Next, we use the ngModel directive to create the FormControl instance for each of the HTML form elements.
<form #contactForm="ngForm" (ngSubmit)="onSubmit(contactForm)">
  <h1 class="text-center"> <strong> ANGULAR TEMPLATE DRIVEN FORM DEMO</strong></h1>
  <br>
  <div class="container">
    <div class="row">
      <div class="col-md-6">
        <div class="mb-1">
          <label class="form-label" for="firstname">First Name</label>
          <div class="input-group">
            <input type="text" class="form-control" name="firstname" ngModel>
          </div>
        </div>
        <div class="mb-1">
          <label class="form-label" for="lastname">Last Name</label>
          <div class="input-group">
            <input type="text"  class="form-control" name="lastname" ngModel>
          </div>
        </div>
        <div class="mb-1">
          <label class="form-label" for="email">Email </label>
          <div class="input-group">
            <input type="text" class="form-control" id="email" name="email" ngModel>
          </div>
        </div>
        <div class="mb-1">
          <label class="form-label" for="gender">Geneder</label>
          <div class="input-group">
            <input type="radio" value="male" name="gender" ngModel> Male
            <input type="radio" value="female" name="gender" ngModel> Female
          </div>
        </div>
        <div class="mb-1">
          <label class="form-label" for="isMarried">Married</label>
          <div class="input-group">
            <input type="checkbox" name="isMarried" ngModel>
          </div>
        </div>
        <div class="mb-1">
          <label class="form-label" for="country">Country</label>

          <div class="input-group">
            <select name="country"  class="form-control" ngModel>
              <option [ngValue]="c.id" *ngFor="let c of countryList">
                {{c.name}}
              </option>
            </select>
          </div>
        </div>
        <div ngModelGroup="address">
          <div class="mb-1">
            <label class="form-label" for="city">City</label>
            <div class="input-group">
              <input type="text" class="form-control" name="city" ngModel>
            </div>
          </div>
          <div class="mb-1">
            <label class="form-label" for="street">Street</label>
            <div class="input-group">
              <input type="text" class="form-control" name="street" ngModel>
            </div>
          </div>
          <div class="mb-1">
            <label class="form-label" for="pincode">Pin Code</label>
            <div class="input-group">
              <input class="form-label" class="form-control" type="text" name="pincode" ngModel>
            </div>
          </div>
          <div class="mb-1">
            <div class="input-group">
              <button class="btn btn-primary" type="submit">Submit</button>
            </div>
          </div>

      </div>
      </div>
      <div class="col-md-6">
        <pre>Value : {{contactForm.value | json }} </pre>
        <pre>Valid : {{contactForm.valid}} </pre>
        <pre>Touched : {{contactForm.touched  }} </pre>
        <pre>Submitted : {{contactForm.submitted  }} </pre>
      </div>
    </div>
  </div>
  </form>


Next, we will submit the form data to the component class.
import { Component, OnInit } from '@angular/core';
export class country {
  id:string;
  name:string;

  constructor(id:string, name:string) {
    this.id=id;
    this.name=name;
  }
}
@Component({
  selector: 'app-templatedrivenform',
  templateUrl: './templatedrivenform.component.html',
  styleUrls: ['./templatedrivenform.component.css']
})
export class TemplatedrivenformComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }
  countryList:country[] = [
    new country("1", "India"),
    new country('2', 'USA'),
    new country('3', 'England')
  ];
  onSubmit(contactForm: { value: any; }) {
    console.log(contactForm.value);
  }

}

OUTPUT


2. MODEL DRIVEN FORMS (REACTIVE FORMS)
In Reactive forms we define the structure of the form in the component class. i.e. We define the form model with Form Groups, Form Control and Form Arrays. And then we define validation rules in the component class. And finally, we bind it to the HTML form in the template.
How to use Reactive Forms

    Import ReactiveFormsModule
    Defining Form Model in the component
    Create the HTML Form uses the Form Model properties.Bind the HTML Form to the Form Model

1. Import ReactiveFormsModule
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

 imports: [

     //  Angular Form Modules
    FormsModule,
    ReactiveFormsModule
  ],


2. Defining Form Model in the component
FormGroup Represents a collection of form controls. It can also contain other Form Groups and FormArrays. In fact, an angular form is a FormGroup.

FormControl Encapsulates the state of a single form element in our form. It stores the value and state of the form element and helps us to interact with them using properties & methods.
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { UserService } from '../service/user.service';

@Component({
  selector: 'app-add-user',
  templateUrl: './add-user.component.html',
  styleUrls: ['./add-user.component.css']
})
export class AddUserComponent implements OnInit {

  id: number = 0;
  userform: FormGroup;

  constructor(
    private route: ActivatedRoute,
    private router: Router,
    private fb: FormBuilder,
    private userService: UserService
  ) {
    //**************Create Reactive Form with validation********************* */
    this.userform = this.fb.group({
      name: ['', [Validators.required]],
      mobile: ['', []],
      email: ['', [Validators.required, Validators.email, Validators.pattern('^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}$')]],
      gender: ['', [Validators.required]],
      dob: [null, [Validators.required]],
      id: [0, [Validators.required]],
      isActive: [true],
      rating: [0, []],
      userType: ['', [Validators.required]],
    });

  }

  ngOnInit(): void {
    //**************Get User ID On Edit********************* */
    this.route.params.subscribe(params => {
      this.id = params['id'];
      if (params['id'] != null) {
        this.userform.get('Id')?.setValue(params['id']);
        const data = this.userService.getUsersByID(this.id);
        if (data) {
          this.userform.setValue(data);
        }
      }
    });
  }

  save() {
    if (this.userform.invalid) // true if any form validation fail
      return

    if (this.userform.get('id')?.value === 0) {
      // on Create New User
      this.userService.addUser(this.userform.value);
    } else {
      // on Update User info
      this.userService.updateUser(this.userform.value);
    }

    //Redirecting to user List page after save or update
    this.router.navigate(['/user']);
  }

}


3. User Form
<div class="container">
  <form [formGroup]="userform" autocomplete="off">
      <div class="mb-1">
          <label for="name" class="form-label">Name</label>
          <div class="input-group has-validation">
              <input type="text" #name [ngClass]="{'form-control': true, 'is-invalid': userform.get('name')?.invalid &&
              (userform.get('name')?.dirty || userform.get('name')?.touched)}" id="name" name="name"
                  formControlName="name" placeholder="Name">
              <div class="invalid-feedback">
                  This field is required.
              </div>
          </div>
      </div>
      <div class="mb-1">
          <label for="mobile" class="form-label">Mobile</label>
          <div class="input-group has-validation">
              <input type="number" maxlength="10" [ngClass]="{'form-control': true, 'is-invalid': userform.get('mobile')?.invalid &&
              (userform.get('mobile')?.dirty || userform.get('mobile')?.touched)}" id="mobile" name="mobile"
                  formControlName="mobile" placeholder="Mobile">
              <div class="invalid-feedback">
                  This field is required.
              </div>
          </div>
      </div>
      <div class="mb-1">
          <label for="rating" class="form-label">Rating</label>
          <div class="input-group has-validation">
            <input type="number" maxlength="10" [ngClass]="{'form-control': true, 'is-invalid': userform.get('rating')?.invalid &&
            (userform.get('rating')?.dirty || userform.get('rating')?.touched)}" id="rating" name="rating"
                formControlName="rating" placeholder="rating">
              <div class="invalid-feedback">
                  This field is required.
              </div>
          </div>
      </div>
      <div class="mb-1">
          <label for="email" class="form-label">Email</label>
          <div class="input-group has-validation">
              <input type="email" [ngClass]="{'form-control': true, 'is-invalid': userform.get('email')?.invalid &&
                  (userform.get('email')?.dirty || userform.get('email')?.touched)}" id="email" name="email"
                  formControlName="email" placeholder="[email protected]">
              <div class="invalid-feedback">
                  {{userform.get('email')?.hasError('required') ? 'This field is required.':'Invalid Email'}}
              </div>
          </div>
      </div>
      <div class="mb-1">
          <label for="DOB" class="form-label">DOB</label>
          <input type="date" [ngClass]="{'form-control': true, 'is-invalid': userform.get('dob')?.invalid &&
                  (userform.get('dob')?.dirty || userform.get('dob')?.touched)}" id="dob" name="dob"
                  formControlName="dob">
      </div>
      <div class="mb-1">
          <label for="email" class="form-label">Gender {{userform.get('gender')?.value}} </label>
          <div class="input-group has-validation">
              <select [ngClass]="{'form-select': true, 'is-invalid': userform.get('gender')?.invalid &&
                  (userform.get('gender')?.dirty || userform.get('gender')?.touched)}"
                  aria-label="Default select example" formControlName="gender">
                  <option value=""> --Select--</option>
                  <option value="Male" selected="userform.get('gender')?.value=='Male'">Male</option>
                  <option value="Female" selected="userform.get('gender')?.value=='Female'">Female</option>
              </select>
              <div class="invalid-feedback">
                  This field is required.
              </div>
          </div>
      </div>
      <div class="mb-1">
          <label for="name" class="form-label">User Type</label>
          <div class="input-group has-validation">
              <div class="form-check form-check-inline">
                  <input class="form-check-input" formControlName="userType" type="radio" id="User" value="User">
                  <label class="form-check-label" for="User">User</label>
              </div>
              <div class="form-check form-check-inline">
                  <input class="form-check-input" formControlName="userType" type="radio" id="Admin" value="Admin">
                  <label class="form-check-label" for="Admin">Admin</label>
              </div>
          </div>
      </div>
      <div class="mb-1">
          <div class="form-check form-switch">
              <input class="form-check-input" type="checkbox" formControlName="isActive" id="isActive">
              <label class="form-check-label" for="isActive">Is Active</label>
          </div>
      </div>
      <div class="mb-1">
          <div class="btn-group" role="group" aria-label="Basic example">
              <button (click)="save()" [disabled]="userform.invalid" class="btn btn-primary" type="button">
                  {{id==0 || id==null ?'Save':'Update'}}</button>
              <button class="btn btn-secondary" type="button">Reset </button>
          </div>
      </div>

      <div class="mb-1">
          {{userform.value |json}}
      </div>
  </form>
</div>

OUTPUT

 



Node.js Hosting Europe - HostForLIFE :: How To Check If A File Exists In NodeJS?

clock July 6, 2022 10:29 by author Peter

Node.js comes bundled with the file system module which allows the developers to interact with the file system of the operating system. This module is commonly used to create, read, update, delete and rename a file. However, before we start performing the above-mentioned operations it is always a better idea to check if the file we're trying to access exists in the file system. And the file system module provides multiple ways to perform this check.
Using existsSync method

The easiest way to test if a file exists in the file system is by using the existsSync method. All you need to do is pass the path of the file to this method.
const fs = require('fs');
const path = './my-awesome-file.txt';

if (fs.existsSync(path)) {
  console.log('file exists');
} else {
  console.log('file not found!');
}


The existsSync method will return true if the file exists and else it'll return false.
One thing that we need to keep in mind is this method is synchronous in nature. that means that it’s blocking.

Using exists method (Deprecated)
The exists method checks for the existence of a file asynchronously. It accepts two parameters:
    Path to the file
    Callback function to execute once path is verified passing a boolean parameter value to the function as its argument.
const fs = require('fs');
const path = './my-awesome-file.txt';

fs.exists(path, function (doesExist) {
  if (doesExist) {
    console.log('file exists');
  } else {
    console.log('file not found!');
  }
});


The parameter value will be true when the file exists otherwise it'll be false.

Using accessSync method
The accessSync method is used to verify the user’s permission for the specified path. If the path is not found, it will throw an error that we need to handle using try...catch block.

This method accepts two parameters as follows,
    Path to the file
    Mode of verification

The mode parameter is optional. It specifies the accessibility checks that need to be performed.0

Following constants can be used as the second parameter to specify the mode.
      fs.constants.R_OK to check for read permission
    fs.constants.W_OK to check for write permission
    fs.constants.X_OK to check for execute permission

If the second parameter is not provided it defaults to  fs.constants.F_OK constant.
const fs = require('fs');
const path = './my-awesome-file.txt';

try {
  fs.accessSync(path);
  console.log('file exists');
} catch (err) {
  console.log('file not found');
  console.error(err);
}

The above code verifies the existence of my-awesome-file.txt file:

If you wish to determine the write and read access, you can pass the mode parameter with a bitwise OR operator as follows:
const fs = require('fs');
const path = './my-awesome-file.txt';

try {
  fs.accessSync(path, fs.constants.R_OK | fs.constants.W_OK);
  console.log('read/write access');
} catch (err) {
  console.log('no access:');
  console.error(err);
}


Using access method
The access method is basically the asynchronous version of accessSync method.

The access method allows the developers to verify the existence or permissions of a specified path asynchronously.

The method accepts three parameters, first two parameters are the same as accessSync method parameters, and last parameter is a callback function:
    Path to the file
    Mode of verification
    The callback function to execute

const fs = require('fs')
const path = './my-awesome-file.txt'

fs.access(path, fs.F_OK, (err) => {
  if (err) {
    console.error(err)
    return;
  } else {
    console.log('file exists')
  }
})


existsSync, exists, accessSync, and access are the four methods that allow the developers to verify if the file exists in the file system. It’s recommended to use existsSync method if you only wish to check for the existence of a file. When you wish to check for specific permissions as well as the existence of the file, you can use either accessSync or access method. The exists method is deprecated from node.js and hence needs to be avoided. 



AngularJS Hosting Europe - HostForLIFE :: Angular 14 New Features

clock July 1, 2022 08:53 by author Peter

How to install Angular 14?
Angular 14 could be installed via npm using the next flag.

Simply open a new command line interface and run the following command to install the latest version of Angular:
    npm install --global @angular/cli@next

This will install the latest version of Angular CLI globally on your development machine.

Check the angular CLI version using below command
    ng version

Angular 14 Features
1. Standalone Components
With the release of Angular 14, standalone components will, at last, be a feasible option, and Angular modules will no longer be required.

A standalone component is not declared in any existing NgModule, and it directly manages its own dependencies (instead of having them managed by an NgModule) and can be depended upon directly, without the need for an intermediate NgModule.

Key Points
    Standalone component has the flag "standalone" we need to set the value true.
    Not Required to add the standalone component in ngModule.
    We can import the required modules in the component itself.
    Command,
    ng g c standalonedemo --standalone

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

@Component({
    selector: 'app-standalonedemo',
    standalone: true,
    imports: [CommonModule],
    templateUrl: './standalonedemo.component.html',
    styleUrls: ['./standalonedemo.component.css']
})
export class StandalonedemoComponent implements OnInit {
    constructor() {}
    ngOnInit(): void {}
}

<div class="container pages text-justify pb-5">
    <h1 class="mb-4">Angular 14 Standalone Component</h1>
    <p>standalonedemo works!</p>
</div>


2. Typed Forms
The most common request for an Angular feature on GitHub is for strictly typed forms, which, would improve the framework’s model-driven approach to the process of dealing with forms.
Key Points
    This feature is only for reactive forms.
    For using this feature tsconig.js should be in strict mode.
    Typed forms ensure that the values inside of form control, groups and array are type safe across the entire API surface.
    This helps developer for generating safer forms and it helps in case of complex nested object.
    If you want to use the older version you can use the untyped version.

E.g. create a contact us standalone component and add 4 fields in it (name, number, email, message) and import ReactiveFormsModule in it as shown below,
import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule, UntypedFormControl, UntypedFormGroup } from '@angular/forms';

@Component({
    selector: 'app-contactus',
    standalone: true,
    imports: [CommonModule, ReactiveFormsModule],
    templateUrl: './contactus.component.html',
    styleUrls: ['./contactus.component.css']
})
export class ContactusComponent implements OnInit {
    constructor() {}
    ngOnInit(): void {}
    contactForm = new FormGroup({
        name: new FormControl < string > (''),
        email: new FormControl(''),
        message: new FormControl(''),
        number: new FormControl()
    });
    contactFormUntyped = new UntypedFormGroup({
        name: new UntypedFormControl(''),
        email: new FormControl(''),
        message: new FormControl(''),
        number: new FormControl()
    });
    Submit() {
        console.log(this.contactForm.value);
        console.log(this.contactForm.value.email?.length); //check the null value
        console.log(this.contactForm.value.email!.length); //If you are sure value is not null
        console.log(this.contactFormUntyped.value.name.length); // throw error in browser
    }
}


<div class="container pages text-justify pb-5">
    <h1 class="mb-4">Angular 14  Typed Form</h1>
    <section class="mb-4">
        <!--Section heading-->
        <div class="row">
            <!--Grid column-->
            <div class="col-md-9 mb-md-0 mb-5">
                <form [formGroup]="contactForm" (ngSubmit)="Submit()">
                    <!--Grid row-->
                    <div class="row">
                        <!--Grid column-->
                        <div class="col-md-6">
                            <div class="md-form mb-0">
                                <input formControlName="name" type="text" class="form-control">
                                <label for="name" class="">Your name</label>
                            </div>
                        </div>
                        <!--Grid column-->
                        <!--Grid column-->
                        <div class="col-md-6">
                            <div class="md-form mb-0">
                                <input formControlName="email" type="text" class="form-control">
                                <label for="email" class="">Your email</label>
                            </div>
                        </div>
                        <!--Grid column-->
                    </div>
                    <!--Grid row-->
                    <!--Grid row-->
                    <div class="row">
                        <div class="col-md-12">
                            <div class="md-form mb-0">
                                <input formControlName="number" type="text" class="form-control">
                                <label for="subject" class="">Number</label>
                            </div>
                        </div>
                    </div>
                    <!--Grid row-->
                    <!--Grid row-->
                    <div class="row">
                        <!--Grid column-->
                        <div class="col-md-12">
                            <div class="md-form">
                                <textarea formControlName="message" type="text" rows="2" class="form-control md-textarea"></textarea>
                                <label for="message">Your message</label>
                            </div>
                        </div>
                    </div>
                    <!--Grid row-->
                    <button type="submit" class="btn btn-primary">Submit</button>
                </form>
            </div>
            <!--Grid column-->
        </div>
    </section>
</div>


3. Streamlined page title accessibility (Title Strategy)
Your page title shows the content of your page differently when you are developing applications. In Angular 13, the entire process of adding titles was streamlined with the fresh Route.title property in the Angular router. However, Angular 14 doesn't have more additional imports needed when you are adding a title to your page.

Go to the routing module where we define our routes now. We have a feature to add the title in the route and implement the TitleStrategy by extending the approuting module as shown.
import { NgModule } from '@angular/core';
import { RouterModule, RouterStateSnapshot, Routes, TitleStrategy } from '@angular/router';
import { ContactusComponent } from './contactus/contactus.component';
import { HomeComponent } from './home/home.component';
import { StandalonedemoComponent } from './standalonedemo/standalonedemo.component';

const routes: Routes = [
  {path:'',component:HomeComponent, title : "Core Knowledge Sharing"},
  { path: 'standalonedemo', component: StandalonedemoComponent, title : "Stand alone Component" },
  { path: 'contactus', component: ContactusComponent, title : "Contact Us" }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule extends TitleStrategy {
  updateTitle(snapshot: RouterStateSnapshot): void {
     const pageTitle = this.buildTitle(snapshot);
     if(pageTitle != undefined){
      document.title = "${pageTitle}"
     }
  }
}


4. Extended developer diagnostics (ng compilation)
This feature from Angular v14 delivers an extendable framework that assists better insights into your templates and offers suggestions for potential boosts. . It also checks the syntax error in our component like in contact us component you remove the reactive

E.g. you type the wrong command like ng sevre then it will give suggestion for right commands

5. Bind to protected component members
In v14, you can now bind to protected component members directly from your templates, thanks to a contribution from Zack Elliott!
@Component({
    selector: 'my-component',
    template: '{{ message }}',  // Now compiles!
})
export class MyComponent {
    protected message: string = 'Hello world';
}


6. Optional Injectors in Embedded Views
v14 adds support for passing in an optional injector when creating an embedded view through ViewContainerRef.createEmbeddedView and TemplateRef.createEmbeddedView. The injector allows for the dependency injection behavior to be customized within the specific template.

This enables cleaner APIs for authoring reusable components and for component primitives in Angular CDK.
viewContainer.createEmbeddedView(templateRef, context, {
  injector: injector,
})


7. NgModel OnPush
And finally, a community contribution by Artur Androsovych closes a top issue and ensures that NgModel changes are reflected in the UI for OnPush components.

I have two components: the first one is a simple child component with some input and basic support of [ngModel] directive via ControlValueAccesor interface. The second one is a parent component that has onPush change detection strategy and populates a value into child component via [ngModel] directive (right after that it's marked for changes via ChangeDetectorRef class). When [ngModel] is updated child component still displays an old value in the template while the component object has actual value in target property.
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core';

@Component({
    selector: 'app-onpushdemo',
    template: `<div>
  <app-child [ngModel]="value"></app-child>
</div>`,
    styleUrls: ['./onpushdemo.component.css'],
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class OnpushdemoComponent implements OnInit {
    public value: any = "old value";
    constructor(private _changeDetector: ChangeDetectorRef) {
        setTimeout(() => {
            debugger;
            this.value = "new value";
            this._changeDetector.markForCheck();
        }, 5000)
    }
    ngOnInit(): void {}
}

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

@Component({
    selector: 'app-child',
    template: `<div (click)="click()">Current Value: {{value}}.
  Click me to force change detection</div>`,
    styleUrls: ['./child.component.css'],
    inputs: ['value'],
    providers: [{
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => ChildComponent),
        multi: true
    }],
})
export class ChildComponent implements OnInit {
    constructor() {}
    public value: any;
    public onChange: (_: any) => void = (_: any) => {
        // do nothing
    };
    public onTouched: () => void = () => {
        // do nothing
    };
    public writeValue(value: any): void {
        this.value = value;
    }
    public click(): void {
        debugger;
        this.value = "child new value";
        // event just forces angular to re run change detection
    }
    public registerOnChange(fn: (_: any) => void): void {
        this.onChange = fn;
    }
    public registerOnTouched(fn: () => void): void {
        this.onTouched = fn;
    }
    ngOnInit(): void {}
}



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