Weather App Using Angular
We will be creating a weather application using the Angular framework. This app will allow users to check the current weather conditions by entering a city name. It will provide detailed information including temperature, weather description, wind speed, and humidity. With responsive design and interactive features, the app will offer a user-friendly experience across various devices.
Project Preview

Prerequisites
Approach
- We will initialize an Angular project to build a weather application, setting up the basic structure and components.
- We will use custom CSS to style the app, ensuring a clean and responsive design.
- We will integrate the OpenWeatherMap API to fetch and display real-time weather data based on user input.
- We will implement features to show temperature, weather description, wind speed, and humidity, with proper error handling and a loading indicator for a smooth user experience.
Steps to Create Weather App using Angular
Step 1: Install Angular CLI
If you haven’t installed Angular CLI yet, install it using the following command
npm install -g @angular/cli
Step 2: Create a New Angular Project
ng new weather-app --no-standalone
cd weather-app
Step 3: Create a Component
Create a component. You can generate a component using the Angular CLI:
ng generate component weather-app
Step 4: Install dependencies
Install moment library for real-time date fetching:
ng install moment --save
Dependencies
"dependencies": {
"@angular/animations": "^18.2.1",
"@angular/common": "^18.2.1",
"@angular/compiler": "^18.2.1",
"@angular/core": "^18.2.1",
"@angular/forms": "^18.2.1",
"@angular/platform-browser": "^18.2.1",
"@angular/platform-browser-dynamic": "^18.2.1",
"@angular/router": "^18.2.1",
"moment": "^2.30.1",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.10"
}
Folder Structure

