Must know angular interview questions

Indrajeet GiramIndrajeet Giram
9 min read

20 JavaScript and 20 Angular concepts along with code snippets


JavaScript Concepts with Code and Explanation

  1. Event Delegation

     document.querySelector('#parent').addEventListener('click', function(event) {
       if (event.target && event.target.matches('button.classname')) {
         console.log('Button clicked!');
       }
     });
    

    Explanation: Event delegation is useful when attaching events to many elements. Here, the parent element listens for clicks, and if the clicked element matches the button with classname, the event handler is triggered.

  2. Asynchronous Operations

     async function fetchData() {
       const result = await new Promise((resolve) => setTimeout(() => resolve('Data fetched!'), 1000));
       console.log(result);
     }
    
     fetchData();
    

    Explanation: This uses async/await to handle asynchronous code. The Promise is resolved after 1 second, and await pauses the execution until the Promise resolves.

  3. Difference Between == and ===

     console.log(5 == '5');  // true
     console.log(5 === '5'); // false
    

    Explanation: == compares values but performs type coercion, while === compares both value and type, which is stricter.

  4. Closures

     function outerFunction() {
       let outerVar = 'I am outer';
       return function innerFunction() {
         console.log(outerVar);
       };
     }
    
     const inner = outerFunction();
     inner(); // Logs 'I am outer'
    

    Explanation: A closure allows the inner function to access variables from its outer function even after the outer function has returned.

  5. Higher-Order Functions

     const numbers = [1, 2, 3, 4];
     const doubled = numbers.map(num => num * 2);
     console.log(doubled); // [2, 4, 6, 8]
    

    Explanation: Higher-order functions take other functions as arguments or return a function. Here, map() is a higher-order function that transforms each number.

  6. this Context

     const person = {
       name: 'John',
       greet: function() {
         console.log(`Hello, ${this.name}`);
       }
     };
     person.greet(); // 'Hello, John'
    

    Explanation: The value of this refers to the object person. Inside the greet method, this.name accesses the name property of the person object.

  7. Prototype Chain

     function Person(name) {
       this.name = name;
     }
    
     Person.prototype.greet = function() {
       console.log(`Hello, ${this.name}`);
     };
    
     const john = new Person('John');
     john.greet(); // 'Hello, John'
    

    Explanation: The prototype chain enables Person objects to share methods. The method greet is added to the Person.prototype, allowing instances to access it.

  8. Arrow Functions

     const numbers = [1, 2, 3];
     const squares = numbers.map(n => n * n);
     console.log(squares); // [1, 4, 9]
    

    Explanation: Arrow functions provide a more concise syntax and do not have their own this binding, making them ideal for short functions.

  9. call, apply, and bind

     function greet() {
       console.log(`Hello, ${this.name}`);
     }
    
     const person = { name: 'John' };
     greet.call(person);  // 'Hello, John'
     greet.apply(person); // 'Hello, John'
     const boundGreet = greet.bind(person);
     boundGreet();        // 'Hello, John'
    

    Explanation: call() and apply() invoke the function immediately, setting the this value. bind() returns a new function with this bound to person.

  10. Modules in JavaScript In module1.js:

export function greet() {
  console.log('Hello');
}

In main.js:

import { greet } from './module1.js';
greet(); // 'Hello'

Explanation: Modules allow splitting code into reusable pieces. You can export functions or variables from one file and import them into another.

  1. Hoisting
console.log(x); // undefined
var x = 5;

Explanation: Variables declared with var are hoisted to the top, meaning they can be used before their declaration, but their value will be undefined.

  1. Promises
const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Done!'), 1000);
});

myPromise.then(result => console.log(result)); // 'Done!'

Explanation: A Promise is an object representing the eventual completion of an asynchronous operation. The then() method handles the resolved value.

  1. Difference Between var, let, and const
var x = 10; // function-scoped, can be re-assigned
let y = 20; // block-scoped, can be re-assigned
const z = 30; // block-scoped, cannot be re-assigned

Explanation: var is function-scoped and can be redeclared. let and const are block-scoped, with const being immutable after assignment.

  1. Immediately Invoked Function Expression (IIFE)
(function() {
  console.log('IIFE executed');
})();

Explanation: IIFE is a function that runs as soon as it’s defined. It helps create a private scope and avoid polluting the global namespace.

  1. reduce()
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // 10

