0

I'm new to angular and trying to build a simple weather application. Whenever I try to pass the value of city in the form on ngSubmit to the api service, it's not at all working. I have tried to implement using Emitter Event, but it seems that the city value is not getting updated in the service. Is there a way, how we can send this value to the api service.

weather-card.component.html

<div class="input-container">
  <app-weather-form></app-weather-form>
</div>
<div *ngFor="let item of weathers[0]; first as isFirst">
  <div *ngIf="!isFirst">
    <mat-card class="mat-card">
      <p><strong>Name :</strong>{{ item.name }}</p>
      <p><strong>State :</strong> {{ item.region }}</p>
      <p><strong>Country :</strong>{{ item.country }}</p>
      <p><strong>Latitude:</strong> {{ item.lat }}</p>
      <p><strong>Longitude:</strong> {{ item.lon }}</p>
    </mat-card>
  </div>
</div>

weather-card.component.ts

import { Component, OnInit, Output, EventEmitter } from '@angular/core';
import { WeatherService } from '../../services/weather.service';
import { WeatherData } from '../../models/weather';
import { WeatherFormComponent } from '../weather-form/weather-form.component';

@Component({
  selector: 'app-weather-card',
  templateUrl: './weather-card.component.html',
  styleUrls: ['./weather-card.component.scss'],
})
export class WeatherCardComponent implements OnInit {
  weathers: any = [];

  constructor(public weatherService: WeatherService) {}

  ngOnInit() {
    this.getUsers();
  }

  getUsers() {
    this.weatherService.getWeatherData().subscribe((data) => {
      this.weathers = Object.entries(data);
      console.log(this.weathers);
    });
  }
}

weather-form.component.html

<form (ngSubmit)="submit()">
  City:<br />
  <input type="text" name="city" [(ngModel)]="name" /><br />
  <input type="submit" value="Submit" />
</form>

weather-form.component.ts

import { WeatherService } from 'src/app/services/weather.service';
import { WeatherData } from 'src/app/models/weather';

@Component({
  selector: 'app-weather-form',
  templateUrl: './weather-form.component.html',
  styleUrls: ['./weather-form.component.scss'],
})
export class WeatherFormComponent implements OnInit {
  @Output() onSelection: EventEmitter<any> = new EventEmitter();
  weather!: WeatherData;
  name!: '';
  constructor(private weatherService: WeatherService) {}

  ngOnInit(): void {}

  submit() {
    this.weatherService.getWeatherData().subscribe((data: any) => {
      this.onSelection.emit(this.weather);
    });
  }
}

weather.ts

export interface WeatherData {
  name: string;
  region: string;
  country: string;
  humidity: string;
  localtime: string;
  lat: string;
  lon: string;
}

weather.service.ts

import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import {
  HttpClient,
  HttpHeaders,
  HttpErrorResponse,
} from '@angular/common/http';

let serviceUrl: String = 'http://api.weatherapi.com/v1/current.json';
let apiKey: String = 'someAPIKey'; // insert your API key here
let name: String = 'mumbai';
@Injectable({
  providedIn: 'root',
})
export class WeatherService {
  constructor(private http: HttpClient) {}

  getWeatherData() {
    return this.http.get(
      serviceUrl + '?key=' + apiKey + '&q=' + name + '&aqi=no'
    );
  }
}

Correct me if I'm wrong. In the weather.service.ts file, I wanted to change the value of name by passing the value from form and pass it to the URL. Currently, I have hard coded the value.

Sajjad Tabreez
  • 188
  • 4
  • 21
  • 1
    Don't include your api key in the answer! Also what does the "!" do here? It's there in declaration of weather and name fields in the web-form.component.ts – Jayesh Aug 05 '21 at 17:38
  • its probably better to use a form group and a getter even if its just one item with a form builder. regardless though you are not passing the name value into the service so it doesn't know anything about it. just the one you static typed. – chris burd Aug 05 '21 at 17:38
  • 1
    @Jayesh I was editing his answer to remove the keys myself it must have been you that changed them for him. – chris burd Aug 05 '21 at 17:39
  • 1
    @Chris that wasn't me – Jayesh Aug 05 '21 at 17:42
  • I'm not quite sure what you're trying to do but your `` element doesn't even have an output attribute. Such as ``. I'd suggest taking a look at the docs again or be a little more specific – eko Aug 05 '21 at 17:44
  • @eko I was trying to pass the form value i.e the city name to the API service and update the name. As I m new to Angular, I saw some docs where we pass data between components using ViewChild and Event Emitter. But if you see in my weather.service.ts, I have hard coded the value....Is there a way when I click submit on the form, the name value in the service gets changed. – Sajjad Tabreez Aug 05 '21 at 17:47
  • So just put the field inside the method: `this.weatherService.getWeatherData(this.name)`. And update the method in the service so it accepts a variable: `getWeatherData(name: string) {..` – eko Aug 05 '21 at 17:48
  • @eko I tried to follow your method. but it's throwing error Error: src/app/components/weather-card/weather-card.component.ts:21:25 - error TS2554: Expected 1 arguments, but got 0. 21 this.weatherService.getWeatherData().subscribe((data) => { ~~~~~~~~~~~~~~~~ src/app/services/weather.service.ts:18:18 18 getWeatherData(name: string) { ~~~~~~~~~~~~ An argument for 'name' was not provided. – Sajjad Tabreez Aug 05 '21 at 17:55
  • just pass the default string then, or the updated name in the form: `this.weatherService.getWeatherData(this.name).subscribe((data) =>` – eko Aug 05 '21 at 17:57
  • @eko it's not working. – Sajjad Tabreez Aug 05 '21 at 18:18

0 Answers0