Skip to main content

2 posts tagged with "Angular"

View All Tags

Speedrun .NET + Angular

· 5 min read
Guster
Full-stack Staff Engineer

image

Introduction

Recently, I had an initial interview with a new company that uses Angular and .NET as its tech stack. Frankly, these two frameworks are pretty unfamiliar to me. I used to work with Angular.js back when it was still v1, which was about 8 years ago. I remember it was renamed to just Angular starting from v2, and now it's already at v18.

What about .NET? Even worse, I have never used it in my entire life! In fact, I don't know C# at all. Though I've heard a lot about it and that it's similar to Java.

Long story short, regardless of whether I advance to the next interview, I decided to take this as an opportunity to learn some new skills. However, I don't want to spend too much time learning. So, I decided to start a speed run on learning .NET and Angular.

How I learn

How I usually learn a new framework or programming language is by building a sample project. Here are a few pros of this approach:

  • Less boring - You get to see your half-baked product evolve while going through the tutorial.
  • Learn based on the features you need - It takes time to learn everything, especially with a complex framework like .NET. It's better to learn as you go. For example, if you need user authentication or a database migration.
  • Feels accomplished once the sample project is done and deployed for showcasing!

I have shared some of the notable points I learned from these frameworks here:

A Todo Project

And so, I decided to build a simple Todo task list. This Todo will contain the following features and acceptance criteria:

  • A login page for user authentication
  • Users can create, read, update, and delete a collection (a group of tasks)
  • Users can create, read, update, and delete a task within a collection
  • A main page with a two-pane layout: the left pane shows a list of collections, and the right pane shows the selected collection’s tasks
  • Users must be authenticated to view the main page
  • Basic UI styling (tailwind for the rescue!)
  • Logout functionality

Deployment

Now that I have finished building the API and web app, I want to deploy them somewhere to showcase if needed. Since I already have AWS, I decided to deploy there.

I want it fast and simple, so here’s what I did:

  • Hosted the Angular app on an S3 bucket as a static site
  • Dockerized the .NET API and deployed it to an EC2 instance
  • Created a Postgres instance in RDS

I used Terraform to ease the process of provisioning these resources. Here’s a sample script.

# VPC, subnets, internet gateway, route table and security groups provisioning
# ...

# ==================== RDS ====================
resource "aws_db_instance" "my_rds" {
allocated_storage = 20
engine = "postgres"
engine_version = "16.4"
instance_class = "db.t3.micro"
db_name = "mydatabase"
username = "username"
password = "password"
vpc_security_group_ids = [aws_security_group.rds_sg.id]
db_subnet_group_name = aws_db_subnet_group.my_db_subnet_group.name
skip_final_snapshot = true
publicly_accessible = false
}
resource "aws_db_subnet_group" "my_db_subnet_group" {
name = "my-db-subnet-group"
subnet_ids = [
aws_subnet.private_subnet_a.id,
aws_subnet.private_subnet_b.id
]
}

# ==================== EC2 ====================
resource "aws_instance" "dotnet_todo_instance" {
ami = "ami-0a6b545f62129c495"
instance_type = "t2.micro"
subnet_id = aws_subnet.public_subnet_a.id
vpc_security_group_ids = [aws_security_group.ec2_sg.id]
tags = {
Name = "dotnet-todo-ec2"
}
}

# ==================== S3 ====================
resource "aws_s3_bucket" "dotnet_todo_web" {
bucket = "dotnet-todo-web"
}
resource "aws_s3_bucket_policy" "dotnet_todo_web_policy" {
bucket = aws_s3_bucket.dotnet_todo_web.id
policy = jsonencode(
{
Version = "2012-10-17"
Statement = [
{
Sid = "PublicReadGetObject"
Action = "s3:GetObject"
Effect = "Allow"
Principal = "*"
Resource = "${aws_s3_bucket.dotnet_todo_web.arn}/*"
},
]
}
)
}

Result

Screenshot 2024-08-19 at 10.34.42 PM.png

Screenshot 2024-08-19 at 10.34.27 PM.png

Concluding Thoughts

Overall, it took me roughly one week to learn Angular, .NET, and complete the project. From a developer's perspective, the experience was quite smooth and easy. I found Angular's opinionated structure to be particularly beneficial. Its out-of-the-box common libraries saved me a significant amount of time that I would have otherwise spent searching for third-party solutions. This allowed me to focus more on building the actual features of my project rather than dealing with setup complexities.

When it comes to .NET, although I don’t particularly like C#’s Pascal-case naming conventions and its syntax formatting, I must admit that .NET is very easy to set up, develop, and build. I found the CLI and generators to be especially helpful tools that streamlined the development process. These tools provided a robust foundation, making it easier to manage and organize the codebase efficiently.

I built a simple todo for this project, but the learning experience has inspired me to explore more complex projects using Angular and .NET. I am definitely going to start building more with Angular and .NET in the future. The combination of these frameworks provides a powerful and efficient development environment that I am excited to continue exploring.

My Angular 18 crash course

· 5 min read
Guster
Full-stack Staff Engineer

image

Introduction

Angular is a powerful and versatile web application framework that enables developers to create robust, high-performance applications with ease. It provides a rich set of tools and features designed to streamline the development process and enhance code maintainability. By leveraging Angular's component-based architecture, developers can build scalable and modular applications that are both efficient and easy to maintain.

