Creating an axios URL using Vue data results in receiving the value of undefined

I'm currently experimenting with axios to retrieve data from openweathermap. I've been working on constructing the URL by utilizing various methods to extract latitude and longitude from the user's browser, followed by a function call to piece together the URL.

Although the URL is constructed successfully without any hitches, when attempting to make the API call using axios, some strange occurrences transpire (essentially, I receive my own page's HTML code as the response).

Below is the code snippet:

let weather = new Vue ({
  el: '#weather',
  data: {
    error: '',
    apiUrl: '',
    city: '',
    country: '',
    icon: '',
    description: '',
    results: [],
  },
  methods: {
    getPosition: function() {
      if (navigator.geolocation){
        navigator.geolocation.getCurrentPosition(this.getUrl);
      }else{
        this.error = 'Geolocation is not supported.';
      }
    },
    getUrl: function(position){
      let lat = position.coords.latitude;
      let lon = position.coords.longitude;
      this.apiUrl = buildWeatherUrl(lat, lon);
    },
    getWeather: function(){
      axios.get(this.apiUrl).then(function (response) {
        this.city = response.data.name;
        this.results = response.data;
      }).catch( error => { console.log(error); });
    }
  },
  beforeMount() {
    this.getPosition();
  },
  mounted() {
    this.getWeather();
  }
});

Being new to both Vue and axios, I'm uncertain about where I may have gone wrong. I also attempted adding let self = this; and substituting all instances of this with self in the getWeather method, but that didn't yield any positive results.

The crux of the issue lies in trying to access the URL retrieved from apiUrl, which should be updated by the getUrl method. However, upon executing getWeather post-mounting, the URL doesn't appear to be updated (it works seamlessly if hardcoded).

Thank you for any assistance provided.

Answer №1

I believe the issue lies with this particular line of code:

navigator.geolocation.getCurrentPosition(this.getUrl);
.

When the callback function this.getUrl is executed by the navigator, it loses its reference to the correct this context. As a result,

this.apiUrl = buildWeatherUrl(lat, lon);
will not function correctly. One solution is to bind this to this.getUrl, as shown below:

getPosition: function() {
  if (navigator.geolocation){
    let getUrl = this.getUrl.bind(this)
    navigator.geolocation.getCurrentPosition(getUrl);
  }else{
    this.error = 'Geolocation is not supported.';
  }
},

Alternatively, you can simplify the process by using

navigator.geolocation.getCurrentPosition(this.getUrl.bind(this));

The same issue also exists in the following snippet of code:

axios.get(this.apiUrl).then(function (response) {
    this.city = response.data.name;
    this.results = response.data;
  }).catch( error => { console.log(error); });

To address this, you can either re-implement your previous workaround:

I attempted using let self = this; and replacing all instances of this with self in the getWeather function, but that approach was unsuccessful.

Or you can opt for using arrow functions instead:

axios.get(this.apiUrl).then(response => {
    this.city = response.data.name;
    this.results = response.data;
  }).catch( error => { console.log(error); });

For further guidance on handling Javascript's this, please refer to this comprehensive stack overflow answer:

Make sure to navigate to the section titled "Common problem: Using object methods as callbacks/event handlers" within the provided link.

Answer №2

It appears that the route was mistakenly registered as a POST request instead of a GET request in the routes file. Simply update it to GET and the issue should be resolved.

Answer №3

I encountered a challenge that I was able to resolve by making some adjustments to the Vue code. Initially, I decided to comment out all the Vue code and instead create an empty object named data. I attempted to place the API URL within this object but faced repeated failures. It dawned on me that passing the URL to the object from within

navigator.geolocation.getCurrentPosition
was not feasible. After tinkering with global variables, it struck me that the issue lay in how I was attempting to retrieve the URL from within
navigator.geolocation.getCurrentPosition
.

To address this, I made modifications by including lat and lon in the Vue data and then constructing the URL before invoking axios. This adjustment led to the desired outcome.

For those who may find it helpful, below is the final code snippet:


let weather = new Vue({
  el: '#weather',
  data: {
    error: '',
    lat: 0,
    lon: 0,
    apiUrl: '',
    city: '',
    country: '',
    icon: '',
    description: '',
    results: [],
  },
  methods: {
    getPosition: function() {
      if (navigator.geolocation){
        var vm = this;
        navigator.geolocation.getCurrentPosition(this.updatePosition);
      }else{
        this.error = 'Geolocation is not supported.';
      }
    },
    updatePosition: function(position) {
        this.lat = position.coords.latitude;
        this.lon = position.coords.longitude;
    },
    getWeather: function(){
      let url = buildWeatherUrl(this.lat, this.lon);

      axios
      .get(url)
      .catch(function (error) {
        console.log(error);
      })
      .then(function (response) {
        console.log(response.data);
      });
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Collect all the attribute values of the checkboxes that have been checked and convert them

Is there a way to retrieve the attribute values of all checked checkboxes as an XML string? <input type="checkbox" id="chkDocId1" myattribute="myval1"/> <input type="checkbox" id="chkDocId2" myattribute="myval43"/> <input type="checkbox ...

Struggling with integrating HTML Canvas within Vue.js

Currently, I am attempting to upload an image by utilizing HTML canvas. My decision to use canvas stems from the fact that I will be superimposing additional images based on the data received from the API, and this process seems more straightforward when u ...

Loading message displayed in web browsers by banner rotation system

I'm currently working on a banner rotator function that seems to be showing a "loading" message continuously while running. Here is the code snippet for reference: var banners = ['../Graphics/adv/1.gif','../Graphics/adv/2.jpg']; / ...

How can we enhance the backbone sync feature by appending a query string to the URL?

I am facing an issue with adding a token to the backbone URL query string and I am seeking assistance from you all. Here are three important things to note: There is a REST API that requires a token for each request An NGINX backend handles authenticatio ...

Is there a way to prevent Mac users from using the back and refresh buttons on their browser?

There seems to be a common trend of disabling the back button or refresh button on Windows using JS or Jquery to prevent F5 from working. Can this same method be applied to CMD+R on Mac computers? ...

Gridsome fails to update data following adjustments in API

Currently, I am retrieving data from a Strapi API as a Collection. It is working fine, but whenever I make changes in Strapi, the data does not update in Gridsome. The only way to get the new information is by restarting the Gridsome server. I am running ...

A new value was replaced when assigning a JSON value inside a loop

Is there a way to generate a structure similar to this? { "drink": { "2": { "name": "coke", "type": "drink" }, "3": { "name": "coke", "type": "drink" } }, "food": ...

When utilizing an API to render text into a div, the offsetHeight function may return 0

I'm working with a div that displays text fetched from an API call. I'm trying to implement a See more button if the text exceeds 3 lines. Here is my approach: seeMore(){ this.setState({ seeMore: !this.state.seeMo ...

Encountered a problem while trying to upload a video on bunny stream using node.js

Having trouble uploading videos to the Bunny Stream API using Node.js and Axios. Everything else seems to be working fine, like fetching, deleting, changing names, and resolutions of videos. However, when trying to upload a video, consistently receiving 40 ...

Creating a serial number in a Class without relying on a global variable is a useful technique that

I am looking for a way to assign a unique ID to each instance of a Class without relying on global variables. I have tried using a global variable and incrementing it, but I would prefer a more efficient approach. Is there a way to generate an ID within t ...

Angular 2 - The constructor of a class cannot be called without using 'new' keyword

Currently, I am working on integrating the angular2-odata library into my project. This is the code snippet I have: @Injectable() class MyODataConfig extends ODataConfiguration { baseUrl = "http://localhost:54872/odata/"; } bootst ...

Creating Angular Custom Form Validation and Custom Directives

I recently created a custom validation directive and applied it to the form element like this: <form myValidations> app.directive('myValidations', function(){ return{ //require: 'ngModel', note its commented out link: f ...

If the value of the input matches, set the checkbox to be

I have successfully implemented functionality that allows the value of an input to be changed by clicking a checkbox. This works without any issues. Now, I am facing the challenge of automatically checking the checkbox when the page loads, but only if the ...

Is it necessary to use `top` or `parent` when utilizing local scripts in an iFrame?

Is it possible to eliminate the use of top or parent in iFrame localized scripts, as the title suggests? Upon examining the screenshot below, I encounter a "not defined" error unless I include top or parent as a prefix to my function call. test(); does n ...

Navigating through Laravel's API

My software is quite small and I utilize both laravel and vue.js. I am curious about the variance between routing via api.php and web.php within the routes folder. Could someone please enlighten me on the distinctions between these two scenarios? ...

javascript implement a process to iteratively submit a form using ajax

I have a dynamic form with an unknown number of input fields that are not fixed. While searching for solutions, I came across jQuery ajax form submission which requires manually constructing the query string. In this scenario, the number of input fields ...

Browse through different states by clicking on the <a> </a> tag

Is there a way to switch between states defined by $stateProvider when clicking on the <a> </a> tag? Below are the states I have set up: $stateProvider //region page States .state('page1', { url: "/pg1", ...

As the user types, automatically format the input field for a seamless and intuitive experience

My current application is running on Angular 1.3.10 I have implemented a jQuery function to automatically add a backslash to the expiration input field once the user types the third number. Although it was a quick fix, I now aim to move this functionality ...

Encountering an issue with the history module when utilizing the webpack dev server

I am encountering an issue while trying to run webpack dev server. The history functionality was working fine until I started using the webpack module. A warning message appeared in my console: WARNING in ./src/history.js 2:15-35 export 'createBrows ...

Experiencing difficulties integrating relational data with Angular and MongoDB

I have a view where I display 'Transporters'. Each Transporter has multiple 'Deliveries', so I want to associate Deliveries with the corresponding Transporters. My tech stack includes express, mongoose, and angular.js. Here are my mode ...