Angular Developer Interview Questions for Freshers

`ng serve` and `npm start` are both commands used in web development, but they serve different purposes depending on the context. Let's look at the differences between `ng serve` and `npm start` with some examples: 1. `ng serve` Example: Let's say you're working on an Angular project and want to run it locally for development purposes. You would navigate to your project directory in the command line and run the following command:

   ng serve

This command would compile your Angular application, bundle the assets, start a development server, and watch for changes. It will then provide you with a local URL (usually http://localhost:4200) where you can access and test your application in the browser. The development server will also automatically reload the application whenever you make changes to the code. 2. `npm start` Example: Suppose you're working on a Node.js project that has a `start` script defined in the `package.json` file. The `start` script is set to execute the main application file, `index.js`. To start your application, you would navigate to the project directory and run the following command:

   npm start

This command will execute the command specified in the `start` script of the `package.json` file, which in this case is running `index.js`. It could be any command you specify. For example, you might use `npm start` to launch a web server, initiate a build process, or perform any other necessary actions to start your application in a production or deployment environment. In summary, `ng serve` is used specifically for running an Angular project locally during development, providing a development server and automatic reloading. On the other hand, `npm start` is a more generic command used in Node.js projects to execute a command specified in the `start` script, often used for starting an application in a production environment.
The `dependencies` and `devDependencies` properties in the `package.json` file are used to manage different types of dependencies in a Node.js project. Here's the difference between them: 1. `dependencies`: - The `dependencies` property is used to list the packages that are required for the project to run in a production or deployment environment. - These packages are necessary for the application's core functionality and are typically required at runtime. - When you install the project dependencies using `npm install`, the packages listed in the `dependencies` section are installed. Example:

   "dependencies": {
     "express": "^4.17.1",
     "lodash": "^4.17.21"
   }

2. `devDependencies`: - The `devDependencies` property is used to list the packages that are only required during development, such as testing frameworks, build tools, and development-specific utilities. - These packages are not necessary for the application to run in a production environment but are helpful during development and testing phases. - When you install the project dependencies along with dev dependencies using `npm install`, the packages listed in both the `dependencies` and `devDependencies` sections are installed. Example:
   "devDependencies": {
     "mocha": "^9.0.3",
     "nodemon": "^2.0.13"
   }

By separating dependencies into `dependencies` and `devDependencies`, you can distinguish between packages required for production and those required for development. This separation helps reduce the size of the production deployment by excluding unnecessary development-related packages. Conclusion To summarize, `dependencies` includes packages needed for the application to run in a production environment, while `devDependencies` includes packages required during development and testing but are not necessary for the production deployment.
OptionDescription
providers?

The set of injectable objects that are available in the injector of this module.

declarations?

The set of components, directives, and pipes (declarables) that belong to this module.

imports?

The set of NgModules whose exported declarables are available to templates in this module.

exports?

The set of components, directives, and pipes declared in this NgModule that can be used in the template of any component that is part of an NgModule that imports this NgModule. Exported declarations are the module's public API.

entryComponents?

The set of components to compile when this NgModule is defined, so that they can be dynamically loaded into the view.

bootstrap?

The set of components that are bootstrapped when this module is bootstrapped. The components listed here are automatically added to entryComponents.

schemas?

The set of schemas that declare elements to be allowed in the NgModule. Elements and properties that are neither Angular components nor directives must be declared in a schema.

id?

A name or path that uniquely identifies this NgModule in getModuleFactory If left undefined, the NgModule is not registered with getModuleFactory.

jit?

When present, this module is ignored by the AOT compiler. It remains in distributed code, and the JIT compiler attempts to compile it at run time, in the browser. To ensure the correct behavior, the app must import @angular/compiler.

In Angular, components have a lifecycle that consists of various phases and events. These phases are known as lifecycle hooks, and they provide opportunities to perform actions at specific moments during the component's creation, rendering, and destruction. The following are the lifecycle hooks available in an Angular component: 1. ngOnChanges: This hook is called when the component receives input properties and is executed before `ngOnInit()`. It allows you to react to changes in the input properties. 2. ngOnInit: This hook is called once, after the first `ngOnChanges()`, when the component is initialized. It is commonly used for initialization logic, such as retrieving data from a server. 3. ngDoCheck: This hook is called during every change detection run, allowing you to implement your own custom change detection logic. It is invoked frequently, so use it judiciously to avoid performance issues. 4. ngAfterContentInit: This hook is called after the component's content has been projected into its view. It is useful when you need to interact with content children components. 5. ngAfterContentChecked: This hook is called after the content of the component has been checked by Angular's change detection mechanism. It is called after every check of the content children. 6. ngAfterViewInit: This hook is called after the component's view has been initialized. It is useful when you need to interact with child components that are part of the view. 7. ngAfterViewChecked: This hook is called after the view of the component has been checked by Angular's change detection mechanism. It is called after every check of the component's view and its child views. 8. ngOnDestroy: This hook is called just before the component is destroyed and removed from the DOM. It is used to clean up resources, such as unsubscribing from observables or canceling timers. These lifecycle hooks allow you to perform specific actions at different stages of a component's lifecycle. By implementing and using these hooks, you can control the behavior and manage resources effectively throughout the component's lifespan.
Lazy loading in Angular is a technique that allows you to load modules and their associated resources (components, services, etc.) on-demand, rather than loading everything upfront when the application starts. This helps to improve the initial loading time of the application and optimize the overall performance. By default, Angular loads all modules and their associated resources when the application is launched. However, with lazy loading, you can split your application into feature modules and load them dynamically only when they are needed. This way, you can reduce the initial bundle size and load only the necessary code for the current route or feature. To implement lazy loading in Angular, you need to follow these steps: 1. Create Feature Modules: Divide your application into feature modules that encapsulate related components, services, and other resources. Each feature module will have its own routing configuration. 2. Configure Routes: In the main routing configuration of your application, set up the routes for the feature modules using the `loadChildren` property instead of `component`. The `loadChildren` property specifies the path to the module file to be loaded lazily.

   const routes: Routes = [
     { path: 'dashboard', component: DashboardComponent },
     { path: 'products', loadChildren: () => import('./products/products.module').then(m => m.ProductsModule) },
     // other routes...
   ];
 
3. Create Feature Module: In each feature module, define its own routing configuration using the `RouterModule.forChild()` method.

   const routes: Routes = [
     { path: '', component: ProductListComponent },
     { path: 'details/:id', component: ProductDetailsComponent },
     // other routes specific to the feature module...
   ];

   @NgModule({
     imports: [RouterModule.forChild(routes)],
     exports: [RouterModule]
   })
   export class ProductsRoutingModule { }

4. Build and Serve: Build your Angular application using the Angular CLI. When you navigate to a route associated with a lazy-loaded module, Angular will fetch and load the necessary module and its resources on-demand. Lazy loading allows you to optimize your application's performance by splitting it into smaller modules that can be loaded when needed. It helps reduce the initial loading time and improves the user experience, especially for larger applications with multiple features. For more details, checkout this angular's official link to understand lazy loading - Lazy loading in Angular

In Angular, there are several ways to share data between two components. Here are some common methods:

1. Parent-to-child communication (Input binding): In Angular, you can share data from a parent component to a child component by using input properties. The parent component binds a value to an input property of the child component. Example: Parent Component:

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

@Component({
  selector: 'app-parent',
  template: `
    
  `
})
export class ParentComponent {
  sharedData: string = 'Hello from parent!';
}

Child Component:

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

@Component({
  selector: 'app-child',
  template: `
    

{{ data }}

` }) export class ChildComponent { @Input() data: string; }
2. Child-to-parent communication (EventEmitter): If you need to share data from a child component back to its parent component, you can use the EventEmitter class. The child component emits events that the parent component listens to. Example: Child Component:

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

@Component({
  selector: 'app-child',
  template: `
    Send Data
  `
})
export class ChildComponent {
  @Output() dataEvent = new EventEmitter();

  sendData() {
    const data = 'Hello from child!';
    this.dataEvent.emit(data);
  }
}

Parent Component:

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

@Component({
  selector: 'app-parent',
  template: `
    
    

{{ receivedData }}

` }) export class ParentComponent { receivedData: string; receiveData(data: string) { this.receivedData = data; } }
3. Service (Shared service): You can create a shared service that acts as a data-sharing intermediary between components. The service holds the shared data, and components can read and write to it. Example: Shared Service:

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

@Injectable()
export class DataService {
  sharedData: string = 'Hello from service!';
}

Component A:

import { Component } from '@angular/core';
import { DataService } from 'path-to-data-service';

@Component({
  selector: 'app-component-a',
  template: `
    

{{ dataService.sharedData }}

` }) export class ComponentA { constructor(public dataService: DataService) {} }
Component B:

import { Component } from '@angular/core';
import { DataService } from 'path-to-data-service';

@Component({
  selector: 'app-component-b',
  template: `
    Update Data
  `
})
export class ComponentB {
  constructor(public dataService: DataService) {}

  updateData() {
    this.dataService.sharedData = 'New data!';
  }
}

These are some common ways to share data between two components in Angular. The method you choose depends on the relationship between the components and the specific requirements of your application.
A single-page application is an app that doesn’t need to reload the page during its use and works within a browser. One of the best advantages of a correctly-configured SPA is the user experience (UX), where the user enjoys a natural environment of the app without having to wait for the page reloads and other things. You remain on the same page, which is powered by JavaScript programming language. Before we go further, there are three abbreviations you’ll see in this article: SPA - single-page application (like we’ve mentioned above) MPA - multi-page application (a traditional app that loads new pages when you click a link) PWA - progressive web application (a website that is built using JavaScript or its frameworks and can act like an app, i.e., you can, for example, add it to your mobile phone homepage as an app) Advantages The main advantage of single-page applications is its speed. Most resources SPA needs (HTML + CSS + Scripts) are loaded at the launch of the app and don’t need to be reloaded during the usage. The only thing that changes is the data that is transmitted to and from the server. As a result, the application is very responsive to the user’s queries and doesn’t have to wait for client-server communication all the time.
The main limitation is that AoT, due to the way it compiles the raw code, cannot be used with common code patterns, for example, default exports from modules, template literals for templates, and functions in providers, routes, or declarations. AoT Do's and Don'ts This section explains the cases listed above, and will show how each of them fails and works. -> arrow-function-exports Arrow function does not work with AoT when it is passed to an NgModule.

Don't:

export const couterReducer = (state, action: Action) => {
  // ...
}

Do:

export function counterReducer(state, action: Action) {
  // ...
}

-> control This is used as a simplest working case. default-exports Default exports are not supported with AoT.

Don't:

export default class AppComponent {};

Do:

export class AppComponent {};

-> form-control

Use this.helloForm.controls["greetingMessage"] to retrieve form control is fine.

-> form-control-error The syntax errors? is not supported by AoT.

Don't:

{{helloForm.controls["greetingMessage"].errors?.minlength}}

Do:

{{helloForm.controls["greetingMessage"].hasError("minlength")}}

-> func-in-routes Direct use of function in route is not supported by AoT. Either avoid using it or export it from other module.

Don't:

function random() {
  return [{
    path: "",
    component: AppViewComponent
  }];
}
const SAMPLE_APP_ROUTES: Routes = random();

Do:

const SAMPLE_APP_ROUTES: Routes = [{
  path: "",
  component: AppViewComponent
}];

For more details click here
Caret sign

"dependencies": {
  "express": "^3.9.2"
}

Caret allows:- ->Backward compatible new functionalities ->Large internal refactor ->Bug fixes ->Deprecation of old functionality (which is still operational) ->With the caret you can get releases like 3.., where the * characters will match the highest version number available. So changes in the major digit, like 4.0.0, will not be used in this case. Tilde sign

"dependencies": {
  "express": "~3.9.2"
}

Tilde allows ->Bug fixes ->With tilde, you can get releases like 3.9.*. Only the latest bug fixes are allowed with the tilde. So we can conclude by saying that the ~ character should be used if you want to lock in the patch number. You should use this when you are ready to accept only bug-fixes and don't want to face any possibly incompatible alterations. On the other hand, the ^ character is responsible for locking in the patch and the minor version numbers. It's to be used when you want to have backwards compatible new functionality as well as bug fixes.
getAllAngularRootElements() on browse console will return something .For now it is returing :-[app-root]