skip to Main Content

I am having a problem in calling/accessing a in-class function AND a service function from a function which calls a external js lib/code… But I am able to access class variable using the ‘this’ keyword in angular 2 component

FB <- is the facebook sdk function to get the facebook communicated values of the logged user

Here’s the code

statusChangeCallback(resp: any) {
        if (resp.status === 'connected') {
            this.access_token = resp.authResponse.accessToken; // this variable gets the correct value in it

            FB.api('/me?fields=name,email', function (resp: any) {
                this.email = resp.email; // this variable gets the correct value in it

                if (this.email !== '' && this.access_token !== '') {
                    console.log('under if statement');
                    var auth = {};
                    auth['accesstoken'] = this.access_token;
                    auth['emailid'] = this.email;

                    console.log(auth);

                    this.send_registeration(auth); // this function throws ERROR
                    // this.http.fb_register(this.email, this.access_token);
                }
            }, { scope: 'email,public_profile' });
        } else if (resp.status === 'not_authorized') {

        } else {

        }
    }

Here’s Error Description shown in chrome

zone.js:260 Uncaught TypeError: this.send_registeration is not a function

here’s the full component code to checkout

import {Component, OnInit, Output} from '@angular/core';
import {ROUTER_DIRECTIVES, Router} from '@angular/router-deprecated';
import { HttpService } from '../../Service/http.service';

declare const FB: any;

@Component({
    selector: 'facebook-login',
    template: `
    <div>
        <button class="btn btn-facebook" (click)="onFacebookLoginClick()">
            <i class="fa fa-facebook"></i>Sign in with Facebook
        </button>
    </div>
    `,
    providers: [HttpService],
    directives: [ROUTER_DIRECTIVES]
})

export class FacebookLoginComponent implements OnInit {

    access_token: string = '';
    email: string = '';


    constructor(private http: HttpService) {
        FB.init({
            appId: '****APP ID **********',
            cookie: false,  // enable cookies to allow the server to access
            // the session
            xfbml: true,  // parse social plugins on this page
            version: 'v2.5' // use graph api version 2.5
        });
    }

    onFacebookLoginClick() {
        FB.login(this.statusChangeCallback);
    }

    statusChangeCallback(resp: any) {
        if (resp.status === 'connected') {
            this.access_token = resp.authResponse.accessToken;
            // var self = this;
            FB.api('/me?fields=name,email', (resp: any) => {
                this.email = resp.email;

                if (this.email !== '' && this.access_token !== '') {

                    var auth = {};
                    auth['accesstoken'] = this.access_token;
                    auth['emailid'] = this.email;

                    console.log(auth);

                    this.send_registeration(auth); //throws Error
                    // this.http.fb_register(this.email, this.access_token); // this Service function also throws Error just the same way
                }
            }, { scope: 'email,public_profile' });

        } else if (resp.status === 'not_authorized') {

        } else {

        }
    }

    send_registeration(auth: any) {
        this.http.postRequest(auth, 'fbinvestors')
            .subscribe(
            data => {
                console.log('Server respond is ');
                console.log(data);
            }
            );
    }
}

Here’s the updated function … Facebook sdk callback doesnt seems to be earlier as stated earlier … but the problem still exits

statusChangeCallback(resp: any) {

        if (resp.status === 'connected') {
            this.access_token = resp.authResponse.accessToken;

        FB.api('/me?fields=name,email,first_name,last_name,age_range,gender,picture', (resp: any) => {
                this.email = resp.email;
        }, { scope: 'email,public_profile' });


        } 

        var self = this;
        setTimeout(function () {
            if (this.email !== '' && this.access_token !== '') {
                console.log('under if statement');
                var auth = {};
                auth['accesstoken'] = this.access_token;
                auth['emailid'] = this.email;

                console.log(auth); // show variable output as required
// no problem till here

            }
            self.http.postRequest(auth, 'fbinvestors') // this line throws error as shown below
                .subscribe(
                data => {
                    console.log('Server respond is ');
                    console.log(data);
                }
                );

        }, 7000);
    }

the new Error is similiar to the old one … but now its not calling the service method – Error shown is

TypeError: Cannot read property 'postRequest' of undefined

UPDATE: on line self.http.postRequest(auth, ‘fbinvestors’) … self is undefined basically … so now I solve this problem if
1. I can pass class scope (‘this’) as a parameter to this callback function
2. If I can provide a array of callback functions instead of just one callback function

Please help – I am trying this to get solved from 2 days now….

3

Answers


  1. Chosen as BEST ANSWER

    I changed the original function

    onFacebookLoginClick() {
            FB.login(this.statusChangeCallback);
        }
    
    statusChangeCallback(resp: any) {
    
            if (resp.status === 'connected') {
                this.access_token = resp.authResponse.accessToken;
    
            FB.api('/me?fields=name,email,first_name,last_name,age_range,gender,picture', (resp: any) => {
                    this.email = resp.email;
            }, { scope: 'email,public_profile' });
    
    
            } 
    
            var self = this;
            setTimeout(function () {
                if (this.email !== '' && this.access_token !== '') {
                    console.log('under if statement');
                    var auth = {};
                    auth['accesstoken'] = this.access_token;
                    auth['emailid'] = this.email;
    
                    console.log(auth); // show variable output as required
    // no problem till here
    
                }
                self.http.postRequest(auth, 'fbinvestors') // this line throws error as shown below
                    .subscribe(
                    data => {
                        console.log('Server respond is ');
                        console.log(data);
                    }
                    );
    
            }, 7000);
        }
    

    to this

        onFacebookLoginClick() {
                var self = this;
                FB.login(this.statusChangeCallback);
                var callback = setTimeout(function () {
                    if (this.email !== '' && this.access_token) {
                        console.log('send the http request from here');
                        var auth = {};
                        auth['emailid'] = this.email;
                        auth['accesstoken'] = this.access_token;
                        self.httpTest.postRequest(auth, 'fbinvestors')
                            .subscribe(
                            data => {
                                console.log('Server respond is ');
                                console.log(data);
                            }
                            );
                    } else {
                        this.callback(); // gave a recursion untill post is not done.
                    }
    
                }, 2000);
            }
    statusChangeCallback(resp: any) {
    
            if (resp.status === 'connected') {
                this.access_token = resp.authResponse.accessToken;
    
                // var self = this; // as shown on online to solve the 'this' keyword problem
                console.log(this.httpTest + ' is the service I want to access');
                FB.api('/me?fields=name,email,first_name,last_name,age_range,gender,picture',
                    (resp: any, httpService: any = this.httpTest) => {
                        this.email = resp.email;
                    });
            } else if (resp.status === 'not_authorized') {
    
            } else {
    
            }
        }
    

    Waiting for the response from fb via recursion callback is obviously not a good idea ... but for now it has solved by problem until I do not find the right solution


  2.  function (resp: any) {
    

    should be

    (resp: any) =>
    

    otherwise this. won’t point to your current component instance.
    See also https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Functions/Arrow_functions

    Login or Signup to reply.
  3. Take a look at this excellent Stackoverflow thread. It explains the issue you’re having and the solution to it.
    The this in your callback function is referring to the wrong context, because it is eventually being called from somewhere inside the facebook API code, not your class. Thus, you cannot access your other class functions with this this.

    Thankfully, the solution to this is pretty simple:

    ...
    var self = this;
    FB.api('/me?fields=name,email', function (resp: any) {
        ...
        self.send_registeration(auth);
    

    By putting this in a temorary variable, and using that inside of the callback, you will be referring to the right context.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search