Skip to content

Instantly share code, notes, and snippets.

@ThomasBurleson
Last active February 2, 2021 17:40
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ThomasBurleson/727d9d50332b8ada27f70c34fef8be88 to your computer and use it in GitHub Desktop.
Save ThomasBurleson/727d9d50332b8ada27f70c34fef8be88 to your computer and use it in GitHub Desktop.
Angular Interview Questions

The interview questions below are grouped by category and each category lists questions in easy-to-hard order.

Interviews should ask the candidate to self-assess their skills/experience. Based on the candidate's response, the interviewer can jump to the appropriate section.

Some basic questions going from easy to difficult. A more exhaustive list of more questions from the community can be found here.

JavaScript

  • What is variable shadowing
  • What are the 3 big wins with ES6 (over ES5)

Possible answers: fat arrow, template string, modules, classes, default params, implicit accessors/mutators, let/const, desctructuring, spread,

  • ES6 Module,
  • what can it contain
  • how do you publish for external use
  • how do you protect for internal use
  • What is a barrel used for?
  • What is a spread operator (aka desconstruction operator)
  • Why is a spread operator useful ?
  • What is destructing and how would I use ?
  • What is the rest operator

Typescript

  • What is a Generic in Typescript
  • Give me an example of strongly typed function
  • Bonus: strongly typed function that returns observable
  • Bonus: strongly typed function that uses HttpClient
  • What does forwardRef do

Angular Basics

  • What is the difference between an ES6 module and an ngModule
  • How do you get a reference to a child component
  • What is Dependency Injection
  • What is @Injectable used for ?
  • What is @Inject used for ?
  • What are pipes
  • How do you use component that defined/implemented in another module?
  • What is router-outlet?
  • What is the Angular Compiler and how is it used
  • What is the difference between AOT and JIT?
  • What is AOT

Angular Components

  • What is a component in Angular
  • What are differences between Components and Directives
  • How do we create a Angular Component (hint what decorator)
  • Give me 3 component lifecycle events
  • Why is ngOnInit() important
  • Explain content projection
  • What is a difference between @ViewChild and @ContentChild
  • How do you listen for events in a component?
  • What is OnPush change detection in components
  • What is the difference between template and reactive forms and why would you use one or the other
  • What is ViewEncapsulation
  • What is ng-container and why is it useful?
  • What are entryComponents

Angular Advanced

  • What is the difference between Template-Driven and Reactive forms
  • What is a Guard
  • What is a Resolver
  • What is a Zone
  • Why are ngZones important

RxJS

  • Explain Observables and why they are useful.
  • What’s the difference between a promise and Observable?
  • Are Observables asynchronous
  • Why is the Async pipe useful
  • What are two (2) important things provided by the async pipe?
  • What are pipeable operators
  • What is a zombie subscription

State Management

  • What is state and why is state management so important
  • What are the challenges to manually managing state
  • What is Redux pattern and explain why its useful.
  • What are the downsides to Redux
  • What is the difference between Redux and Ngrx
  • What is the aspect of Ngrx you like the most
  • Why are Effects important in ngrx
  • Why is Akita ab attractive alternative to NgRx
  • What is a memoized selector
@ThomasBurleson
Copy link
Author

Question: Is this an ES6 Module or an Angular Module?

// test.ts

@NgModule({
	declarations : [ ]
})
export class TestExample()

@ThomasBurleson
Copy link
Author

Question: Which [below] is a component or directive?

<mat-form-field>
	<input [ngModel]="name">
</mat-form-field>

@ThomasBurleson
Copy link
Author

@Component({
   selector: 'my-comp',
   template: `
    {{ getValues() | async  }}
  `
})
export class MyComponent {
  private stream$ = from([1, 2, 3]);

  getValues(): Observable<number> {
     return this.stream$;
  }
}

Are there any issues with this ^ code ?

@ThomasBurleson
Copy link
Author

ThomasBurleson commented Jan 3, 2020

@Injectable({
  providedIn: 'root'
})
export class FilterService {
  filterSent$       = new Subject<Filter>(); 
  filterExisting$ = new Subject<Filter[]>(); 

  constructor(private commonService: CommonService) { }

  sendFilter(filter: any) { this.filterSent$.next(filter); }
  broadcastFilters(filters: any) { this.filterExisting$.next(filters); }

