Visualizing Angular dependencies

When working on large Angular projqects, managing dependencies between files and modules can become a challenge.

Here are 2 tools to help you visualize dependencies in an Angular project.

Madge – visualizes typescript dependencies

  • https://www.npmjs.com/package/madge
  • Install: npm install -g madge
  • In root folder of project, run:
    npx madge src/main.ts --ts-config tsconfig.json --image ./deps.png

    Above will output the image “deps” in the root of project.
  • Can also be run for any typescript class, e.g. a single component such as:
    npx madge src/app/app.component.ts --ts-config tsconfig.json --image ./deps.png
  • Detect circular dependencies:
    npx madge --circular src/main.ts--ts-config tsconfig.json

  • Detect dead code (code that is never referred to anywhere in your app):
    npx madge --orphans src/main.ts --ts-config tsconfig.json

Compodoc – “The missing documentation tool for Angular..”

https://compodoc.app/

# Install globally compodoc with npm
npm install -g @compodoc/compodoc

# Create a file named tsconfig.doc.json in project root, containing: 
{
"include": ["src/**/*.ts"]
}

# Run compodoc in your project root and serve it on http://127.0.0.1:8080 (will output html based documentation in ./documentation path.
npx compodoc -p tsconfig.doc.json -s

How to update Angular packages minor and patch versions

The simple way

This dont always work but here is a simplistic approach:

  • Delete your node_modules folder and package-lock.json to clear any cached or conflicting dependencies.
  • Make sure all @angular packages are set to the exact same version in package.json (e.g., 19.2.14).
  • Run
npm install
  • If that does not work continue below

Get list of available package updates

Use the npm-check-updates command to get a list of recommended version updates for all npm packages in the project. (E.g. what is the latest available version number for all the packages)

In Angular project root (where the package.json file is) run:
npx npm-check-updates
(is just a dry run wont change anything)

npx npm-check-updates -u
(updates the package.jon file, follow up by npm install to actually install the new versions)

More info: https://www.npmjs.com/package/npm-check-updates

Bump all packages

A recommended approach is to update all “Angular” type of packages first and then any “non Angular packages”.
In Angular project root edit package.json:

Bump all packages with the word “angular” in them to the latest version number (see output from the npm-check-updates command). See this PR diff as an example:
https://dev.azure.com/who-umc/Products/_git/CAT/pullrequest/12413?_a=files&path=/Umc.Cat.Core/src/ClientSPA/package.json
image.png

Then run:
npm install
-> might get dependency errors, cant install

npm install --force
-> forces the install of angular packages
In the above mentioned scenario (just bump angular packages) this works.

As a second step; repeat this for all non-angular packages.

Package.json version interval handling

Whats the difference between ~ and ^ in the acceptable version “interval” value in package.json?
See:
https://stackoverflow.com/questions/22343224/whats-the-difference-between-tilde-and-caret-in-package-json

value desc
~version Approximately equivalent to version, i.e., only accept new patch versions
See npm semver – Tilde Ranges
^version Compatible with version, i.e., accept new minor and patch versions
See npm semver – Caret Ranges
version Must match version exactly
>version Must be greater than version
>=version Must be equal or greater than version
<version Must be lesser than version
<=version Must be equal or lesser than version
1.2.x 1.2.0, 1.2.1, etc., but not 1.3.0
* Matches any version
latest Obtains latest release

The above list is not exhaustive. Other version specifiers include GitHub urls and GitHub user repo’s, local paths and packages with specific npm tags

Official Docs

More tips see this blobpost:
https://www.hostingadvice.com/how-to/update-npm-packages/

A useful npm command for showing peer dependencies of 1 level down:

npm ls --depth=1

(Vary the depth number to show deeper dependencies)

Angular Error Handling

Here is an excellent blog post regarding Angular Error Handling:

Error handling is as much of an important topic as it is also hated, and even more so, overlooked. Of course, we all enjoy authoring cool features, fascinating animations and beautiful UIs, but not so much do we love writing a bunch of code whose only purpose is to save us when something goes wrong.

However, an important part of a developer’s journey to maturity is realizing that errors are inescapable. A third-party library might contain a bug; a network request might fail; something might be wrong with the end user’s machine. In all such scenarios – and more – we need to be able to meet these errors gracefully, and not allow our application to break because of simple scenarios that we are capable of anticipating.

Source: Angular Error Handling

Zoneless in Angular version 20 – going from zone.js to zoneless

How to move from from zone.js change detection into zoneless Angular summary.

Zoneless Angular marks a shift away from Zone.js toward a more modern and efficient approach. Let’s find out what it means and how to prepare your apps to be future-proof and ready for what’s next.

Source: Zoneless Angular – Angular Experts

Testing Components with children – Testing Angular

Testing Components with children

  • Rendering a Component with or without its children
  • Checking that the parent and its children are wired up correctly
  • Replacing child Components with fakes
  • Using the ng-mocks library to fake dependencies