In this guide, I’ll briefly walk you through the essential steps to set up and run an Angular project, giving you a solid foundation to start your journey into Angular development. From installation and project creation to understanding the core concepts.

Installation

Prerequisites

  • Node.js - v18.9.1 or newer
  • CLI

Install Angular CLI

npm install -g @angular/cli

For more details, follow the installation guide on the official documentation.

CLI Commands

  • ng new <project-name> - Create a new project

  • ng generate - Generate Angular resources

    • ng generate component <name> - Generate component
    • ng generate service <name> - Generate service class
    • ng generate class <name> - Generate a class
    • ng generate directive <name> - Generate a directive
    • ng generate interceptor <name> - Generate an interceptor
    • ng generate guard <name> - Generate a authentication guard
  • npm start - Start local development

  • npm run test - Run unit tests

  • npm run build - Build a project

Create a new project

To create a new project, run command ng new <project_name>, eg. ng new my-todo-app, this will generate a new project with the following file structure. The source codes will be inside the /src directory.

.
├── README.md
├── angular.json
├── dist
├── package-lock.json
├── package.json
├── public
├── server.ts
├── src
├── tsconfig.app.json
├── tsconfig.json
└── tsconfig.spec.json

Component

When we generate a Angular component with ng generate component, the CLI will scaffold the following files. Example:

src/app/
├── app.component.css
├── app.component.html
├── app.component.spec.ts
├── app.component.ts

These files are self-explanatory: the .css file contains the CSS styling, while the .html file defines the component's UI, and .spec for unit test.

Alternatively, we can use the template and styles attributes in the @Component decorator to include CSS and HTML code directly in app.component.ts, creating a single-file component.

Component with external template and CSS:

@Component({
selector: 'app-root',
standalone: true,
imports: [],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent {}

Single-file component:

@Component({
selector: 'app-root',
standalone: true,
imports: [],
template: `<div>hello world</div>`,
styles: {...}
})
export class AppComponent {}

A component can be used in a template with its selector. For example, if you want to use a custom component <my-custom-button>in this component, you first need to import it with imports: [MyCustomButton]

@Component({
selector: 'app-root',
standalone: true,
imports: [MyCustomButton],
styleUrl: './app.component.css',
template: `
<my-custom-button></my-custom-button>
`,
})
export class AppComponent {}

Dependency Injection (DI)

Make a class Injectable

Dependency Injection (DI) is a core concept in Angular, widely used throughout the application. DI allows us to incorporate dependencies into classes while Angular manages their lifecycle.

To make a class injectable, decorate it with the @Injectable decorator. For instance, consider a service class named AuthService.

@Injectable({ providedIn: 'root' })
class AuthService {}

The providedIn: 'root' option tells Angular to provide AuthService at the application's root level, allowing it to be injected into all other classes. This approach enables Angular and JavaScript code optimizers to effectively remove unused services—a process known as "tree-shaking."

Injecting a dependency

Once we have made a class injectable with @Injectable, there are two ways we can use it in other classes.

  1. Inject in the constructor

    @Component({})
    class AppComponent {
    constructor(private service: AuthService) {}
    }
  2. Inject with the built-in inject method

    @Component({})
    class AppComponent {
    private service = inject(AuthService);
    }

💡 Tips: Angular CLI provides a quick way to create a service class: ng generate service services/auth

This create a AuthService in /services directory

Routing

Angular features a built-in router for implementing navigation between pages. Here are the steps to set up the navigation routes:

  1. Add provideRouter in app.config.ts

    export const appConfig: ApplicationConfig = {
    providers: [provideRouter(routes)]
    };
  2. Setup a list of routes in app.routes.ts

    export const routes: Routes = [
    { path: '', component: MainPage },
    { path: 'login', component: LoginPage },
    { path: '**', component: NotFoundPage }, // all other routes
    ];
  3. Add RouterLinkRouterLinkActive, and RouterOutlet to your AppComponent's imports option

    @Component({
    selector: 'app-root',
    standalone: true,
    imports: [RouterOutlet, RouterLink, RouterLinkActive],
    templateUrl: './app.component.html',
    styleUrl: './app.component.css'
    })
    export class AppComponent {}
  4. Add the routes to your app-component.html. <router-outlet> tells Angular to render the selected route’s component view into the application.

    <nav>
    <ul>
    <li><a routerLink="/" routerLinkActive="active" ariaCurrentWhenActive="page">Home</a></li>
    <li><a routerLink="/login" routerLinkActive="active" ariaCurrentWhenActive="page">Login</a></li>
    </ul>
    </nav>

    <router-outlet></router-outlet>

For more advanced routing techniques in Angular, visit the official documentation.

Environment Configuration

Angular has a built-in feature to customise configuration for different environments such as dev, staging, prod, etc. Follow the steps below.

Step 1:

Run ng generate environments to generate default environment files. Angular will generate the following files:

  • environments/environment.ts - file as the default config
  • angular.json - where you define the environments

Step 2:

Create a custom environment file, eg. environments/environment.staging.ts and copy the values from the default config file here.

Step 3:

Run ng build --configuration staging and it will replace the environments/environment.ts with environments/environment.staging.ts

Concluding Thoughts

Angular is a comprehensive web framework packed with built-in features that enable efficient and unified web application development. This guide merely scratches the surface of Angular's capabilities. For a deep dive into its more advanced features, check out the official documentation.