  async getArrayFilterValues(data: any[], attribute: string: Promise<string[]>) { }
  async getRangeFilterValues(data: any[], attribute: string): Promise<string[]> { }
  async getFilterValuesFromIdb(category: string): Promise<string[]> {  }
}

Is this ^ a proper implementation?

  • If not, are there any issues?
  • How would you fix this?

@ThomasBurleson
Copy link
Author

ThomasBurleson commented Jan 4, 2020

function update(ev, updateDiff) {
  // get current event from Back End
  return scheduleService.getEvent(ev.id).then(function(event) {
    // send updates to Back end
    return scheduleService.editEvent(ev.id, event.version, updateDiff).then(function(evt) {
      var pack = findAircraftPackById(evt.aircraft.id);
      // get whole aircraft schedules in order to get repo legs updated
      return fetchAircraft(pack).then(function(resp) {
        return resp;
      }, function(error) {
        return $q.reject(error);
      });
    }, function(error) {
      return $q.reject(error);
    });
  }, function(error) {
    return $q.reject(error);
  });
}

How would you improve upon this ^ code?

Using Async/Await

const ERRORS = {
  event : "Unable to get current event: ",
  edit  : "Unable to edit current event: ",
  find  : "Unable to find aircraft: ",
  fetch : "Unable to fetch aircraft details: "
};
const trap(promise, msg) => promise.catch(error => {
  throw new Error(msg + JSON.stringify(error));
});

function async update(ev, updateDiff) {

  const event = await trap(scheduler.getEvent(ev.id),                 ERRORS.event);
  const info  = await trap(scheduler.editEvent(ev.id, event.version), ERRORS.edit);
  const pack  = await trap(findAircraftPackById(info.aircraft.id),    ERRORS.find);
  const plane = await trap(fetchAircraft(pack),                       ERRORS.fetch);

  return plane;
}

@ThomasBurleson
Copy link
Author

Challenge:

Issues:

  • Does not handle out-or-order
  • Extracts state instead of using async pipe
  • Does not use observables
import { Component } from '@angular/core';
import {BackendService, Ticket} from './backend.service';
import {
  Action, 
  TicketActionTypes,
  reducer, 
  applyFilters 
} from './utils/reducers';



@Component({
  selector: 'app-root',
  template: `
    <h2>Tickets</h2>
    
    <input (input)="doFilter(assignee.value)" #assignee type="text">
    
    <ul>
      <li *ngFor="let t of tickets">
        Ticket: {{t.id}}, {{t.description}}
        <button (click)="doComplete(t)">Complete</button>
      </li>
    </ul>
  
    <input value="" #newTicket type="text">
    <button (click)="doAddTicket(newTicket.value)">Add New Ticket</button>
   `,
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  tickets    : Ticket[] = [];   // filtered tickets
  allTickets : Ticket[] = [];   // all known tickets
  filter     : string   = "";   // fitler criteria

  queue      : Promise<boolean> = Promise.resolve(true);

  constructor(private backend: BackendService) {
    backend.tickets().subscribe((list:Ticket[]) => {
      this.allTickets = list;
      this.tickets    = this.refreshFilteredList();
    });
  }

  // ***************************************************************
  // Actions
  // ***************************************************************

  doFilter(val:string) {
    this.filter  = val;
    this.tickets = this.refreshFilteredList();
  }

  doAddTicket(description:string) {    
    this.addToQueue(() => {
      return this.backend
        .newTicket( {description} )
        .toPromise()
        .then((ticket:Ticket) => {
          this.allTickets = this.addTicket(ticket);
          this.tickets    = this.refreshFilteredList();

          return true;
        })
    });
    
  }

  doComplete(ticket:Ticket) {
    this.backend
      .complete(ticket.id, true)
      .subscribe((ticket:Ticket) => {
        this.allTickets = this.completeTicket(ticket);
        this.tickets    = this.refreshFilteredList();
      }) 
  }


  addToQueue( makeRequest ) {
    this.queue = this.queue.then( makeRequest );
  }

  // ***************************************************************
  // 'Action methods'
  // ***************************************************************

  refreshFilteredList() {    
    return applyFilters(this.filter, this.allTickets);
  }

  addTicket(ticket:Ticket) {
    const action = {type: TicketActionTypes.ADD, data: ticket};
    return reducer(this.allTickets, action);
  }

  completeTicket(ticket:Ticket) {
    const action = {type: TicketActionTypes.COMPLETE, data: ticket};
    return reducer(this.allTickets, action);
  }

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment