Home› Frontend› Complete Guide
Complete Guide

Complete Frontend Tutorial

This complete guide covers all 13 Frontend tutorials on TheCodeForge, organised by topic.

Learning Roadmap
Beginner → Build a strong foundation
Intermediate → Deepen your understanding with practical topics
Advanced → Master advanced concepts and real-world applications
13
Topics
6
Beginner
6
Intermediate
1
Advanced
Jump to section
Vue (7)Angular (6)

Vue and Angular solve the same problem from opposite ends, and their error messages show it. Vue tracks dependencies at runtime, so its failures are about reactivity that quietly stopped working — a reassignment the tracker did not see, a render that triggers itself forever. Angular resolves everything up front through dependency injection and template compilation, so its failures are loud and structural: a provider that does not exist, a directive that was never imported, a binding target the compiler has never heard of.

Neither is harder than the other, but the debugging instincts do not transfer. In Vue you ask what is the tracker watching? In Angular you ask what did the injector and the compiler see? Every article in this track is an instance of one of those two questions.

Vue: reactivity is a proxy, and proxies have edges

Vue 3 makes state reactive by wrapping it in a Proxy that intercepts property access. Read a property during a render and Vue records the dependency; write it and Vue re-runs whatever read it. That mechanism is why Vue feels effortless, and also why reactivity 'breaks' in a small number of predictable ways: anything that replaces the proxy rather than mutating through it escapes tracking.

The classic case is destructuring. Pulling a primitive out of a reactive object copies its current value and hands you a plain variable with no connection to the source. Nothing warns you; the UI simply stops updating.

javascript
import { reactive, ref, toRefs } from 'vue'

const state = reactive({ count: 0, user: { name: 'Ada' } })

// Breaks reactivity: count is now a detached copy of the number 0
let { count } = state

// Keeps reactivity: refs stay connected to the source
const { count, user } = toRefs(state)

// Also breaks it: the local binding is replaced, the proxy is discarded
let s = reactive({ items: [] })
s = { items: newItems }            // component still watches the old object

// Mutate through the proxy instead
s.items = newItems                 // tracked
// or hold the value in a ref and replace .value
const items = ref([])
items.value = newItems             // tracked
In practiceMaximum recursive updates exceeded is the same mechanism biting from the other side: something written during render is also read during render, so each pass schedules the next. Look for a mutation inside a computed, a watcher that writes its own source, or a template expression that creates a new object every call — a fresh array literal in a prop is a new identity on every render.

Angular: NullInjectorError names the missing edge in a graph

Angular's injector is a tree, and NullInjectorError: No provider for X means the request walked from the component up to the root and found no provider anywhere on the path. That is nearly always one of four things, and the error text tells you which if you read what is asking rather than what is missing.

Since standalone components became the default, a fifth cause dominates new codebases: the thing is not missing from providers at all, it is missing from the component's own imports array. A standalone component must import every directive, pipe and module its template uses — there is no surrounding NgModule to inherit from any more.

ErrorWhat Angular is telling youUsual fix
No provider for HttpClientNothing on the injector path provides itprovideHttpClient() in the application config, or HttpClientModule in the module
Can't bind to 'ngModel'The compiler sees an unknown property on a known element — so the directive that would claim it is not in scopeImport FormsModule in the standalone component's imports or the owning NgModule
'app-child' is not a known elementThe template references a component the compiler cannot seeAdd the child to imports; check it is exported if it lives in a module
NullInjectorError only in testsTestBed builds its own injector and inherits nothingProvide or mock the dependency in the TestBed.configureTestingModule call

ExpressionChangedAfterItHasBeenChecked, explained properly

This error only appears in development mode, which makes people assume it is cosmetic. It is not — it is Angular running change detection twice and finding a different answer the second time. In production the second pass does not happen, so the view keeps whatever the first pass produced and you get a stale or inconsistent UI instead of a console message.

The cause is always a value that mutates as a side effect of being read or rendered: a getter that increments a counter, a parent property written from a child's ngAfterViewInit, a template calling a function that returns a new object each time. The fix is to make the value stable during a pass — compute it once and store it, or defer the write to the next tick so it belongs to the following cycle.

