Tips for asynchronously updating a model in TypeScript

I have been working on a function to hide the element for connecting to Facebook upon successful connection. I have implemented two functions, success and error, which trigger after Firebase successfully logs in the user. While I can confirm that these functions are working correctly through debugging and console.log statements, the element does not hide when the Facebook connection is successful. Upon inspecting the properties of this, I noticed that isFacebookConnected and isGoogleConnected do not appear, but the User and Providers properties do.

I am wondering if there might be something I am misunderstanding about passing the current model reference to a function in order to modify the UI state. How can I ensure that the UI element hides on successful connection?

FacebookAuthenticator.ts

import { firebase } from '../../app';
import { IAuthenticator } from './IAuthenticator';
import { Navigator } from '../navigation/Navigator';

export class FacebookAuthenticator implements IAuthenticator  {
    public successFunction: Function;
    public errorFunction: Function;

    constructor(success: Function, error: Function) {
        this.successFunction = success;
        this.errorFunction = error;
    }

    public authenticate() {
        const successFunction = this.successFunction;
        const errorFunction = this.errorFunction;

        firebase.login({
            type: firebase.LoginType.FACEBOOK
        }).then(
            function (result) {
                successFunction(result);
            },
            function (errorMessage) {
                errorFunction(errorMessage);
            }
        );
    }
}

AccountViewModel.ts

export class AccountViewModel extends Observable {
    public appVersion : string;
    public User : User;
    public isFacebookConnected : boolean;
    public isGoogleConnected : boolean;
    private authenticator : IAuthenticator;
    private providers : Array<Provider>;

    constructor() {
        super();

        appVersion.getVersionName().then((result) => {
            this.notifyPropertyChange("appVersion", "Version " + result);
        });

        firebase.getCurrentUser().then((result) => {
            this.User = result;
            this.notifyPropertyChange("User", this.User);
            this.providers = ProviderParser.getUserProviders(this.User);
            this.setProviderConnectivty();
        });
    }

    public setFacebookSwitch(togglingOn : boolean) {
        const successFunction : Function = (model : AccountViewModel) => {
            return () => {
                model.isFacebookConnected = true;
                model.notifyPropertyChange("isFacebookConnected", model.isFacebookConnected);
            }
        };

        const errorFunction : Function = (model : AccountViewModel) => {
            return () => {
                model.isFacebookConnected = false;
                model.notifyPropertyChange("isFacebookConnected", model.isFacebookConnected);
                dialogs.alert({
                    title: "Unexpected Error",
                    message: "An unexpected error occurred during login. Please contact the developer.",
                    okButtonText: "Ok"
                });
            }
        };

        this.authenticator = new FacebookAuthenticator(successFunction(this), errorFunction(this));

        if (togglingOn && this.providers.indexOf(Provider.Facebook) === -1) {
            this.authenticator.authenticate();
        }
    }
}

Account.xml

<StackLayout row="2" column="0" class="preferenceGroup">
            <Label text="Connected Accounts" class="preferenceGroupHeading"/>
            <GridLayout rows="*" columns="*, auto" visibility="{{ isFacebookConnected ? 'collapsed' : 'visible' }}">
                <Label row="0" column="0" text="Facebook" class="preferenceItem"/>
                <Label row="0" column="0" 
                        text="Repeat accesses your public profile, friend list, and email address" 
                        textWrap="true"
                        horizontalAlignment="left"
                        class="preferenceSubText"/>
                <Switch loaded="facebookSwitchLoaded" />
            </GridLayout>
            <Label class="divider" />
            <GridLayout rows="*" columns="*, auto">
                <Label row="0" column="0" text="Google" class="preferenceItem"/>
                <Label row="0" column="0" 
                        text="Repeat accesses your public profile, friend list, and email address" 
                        textWrap="true"
                        horizontalAlignment="left"
                        class="preferenceSubText"/>
                <Switch checked="{{isGoogleConnected}}"/>
            </GridLayout>
        </StackLayout>

Answer №1

Seems like the variable model is not pointing to the correct model you are currently working with. The appropriate object should be referenced as this within the closure.

Try making changes to your code in the following manner to see if it resolves the issue:

