Weather App Using Angular (original) (raw)
Last Updated : 29 Aug, 2024
**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
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",0.14.10"
"tslib": "^2.3.0",
"zone.js": "
}
Folder Structure
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.
HTML `
GeeksforGeeks
Weather App Using Angular
Get Weather <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>
CSS
/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;
}
}
JavaScript
// 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;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [WeatherAppComponent]
});
fixture = TestBed.createComponent(WeatherAppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
` JavaScript ``
// 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.
HTML `
JavaScript
// 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'; }
JavaScript
// 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:
HTML `
GeeksforGeeks
Weather App Using Angular
Get Weather <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>
HTML
CSS
/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;
}
}
JavaScript
// 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;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [WeatherAppComponent]
});
fixture = TestBed.createComponent(WeatherAppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
` JavaScript ``
// 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);
}
);
}
}
`` JavaScript `
// 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'; }
JavaScript
// 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