Explanation: The reduce() method applies a function to an accumulator and each element of the array, reducing the array to a single value.

  1. async/await
async function fetchData() {
  const result = await new Promise(resolve => setTimeout(() => resolve('Data!'), 1000));
  console.log(result);
}

fetchData();

Explanation: The async keyword marks a function as asynchronous, and await is used to wait for the Promise to resolve. This simplifies working with asynchronous code.

  1. Default Parameters
function greet(name = 'Guest') {
  console.log(`Hello, ${name}`);
}

greet(); // 'Hello, Guest'

Explanation: Default parameters allow setting a default value for function arguments. If no argument is provided, the default value is used.

  1. Destructuring
const person = { name: 'John', age: 25 };
const { name, age } = person;
console.log(name, age); // 'John', 25

Explanation: Destructuring allows extracting values from objects or arrays and assigning them to variables in a concise way.

  1. Template Literals
const name = 'John';
console.log(`Hello, ${name}`); // 'Hello, John'

Explanation: Template literals use backticks to embed expressions and create multi-line strings. They replace the older + string concatenation method.

  1. Error Handling with try...catch
try {
  throw new Error('Something went wrong');
} catch (error) {
  console.log(error.message); // 'Something went wrong'
}

Explanation: The try...catch block handles exceptions. If an error is thrown in the try block, it is caught in the catch block, preventing the application from crashing.


Angular Concepts with Code and Explanation

  1. Component in Angular

     @Component({
       selector: 'app-root',
       template: `<h1>Hello, {{name}}</h1>`,
     })
     export class AppComponent {
       name = 'Angular';
     }
    

    Explanation: A component is the building block of Angular applications. It controls a portion of the UI and the logic behind it, defined with a template.

  2. Component Lifecycle

     @Component({
       selector: 'app-example',
       template: `<p>Example Component</p>`,
     })
     export class ExampleComponent implements OnInit {
       ngOnInit() {
         console.log('Component initialized');
       }
     }
    

    Explanation: The OnInit lifecycle hook runs after the component is created. It is often used to initialize data or make API calls.

  3. Dependency Injection

    ```ts @Injectable({ providedIn: 'root' })

export class DataService { getData() { return 'Data from service'; } }

@Component({ selector: 'app-root', template: <p>{{data}}</p>, }) export class AppComponent { data: string; constructor(private dataService: DataService) { this.data = this.dataService.getData(); } }


    **Explanation**: Angular uses dependency injection to provide services to components. The `DataService` is injected into the `AppComponent` and used to retrieve data.

4. **Routing in Angular**

    ```ts
    const routes: Routes = [
      { path: '', component: HomeComponent },
      { path: 'about', component: AboutComponent }
    ];

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

Explanation: Angular’s RouterModule allows navigation between different views (components) by mapping URL paths to components.

  1. Services in Angular

     @Injectable({ providedIn: 'root' })
     export class LoggingService {
       log(message: string) {
         console.log(`Log: ${message}`);
       }
     }
    
     @Component({
       selector: 'app-root',
       template: `<p>Check the console</p>`,
     })
     export class AppComponent {
       constructor(private loggingService: LoggingService) {
         this.loggingService.log('Component loaded');
       }
     }
    

    Explanation: Services provide reusable logic that can be shared across components. In this example, LoggingService logs messages to the console.

  2. Two-Way Data Binding

     @Component({
       selector: 'app-root',
       template: `<input [(ngModel)]="name"><p>Hello, {{name}}</p>`,
     })
     export class AppComponent {
       name = '';
     }
    

    Explanation: Two-way data binding allows synchronization between the UI and the component’s data. Any changes in the input will reflect in the name property and vice versa.

  3. Structural Directives (ngIf, ngFor)

     <div *ngIf="isVisible">This is visible</div>
     <ul>
       <li *ngFor="let item of items">{{ item }}</li>
     </ul>
    

    Explanation: Structural directives like *ngIf and *ngFor are used to conditionally add or remove elements and loop through lists in the template.

  4. Reactive Forms in Angular

     @Component({
       selector: 'app-form',
       template: `
         <form [formGroup]="form">
           <input formControlName="name">
         </form>
       `,
     })
     export class FormComponent implements OnInit {
       form: FormGroup;
    
       constructor(private fb: FormBuilder) {}
    
       ngOnInit() {
         this.form = this.fb.group({
           name: ['']
         });
       }
     }
    

    Explanation: Reactive forms provide more flexibility and control than template-driven forms. Form controls and groups are explicitly created in the component class.

  5. Template-Driven Forms

     @Component({
       selector: 'app-form',
       template: `
         <form #form="ngForm">
           <input [(ngModel)]="name" name="name" required>
         </form>
       `,
     })
     export class FormComponent {
       name = '';
     }
    

    Explanation: Template-driven forms rely on directives like ngModel in the template to manage the form state. It's simpler but less flexible than reactive forms.

  6. Pipes in Angular

