0

I am using HTML 5 geolocation inside an Angular component:

...
    export class AngularComponent {
    ...
        constructor(private db: DatabaseService) {}

        // this function is assigned to an HTML button
        logCoords(message, action) {
        navigator.geolocation.getCurrentPosition(this.success, this.error, this.options);
        }

        success(pos) {
            function time() {
            ...
            }
            var crd = pos.coords;
            var lat = crd.latitude
            var long = crd.longitude

            let newCoordinates = {'lat': lat, 'long':long, 'time': time}
            this.db.addLocation(newCoordinates)
        }
    ...
    }
...

I want to store the result of the getCurrentPosition Method inside indexed db using an Angular service but I am unable to access any properties of the component class (this.db is null).

Why I am unable to access this.db inside the success function and how I might be able to work around this?

Lester
  • 357
  • 3
  • 16
  • Can you share some code on stackblitz? – navnath Sep 12 '21 at 05:40
  • add code of module, I thing you forget to inject the service in module. – xdeepakv Sep 12 '21 at 05:47
  • The module is injected and works in other parts of the template; Inside success, console.log shows that this.db is null. I figured it had something to do with my lack of understanding of javascript since the success function is being used elsewhere in the geolocation library... – Lester Sep 12 '21 at 05:51
  • 2
    Replace `success(pos) {` with `success = (pos) => {` – yurzui Sep 12 '21 at 07:37
  • makes sense. wish I had a technical description of why that didn't work. may god bless you. – Lester Sep 12 '21 at 08:04
  • The reason is `scope`. There are a couple posts about that topic, e.g. https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback – Gunnar B. Sep 12 '21 at 09:07

2 Answers2

1

Because you lose the context this when passing the method as a callback. You can fix this by multiple ways:

logCoords(message, action) {
    // bind context
    navigator.geolocation.getCurrentPosition(this.success.bind(this), this.error.bind(this), this.options);
}

or

logCoords(message, action) {
    navigator.geolocation.getCurrentPosition(this.success, this.error, this.options);

    success = (pos) => {} // <= arrow function
    error = () => {}      // <= arrow function
}
Tiep Phan
  • 12,386
  • 3
  • 38
  • 41
1

Issue is with the below line:

navigator.geolocation.getCurrentPosition(this.success, this.error, this.options);

In above line, you are just passing this.success as callback without setting context to it. So in this case as per javascript principles, this would always refer to window object while you are expecting component reference.
To fix this, you have to set the context (component instance) before passing this.success and for that purpose javascript provided bind() function.

Try below code (very simple fix) -

navigator.geolocation.getCurrentPosition(this.success.bind(this), this.error.bind(this), this.options);

For more details around bind() function refer below link -

https://developer.mozilla.org/enUS/docs/Web/JavaScript/Reference/Global_objects/Function/bind

Suneet Bansal
  • 2,664
  • 1
  • 14
  • 18