0

I have declared a global variable in angular class like

public weatherImage: string = "";

Now I have a javascript method inside angular class

public getWeather(city: string) {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function () {
      if (this.readyState === 4 && this.status === 200) {
        var weatherImage = "https:" + JSON.parse(this.responseText)['current']['condition']['icon'];
        var weather = JSON.parse(this.responseText)['current']['condition']['text'];
        var temperature = JSON.parse(this.responseText)['current']['temp_c'];

        //this.weatherImage = weatherImage;
        console.log(weatherImage);
        console.log(weather);
        console.log(temperature);
      }
    };
    xhttp.open("get", "https://api.apixu.com/v1/current.json?key=533920d31cc44af491660306182603&q="+city, true);
    xhttp.send();
  }

but javascript doesn't let me use that weatherImage variable. How I can achieve this

Note: I have use ajax request using javascript rather than angular due CORS issue in angular.

Full class code

import { Component, OnInit } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

@Component({
  selector: 'app-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {

  public navbarOpen = false;
  public language: string = "";
  private transData: string[] = [];
  public weatherImage: string = "";
  public temparature: string = "";
  public city: string = "";
  public weather: string = "";
  private cities: string[] = ["", "", "", ""];

  constructor(
    private translate: TranslateService
  ) { }

  ngOnInit() {
    if (localStorage.getItem('pcLang') == "en") {
      this.language = "Eng";
      this.translate.use("en");
    } else {
      this.language = "नेपाली";
      this.translate.use("ne");
    }

    this.getWeather("Kathmandu");
  }

  public getWeather(city: string) {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function () {
      if (this.readyState === 4 && this.status === 200) {
        var weatherImage = "https:" + JSON.parse(this.responseText)['current']['condition']['icon'];
        var weather = JSON.parse(this.responseText)['current']['condition']['text'];
        var temperature = JSON.parse(this.responseText)['current']['temp_c'];

       weatherImage = weatherImage;
        console.log(weatherImage);
        console.log(weather);
        console.log(temperature);
      }
    };
    xhttp.open("get", "https://api.apixu.com/v1/current.json?key=533920d31cc44af491660306182603&q="+city, true);
    xhttp.send();
  }

  toggleNavbar() {
    this.navbarOpen = !this.navbarOpen;
  }

  public changeLanguage() {
    if (this.language == "Eng") {
      this.language = "नेपाली";
      this.setLanguage("ne");
    } else {
      this.language = "Eng";
      this.setLanguage("en");
    }
  }

  private getTranslation() {
    this.translate.get(['ARE_YOU_SURE', 'YES_LOGOUT', 'CANCEL']).subscribe(
      (result: [string]) => {
        this.transData = result;
      }
    );
  }

  private setLanguage(lang): void {
    this.translate.use(lang);
    localStorage.setItem('pcLang', lang);
    this.getTranslation();
  }

}
Chris Hadfield
  • 494
  • 1
  • 7
  • 34
  • 1
    What do you mean doesnt let you? – callback Oct 29 '18 at 18:01
  • what does this.weatherImage refer too? how are you calling the method? – Joe Warner Oct 29 '18 at 18:02
  • What do you mean by "doesn't let me"? Also, Angular isn't a language, it's a framework that uses JavaScript/TypeScript as its language, so I'm a little confused why you're referring to it and JavaScript as if they're completely different things. – John Montgomery Oct 29 '18 at 18:02
  • CORS is not an angular issue, it is just implementing it securely. Instead of avoiding it by using insecure javascript, use angular http client and resolve the CORS issue separately. This can be done either through proxy config within angular: https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/proxy.md or CORS config in the api. – lupus137 Oct 29 '18 at 18:03
  • cors issue in angular im so confused lol i think you're confusing a few things if we strip it back to i cant access this.weatherImage we can try work on that first xD – Joe Warner Oct 29 '18 at 18:04
  • @callback - I can't access the `weatherImage` variable that I have declared in the just above the constructor. It says `Propery weatherImage doesn't exist on type XMLHttpRequest` – Chris Hadfield Oct 29 '18 at 18:08
  • 2
    Possible duplicate of [How to access the correct \`this\` inside a callback?](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) – ConnorsFan Oct 29 '18 at 18:10
  • To access the class members, define the callback as an arrow function: `xhttp.onreadystatechange = () => { ... }`, or define `that` before the callback. – ConnorsFan Oct 29 '18 at 18:11
  • if you have a js program and and angular program running on the same page. You can use element.scope() to access scope variables. Or you can cheat using localStorage – Ji_in_coding Oct 29 '18 at 18:11
  • 1
    try assigning `this` to a variable and then call the function or access the fields through it. eg. constructor(){var self = this;} foo(){ var self = this; self.fieldname = "value"; go();} go(){var self = this; console.log(this.fieldsname);} – jatinder bhola Oct 29 '18 at 18:17

1 Answers1

2

Issue

The issue is with context this. this will point to different instance rather than NavbarComponent.

Fix

You can keep the reference of NavbarComponent by using extra variable self.

See the following modified code -

public getWeather(city: string) {
    var self = this; //<----keep the current context
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function () {
      if (this.readyState === 4 && this.status === 200) {
        var weatherImage = "https:" + JSON.parse(this.responseText)['current']['condition']['icon'];
        var weather = JSON.parse(this.responseText)['current']['condition']['text'];
        var temperature = JSON.parse(this.responseText)['current']['temp_c'];

        self.weatherImage = weatherImage; //<-- self is used here.
        console.log(weatherImage);
        console.log(weather);
        console.log(temperature);
      }
    };
    xhttp.open("get", "https://api.apixu.com/v1/current.json?key=533920d31cc44af491660306182603&q="+city, true);
    xhttp.send();
  }

Note : You had mentioned in your question you are using this approach to avoid CORS issue however it will not fix your CORS issue.

Community
  • 1
  • 1
Sunil Singh
  • 11,001
  • 2
  • 27
  • 48