@Component({
  selector: 'app-root',
  template: `<p>{{ today | date:'fullDate' }}</p>`,
})
export class AppComponent {
  today = new Date();
}

Explanation: Pipes transform data in the template. The date pipe formats dates, but there are many other built-in and custom pipes that can be used.

  1. Custom Directives
@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {
  @HostBinding('style.backgroundColor') bgColor = 'yellow';
}

// Usage in template: <p appHighlight>Highlighted text</p>

Explanation: Directives are used to modify the behavior or appearance of elements. This custom directive changes the background color to yellow.

  1. Event Binding
@Component({
  selector: 'app-root',
  template: `<button (click)="onClick()">Click me</button>`,
})
export class AppComponent {
  onClick() {
    console.log('Button clicked!');
  }
}

Explanation: Event binding connects DOM events (like click) to methods in the component, allowing interaction between the template and the component logic.

  1. Route Guards
@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {
  canActivate(): boolean {
    return true; // Logic to check if route can be accessed
  }
}

const routes: Routes = [
  { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }
];

Explanation: Route guards prevent access to certain routes based on custom logic. For example, you can block unauthorized users from accessing the dashboard.

  1. Handling HTTP Requests
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  template: `<p>{{ data }}</p>`,
})
export class AppComponent {
  data: any;
  constructor(private http: HttpClient) {
    this.http.get('https://api.example.com/data').subscribe(result => {
      this.data = result;
    });
  }
}

Explanation: Angular's HttpClient service is used to make HTTP requests. The data fetched from the API is displayed in the template.

  1. Change Detection
@Component({
  selector: 'app-root',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `<p>{{ data }}</p>`,
})
export class AppComponent {
  @Input() data!: string;
}

Explanation: Change detection checks if any data in the component has changed. The OnPush strategy only checks for changes when the @Input() value changes.

  1. ngOnChanges Lifecycle Hook
@Component({
  selector: 'app-child',
  template: `<p>{{ data }}</p>`,
})
export class ChildComponent implements OnChanges {
  @Input() data!: string;

  ngOnChanges(changes: SimpleChanges) {
    console.log('Data changed:', changes);
  }
}

Explanation: The ngOnChanges hook is triggered whenever input properties change, allowing you to react to these changes.

  1. Custom Pipes
@Pipe({ name: 'capitalize' })
export class CapitalizePipe implements PipeTransform {
  transform(value: string): string {
    return value.charAt(0).toUpperCase() + value.slice(1);
  }
}

// Usage in template: {{ 'angular' | capitalize }}  <!-- Output: Angular -->

Explanation: Custom pipes transform data in the template. This pipe capitalizes the first letter of a string.

  1. Content Projection
<!-- Parent component -->
<app-child>
  <p>Projected content</p>
</app-child>

<!-- Child component -->
<ng-content></ng-content>

Explanation: Content projection allows you to project content from a parent component into a child component using <ng-content>.

  1. Using ngFor
<ul>
  <li *ngFor="let item of items">{{ item }}</li>
</ul>

Explanation: ngFor is a structural directive that iterates over an array and renders a list of elements dynamically.

  1. HTTP Error Handling
this.http.get('https://api.example.com/data').pipe(
  catchError(error => {
    console.error('Error occurred:', error);
    return throwError(() => new Error('Something went wrong'));
  })
).subscribe(data => console.log(data));

Explanation: When making HTTP requests, it's important to handle errors. The catchError operator allows you to catch and handle errors in a stream of data.


These explanations, along with code examples, provide a solid understanding of key JavaScript and Angular concepts that every front-end Angular developer should master.

0
Subscribe to my newsletter

Read articles from Indrajeet Giram directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Indrajeet Giram
Indrajeet Giram

Hello there! My name is Indrajeet, and I'm an intermediate web👩🏻‍💻 developer. I'm writing to share my programming views🤨 and hope my writeups will be helpful in your 😀 web development journey.