Example: Create the required files as seen in the folder structure and add the following codes.
Weather Component
Below mentioned is Weather Component having HTML, CSS and JavaScript code having an input field to add state name and a Get Weather Button to show the weather update along with humidity and wind speed.
<!--weather-app.component.html-->
<div class="container">
<div class="weather-card">
<h1 style="color: green;">
GeeksforGeeks
</h1>
<h3>
Weather App Using Angular
</h3>
<input type="text" [(ngModel)]="cityName" placeholder="Enter city name">
<button (click)="getWeather()">Get Weather</button>
<div *ngIf="loading" class="loading">
Loading...
</div>
<div *ngIf="error" class="error-message">
{{ error }}
</div>
<div *ngIf="weatherData" class="animate__animated animate__fadeIn" id="weather-info">
<h3 id="city-name">{{ weatherData.name }}</h3>
<p id="date">{{ currentDate }}</p>
<img [src]="iconUrl" alt="Weather Icon" id="weather-icon">
<p id="temperature">{{ weatherData.main.temp }}°C</p>
<p id="description">{{ weatherData.weather[0].description }}</p>
<p id="humidity">Humidity: {{ weatherData.main.humidity }}%</p>
<p id="wind-speed">Wind Speed: {{ weatherData.wind.speed }} m/s</p>
</div>
</div>
</div>
/**weather-app.component.css**/
body {
margin: 0;
font-family: 'Montserrat', sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(to right, #4CAF50, #2196F3);
}
.container {
text-align: center;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
}
.weather-card {
background-color: rgba(255, 255, 255, 0.95);
border-radius: 20px;
border: 2px solid #f44336;
padding: 30px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease-in-out;
width: 100%;
max-width: 450px;
animation: fadeIn 1s ease-in-out;
}
.weather-card:hover {
transform: scale(1.05);
}
input[type="text"] {
padding: 15px;
margin: 10px 0;
width: 100%;
max-width: 300px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 16px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
transition: border-color 0.3s ease-in-out;
}
input[type="text"]:focus {
outline: none;
border-color: #2196F3;
}
input[type="text"]::placeholder {
color: #aaa;
}
button {
padding: 12px 20px;
margin-top: 10px;
background-color: #2196F3;
color: #fff;
border: none;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
transition: background-color 0.3s ease-in-out, transform 0.3s ease-in-out;
}
button:hover {
background-color: #1565C0;
transform: translateY(-3px);
}
#weather-info {
display: none;
margin-top: 20px;
animation: fadeIn 1s ease-in-out;
}
#weather-icon {
width: 100px;
height: 100px;
}
#temperature {
font-size: 26px;
font-weight: bold;
color: #333;
margin: 8px 0;
}
#description {
font-size: 20px;
color: #555;
margin-bottom: 10px;
}
#wind-speed,
#humidity,
#date {
font-size: 16px;
color: #555;
}
#date {
margin-bottom: 5px;
color: #888;
}
.loading {
font-size: 18px;
color: #2196F3;
margin-top: 20px;
}
.error-message {
font-size: 18px;
color: #f44336;
margin-top: 20px;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@media (max-width: 600px) {
.weather-card {
padding: 20px;
width: 90%;
}
input[type="text"] {
font-size: 14px;
}
button {
font-size: 14px;
}
#temperature {
font-size: 22px;
}
#description {
font-size: 18px;
}
#wind-speed,
#humidity,
#date {
font-size: 14px;
}
}
// weather-app.component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { WeatherAppComponent } from './weather-app.component';
describe('WeatherAppComponent', () => {
let component: WeatherAppComponent;
let fixture: ComponentFixture<WeatherAppComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [WeatherAppComponent]
});
fixture = TestBed.createComponent(WeatherAppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
// weather-app.component.ts
import { Component, OnInit } from '@angular/core';
import moment from 'moment';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-weather-app',
templateUrl: './weather-app.component.html',
styleUrls: ['./weather-app.component.css']
})
export class WeatherAppComponent implements OnInit {
cityName: string = 'Pune';
weatherData: any;
iconUrl: string = '';
currentDate: string = '';
loading: boolean = false;
error: string = '';
private url = 'https://api.openweathermap.org/data/2.5/weather';
private apiKey = 'f00c38e0279b7bc85480c3fe775d518c';
constructor(private http: HttpClient) { }
ngOnInit(): void {
this.getWeather();
}
getWeather(): void {
this.loading = true;
this.error = '';
const fullUrl = `${this.url}?q=${this.cityName}&appid=${this.apiKey}&units=metric`;
this.http.get(fullUrl).subscribe(
(data: any) => {
this.weatherData = data;
this.iconUrl = `https://openweathermap.org/img/w/${data.weather[0].icon}.png`;
this.currentDate = moment().format('MMMM Do YYYY, h:mm:ss a');
document.getElementById('weather-info')?.style.setProperty('display', 'block');
this.loading = false;
},
(error) => {
this.error = 'City not found. Please try again.';
this.loading = false;
console.error('Error fetching weather data:', error);
}
);
}
}
App Component
Below mentioned is the App Component having app.component.html, app.module.ts and app.component.ts file. Having selector of weather component in HTML file and necessary imports in app.module.ts file.
<!--app.component.html-->
<app-weather-app></app-weather-app>
// app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'weather-app';
}
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { WeatherAppComponent } from './weather-app/weather-app.component';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { FormsModule } from '@angular/forms';
@NgModule({
declarations: [
AppComponent,
WeatherAppComponent
],
bootstrap: [AppComponent], imports: [BrowserModule,
FormsModule], providers: [provideHttpClient(withInterceptorsFromDi())]
})
export class AppModule { }
Complete Code:
<!--weather-app.component.html-->
<div class="container">
<div class="weather-card">
<h1 style="color: green;">
GeeksforGeeks
</h1>
<h3>
Weather App Using Angular
</h3>
<input type="text" [(ngModel)]="cityName" placeholder="Enter city name">
<button (click)="getWeather()">Get Weather</button>
<div *ngIf="loading" class="loading">
Loading...
</div>
<div *ngIf="error" class="error-message">
{{ error }}
</div>
<div *ngIf="weatherData" class="animate__animated animate__fadeIn" id="weather-info">
<h3 id="city-name">{{ weatherData.name }}</h3>
<p id="date">{{ currentDate }}</p>
<img [src]="iconUrl" alt="Weather Icon" id="weather-icon">
<p id="temperature">{{ weatherData.main.temp }}°C</p>
<p id="description">{{ weatherData.weather[0].description }}</p>
<p id="humidity">Humidity: {{ weatherData.main.humidity }}%</p>
<p id="wind-speed">Wind Speed: {{ weatherData.wind.speed }} m/s</p>
</div>
</div>
</div>
<!--app.component.html-->
<app-weather-app></app-weather-app>
/**weather-app.component.css**/
body {
margin: 0;
font-family: 'Montserrat', sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(to right, #4CAF50, #2196F3);
}
.container {
text-align: center;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
padding: 20px;
}
.weather-card {
background-color: rgba(255, 255, 255, 0.95);
border-radius: 20px;
border: 2px solid #f44336;
padding: 30px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease-in-out;
width: 100%;
max-width: 450px;
animation: fadeIn 1s ease-in-out;
}
.weather-card:hover {
transform: scale(1.05);
}
input[type="text"] {
padding: 15px;
margin: 10px 0;
width: 100%;
max-width: 300px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 16px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
transition: border-color 0.3s ease-in-out;
}
input[type="text"]:focus {
outline: none;
border-color: #2196F3;
}
input[type="text"]::placeholder {
color: #aaa;
}
button {
padding: 12px 20px;
margin-top: 10px;
background-color: #2196F3;
color: #fff;
border: none;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
transition: background-color 0.3s ease-in-out, transform 0.3s ease-in-out;
}
button:hover {
background-color: #1565C0;
transform: translateY(-3px);
}
#weather-info {
display: none;
margin-top: 20px;
animation: fadeIn 1s ease-in-out;
}
#weather-icon {
width: 100px;
height: 100px;
}
#temperature {
font-size: 26px;
font-weight: bold;
color: #333;
margin: 8px 0;
}
#description {
font-size: 20px;
color: #555;
margin-bottom: 10px;
}
#wind-speed,
#humidity,
#date {
font-size: 16px;
color: #555;
}
#date {
margin-bottom: 5px;
color: #888;
}
.loading {
font-size: 18px;
color: #2196F3;
margin-top: 20px;
}
.error-message {
font-size: 18px;
color: #f44336;
margin-top: 20px;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@media (max-width: 600px) {
.weather-card {
padding: 20px;
width: 90%;
}
input[type="text"] {
font-size: 14px;
}
button {
font-size: 14px;
}
#temperature {
font-size: 22px;
}
#description {
font-size: 18px;
}
#wind-speed,
#humidity,
#date {
font-size: 14px;
}
}
// weather-app.component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { WeatherAppComponent } from './weather-app.component';
describe('WeatherAppComponent', () => {
let component: WeatherAppComponent;
let fixture: ComponentFixture<WeatherAppComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [WeatherAppComponent]
});
fixture = TestBed.createComponent(WeatherAppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
// weather-app.component.ts
import { Component, OnInit } from '@angular/core';
import moment from 'moment';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-weather-app',
templateUrl: './weather-app.component.html',
styleUrls: ['./weather-app.component.css']
})
export class WeatherAppComponent implements OnInit {
cityName: string = 'Pune';
weatherData: any;
iconUrl: string = '';
currentDate: string = '';
loading: boolean = false;
error: string = '';
private url = 'https://api.openweathermap.org/data/2.5/weather';
private apiKey = 'f00c38e0279b7bc85480c3fe775d518c';
constructor(private http: HttpClient) { }
ngOnInit(): void {
this.getWeather();
}
getWeather(): void {
this.loading = true;
this.error = '';
const fullUrl = `${this.url}?q=${this.cityName}&appid=${this.apiKey}&units=metric`;
this.http.get(fullUrl).subscribe(
(data: any) => {
this.weatherData = data;
this.iconUrl = `https://openweathermap.org/img/w/${data.weather[0].icon}.png`;
this.currentDate = moment().format('MMMM Do YYYY, h:mm:ss a');
document.getElementById('weather-info')?.style.setProperty('display', 'block');
this.loading = false;
},
(error) => {
this.error = 'City not found. Please try again.';
this.loading = false;
console.error('Error fetching weather data:', error);
}
);
}
}
// app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'weather-app';
}
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { WeatherAppComponent } from './weather-app/weather-app.component';
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { FormsModule } from '@angular/forms';
@NgModule({
declarations: [
AppComponent,
WeatherAppComponent
],
bootstrap: [AppComponent], imports: [BrowserModule,
FormsModule], providers: [provideHttpClient(withInterceptorsFromDi())]
})
export class AppModule { }
Open the terminal, run this command from your root directory to start the application
ng serve --open
Open your browser and navigate to http://localhost:4200
Output