typescript
// Problem: the child writes a parent-bound value during the same pass
ngAfterViewInit() {
  this.parentTitle = this.measureSomething();   // throws in dev mode
}

// Option 1 - defer to the next change-detection cycle
constructor(private cdr: ChangeDetectorRef) {}
ngAfterViewInit() {
  Promise.resolve().then(() => {
    this.parentTitle = this.measureSomething();
    this.cdr.detectChanges();
  });
}

// Option 2 - the usually-better fix: don't compute in the template at all
// Template:  {{ title }}        not  {{ buildTitle() }}
// Compute in ngOnChanges / a signal / a computed observable so the value
// is already settled when rendering starts.
In practiceCalling a method from a template is the most common source of this error and of slow Angular apps generally: the method runs on every change-detection pass, for every binding. Prefer a field, a signal, or an observable piped through async.

Hydration mismatches: two renders that disagree

Server-side rendering asks the same component tree to produce identical output twice — once on the server, once in the browser — and then reuses the server's DOM. A mismatch means the two runs disagreed, and the framework has to throw away the server markup and re-render, which costs you the performance you adopted SSR to get.

The causes are a short list and worth memorising, because the error message rarely names the culprit: anything time-dependent (Date.now(), relative timestamps), anything random, anything reading window, localStorage or a user agent, locale-sensitive formatting where server and client locales differ, and invalid HTML nesting that the browser silently repairs — a <div> inside a <p> produces a different tree in the browser than the string the server emitted.

The fix is to make the first client render match the server exactly and move the divergent value into an effect that runs after hydration. Rendering a stable placeholder and filling it in on mount is not a workaround — it is the correct shape for any value that only exists in the browser.

Frequently Asked Questions

Why does my Vue component stop updating after I assign a new object?
Because reactivity is attached to the proxy, not to the variable holding it. Replacing the variable gives you a new plain object while the component is still subscribed to the old proxy. Mutate properties through the existing reactive object, or hold the value in a ref and assign to .value, which Vue tracks.
Should I use ref or reactive in Vue 3?
Default to ref. It works for primitives and objects alike, survives reassignment because the proxy lives on .value, and keeps one consistent access pattern across a codebase. Reach for reactive when you want an object whose properties are accessed without .value and you know it will never be wholesale replaced.
What is the difference between 'No provider for X' and 'X is not a known element'?
The first comes from the injector at runtime: a class asked for a dependency and nothing on the injector path supplies it. The second comes from the template compiler: a tag or attribute in a template has no matching component or directive in scope. Providers fix the first, imports fix the second, and conflating them is the most common reason people add the wrong thing to the wrong array.
Is 'Http failure response for unknown URL: 0' a CORS problem?
Usually yes, or something adjacent to it. Status 0 means the browser never gave Angular a response to read — blocked preflight, mixed content, a DNS or connection failure, or a cancelled request. Angular cannot distinguish them because the browser deliberately withholds the detail. Read the browser's network panel and the server's access log; the Angular error is the one place that cannot tell you.
Do I still need Vuex or NgRx?
Less often than in 2019. Vue's composition API with composables covers most shared state, and Angular's signals plus services handle a lot of what NgRx was adopted for. A formal store still earns its cost when you need time-travel debugging, strict action auditing, or many components coordinating on the same complex state machine. Start without it and add it when you can name the problem it solves for you.
Which should I learn first, Vue or Angular?
Vue if you want to be productive in an afternoon and will mostly build interfaces; Angular if you are heading for a large enterprise codebase, because dependency injection, RxJS and strict typing are the ambient assumptions there. The concepts in this track — change detection, reactivity tracking, hydration — apply to both, and to React, so time spent on the mechanisms is never wasted.

Vue

Angular

Also Explore
JavaScript 185 tutorials → Web Platform 9 tutorials → Interview 77 tutorials → DevOps 304 tutorials → Testing 12 tutorials → Mobile 20 tutorials →
Start from the beginning

Every tutorial starts with a plain-English analogy — then real code, then interview questions.

Browse Frontend Tutorials →