public setFacebookSwitch(togglingOn : boolean) {
        const successFunction : Function = (model : AccountViewModel) => {
            return () => {
                this.isFacebookConnected = true;

If the above modification does not solve the problem (especially if the Function is overriding the context of this), attempt saving a reference to this in a temporary variable first:

public setFacebookSwitch(togglingOn : boolean) {
        const myTempThis = this;
        const successFunction : Function = (model : AccountViewModel) => {
            return () => {
                myTempThis.isFacebookConnected = true;

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

The contents of the div do not display when the button is pressed except in jsfiddle

I have written a script that triggers the appearance of a div where users can adjust the time settings for a timer. The functionality works perfectly on JSFiddle, with the div displaying as intended. However, when tested on other online IDEs such as Coding ...

Flask causing AJAX Request to encounter a CORS Policy issue

Currently, I am utilizing Flask to construct a basic backoffice system. In an attempt to execute some requests on the client-side using AJAX, I keep encountering a persistent error: Access to XMLHttpRequest at '...' from origin 'http://lo ...

Encountering an issue with Meteor and node-celery: "Unable to access property 'slice' of null"

Check out the Github repository for reproducing this issue Run localhost:3000 to replicate the problem. In my setup with Meteor 1.4.4.1, I am utilizing the node-celery npm packages on the server side. Upon Meteor initialization, the client automatically i ...

Exploring ES6 Property Assignment

After researching, I've discovered that ES6 does not support setting properties of a class and returning that class. class MyClass { constructor() { this.x = 0; this.y = 0; } update(value) { // logic this.y ...

Uh-oh! A circular dependency has been detected in the Dependency Injection for UserService. Let's untangle this web and fix the issue!

Encountering the following error: "ERROR Error: Uncaught (in promise): Error: NG0200: Circular dependency in DI detected for UserService." The auth.component.ts utilizes the UserService and User classes, while the user.service.ts only uses the User class. ...

What is the best way to choose all checkboxes identified by a two-dimensional array?

I need help with a question div setup that looks like this: <div class="Q"> <div id="Q1"><span>1. </span>Which of the following have the same meaning?</div> <div class="A"><input type="checkbox" id="Q1A1Correct" /& ...

Saving compiled babel files to the corresponding directory level

Is there a way to output compiled babel files in the same directory as the source files? Currently, my script generates the compiled files in a separate folder while maintaining the folder structure. This is achieved through the following code snippet in m ...

Utilize information from a JSON Array to populate a JavaScript Array

Is there a way to link the data from the $data variable in ajax.php to the this.products[] array in store.js? Both files are separate, so how can I achieve this? The webpage displays the database data returned by ajax.php as shown below: [{"0":"100001"," ...

Is your jQuery .on function failing to properly detect click events?

Seems like I'm missing something here. Why is the .on function not functioning as expected in this code snippet? <html> <head> </head> <body> <button type="button" class="close" data-test="test">TEST BUTTON< ...

What is the best way to display just one record that has the lowest score out of all the records?

I need help with displaying only 1 record from the DL list that has the lowest score, instead of showing all records. In the example on stackblitz, you can see that for the first record, the DL scores are: 54, 20, and updated. Instead of displaying all 3 ...

The specified column `EventChart.åå` is not found within the existing database

I've been developing a dashboard application using Prisma, Next.js, and supabase. Recently, I encountered an issue when making a GET request. Prisma throws an error mentioning a column EventChart.åå, with a strange alphabet "åå" that I haven&apos ...

NextJS Typescript Player

Encountering an issue during the build process, specifically with the error in audioRef.current.play(). The error message indicates that there is no play function available. I attempted to use an interface but it seems to not accept boolean values. Could ...

Unable to alter the state through the URL bar using ui-router

I am facing an issue where I get redirected to the home state whenever I try to directly access a URL like mysite.com/#!/about. My menu with ui-sref links is functioning correctly, but when it comes to nested states, I encounter problems switching betwee ...

Type guard does not narrow down the union type

Explore the following code snippet: type UnionType = 'foo' | 'bar' | 'baz' const obj = { foo: 'huh', bar: 'hmm' } function func(input: UnionType) { if(input in obj) { input } } In ...

The <iframe> generated by Create-React-App often hinders my ability to interact with or modify the application directly, requiring me to remove it using the browser's element editor

After conducting a global installation of create-react-app, I encountered an issue where instead of editing the rendered content directly in the browser while working on a project, there is a mysterious container created around my app. Upon closer examina ...

Team members

Just started diving into Angular and practicing coding with it while following video tutorials. However, I've stumbled upon something in my code that has left me puzzled. I'm curious about the significance of the line "employees: Employee[]" in ...

Implementing a click function that toggles between adding and removing a class, keeping track of the number of clicks, and utilizing localStorage to prevent repeated clicking in the

Hi there! I'm currently working on a simple widget that features a clickable icon and a counter next to it. When the icon is clicked, it should toggle between an empty heart and a filled heart using addClass/removeClass. Additionally, each click incr ...

Align Bootstrap navigation bar items at the center horizontally

I am currently working on a navigation bar that features two icons, evenly distributed. To achieve this look, I have been experimenting with scaling the icons horizontally in order to make them center-aligned within the navigation bar. However, I have not ...

How well are DOM Mutation Observers supported across different web browsers?

I attempted to search for a solution by Googling, but was unsuccessful in finding an answer. Does anyone know if there is a compatibility matrix available for this feature that works across all browsers? In case someone is interested in the answer, here ...

Looking to verify characters, numbers, and special characters with jQuery's regular expression feature?

Currently, I am facing a challenge in validating the password field to allow characters, numbers, and special characters. It is essential that the password consists of exactly 8 characters. Despite searching online for a solution, I have been unsuccessful ...