Source: Testing Components with children – Testing Angular

“Expression has changed after it was checked” – error in Angular

The “Expression has changed after it was checked” error in Angular indicates that a component property was updated during Angular’s change detection cycle, causing a mismatch between the DOM and the component’s data. To fix this, you can delay the update by using setTimeoutPromise.then, or an asynchronous observable, or update the property in a lifecycle hook before the DOM update. 

Here’s a more detailed explanation and common solutions:

Understanding the Error
  • Angular’s change detection mechanism checks for changes in component properties and updates the DOM accordingly. 
  • The error occurs when a change is made to a component property during this detection cycle, before the DOM has a chance to reflect the change. 
  • This can happen with asynchronous operations like HTTP requests, timers, or event listeners that update data within the change detection cycle. 
Solutions
  1. Delay the Update with setTimeoutPromise.then, or Asynchronous Observable:
    • Wrap the code that modifies the component property in a setTimeoutPromise.then, or an asynchronous observable (like RxJS).
    • This forces the update to happen after the current change detection cycle is complete, preventing the error. 
TypeScript
    setTimeout(() => {      this.myProperty = newValue;    }, 0);
TypeScript
    Promise.resolve().then(() => {      this.myProperty = newValue;    });
TypeScript
    fromEvent(document, 'click').subscribe(() => {      this.myProperty = newValue;    });
  1. 1. Update the Property in a Lifecycle Hook:
    • Move the code that modifies the component property to a lifecycle hook like ngOnInitngAfterContentInit, or ngAfterViewInit. 
    • These hooks are called after Angular has completed its initial change detection and DOM updates, so the change is less likely to interfere with the cycle. 
  2. 2. Manually Trigger Change Detection (Use with Caution):
    • Inject ChangeDetectorRef into your component and use detectChanges() to manually trigger change detection. 
    • This can be useful in specific scenarios, but it’s generally best to avoid manually triggering change detection and use asynchronous solutions or lifecycle hooks whenever possible. 
  3. 3. Refactor your code:
    • Identify the component, the binding, and the expression that are causing the issue. 
    • Determine which property is changing the expression’s result between the regular detectChanges and the checkNoChanges checks. 
    • Refactor your code to prevent changes to the property during the change detection cycle. 
    • For example, move the update to a lifecycle hook or use asynchronous operations. 
Debugging
  • The error message and stack trace can help you pinpoint the exact location where the change is happening.
  • Use the Chrome DevTools debugger to set breakpoints and inspect the values of variables during the change detection cycle.
  • Angular University has a blog post on debugging “Expression Changed” errors that can be helpful. 
Important Considerations
  • Avoid updating component properties directly within template expressions or event handlers. 
  • Use the correct lifecycle hooks for your use case to ensure that updates occur at the appropriate time. 
  • If you need to update the DOM or perform other actions that might interfere with change detection, consider using asynchronous operations or manually triggering change detection. 

Angular Testing Library | Testing Library

The problem

You want to write maintainable tests for your Angular components. As a part of this goal, you want your tests to avoid including implementation details of your components and rather focus on making your tests give you the confidence for which they are intended. As part of this, you want your testbase to be maintainable in the long run so refactors of your components (changes to implementation but not functionality) don’t break your tests and slow you and your team down.

This solution

The Angular Testing Library is a very lightweight solution for testing Angular components. It provides light utility functions on top of DOM Testing Library in a way that encourages better testing practices. Its primary guiding principle is:

The more your tests resemble the way your software is used, the more confidence they can give you.

So rather than dealing with instances of rendered Angular components, your tests will work with actual DOM nodes. The utilities this library provides facilitate querying the DOM in the same way the user would. Finding form elements by their label text (just like a user would), finding links and buttons from their text (like a user would). It also exposes a recommended way to find elements by a data-testid as an “escape hatch” for elements where the text content and label do not make sense or is not practical.

This library encourages your applications to be more accessible and allows you to get your tests closer to using your components the way a user will, which allows your tests to give you more confidence that your application will work when a real user uses it.

Source: Angular Testing Library | Testing Library

API rate limiter in .NET Core 8

.NET Core 8 have built-in API rate limiter functionality.
Can be used in an API project like this in program.cs:

app.UseRateLimiter();

//(PUT BELOW CODE AFTER LINE: var app = builder.Build();)
//Setup API request rate limiter
//If a rate limit is exceeded in ASP.NET Core's Rate Limiting Middleware 
//HTTP response will have the status code: 429 Too Many Requests
builder.Services.AddRateLimiter(options =>
{
    options.AddFixedWindowLimiter(
        "default",
        limiterOptions =>
        {
            limiterOptions.PermitLimit = 10; // Allow 10 requests
            limiterOptions.Window = TimeSpan.FromSeconds(1); // Per second
            limiterOptions.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
            limiterOptions.QueueLimit = 2; // Allow 2 queued requests
        }
    );
});