Page views not updating as required after login

Hi all,

I decided to rewrite my existing jQuery Mobile app using Ionic. I love it and feel excited about it.

But I am facing an issue and have wasted nearly 4 days in finding a solution. If I could not find a solution, I might need to drop using Ionic which I don’t want.

I will try to explain my problem so that experts can look on it.

I am using Parse to handle users and it works great. The problem i am facing is that, my code is not recognizing even if the user has successfully registered. I have 2 DIV elements and I show any on of them if the user is a guest or registered user.

But I am not able to make changes to view after login so that users don’t see the login page again. Similarly if users logout, they should see the “sign-in” page. But these are not happening. I might be missing something simple.

When I refresh the page manually in browser, I can see the actual expected page sections.

I have provided my entire project in the below GitHub code. Please have a look and let me know how silly I am in programming.

https://github.com/Purus/IonicTest/

Test Login for app: a@a.com
Password: a

Hey Mate,

You’re code was a little hard to understand but i can see the core of your issue.

With controllers, they’re singletons. The code that sets the current user from parse only runs when the controller is first created not every time the view is navigate. Because of this the value is never updated. It works when you refresh because this causes the controller to be recreated.

You have multiple options. Your first is events. instead of doing what you’re doing you can put the user code in the beforeEnter event. http://ionicframework.com/docs/api/directive/ionView/

A second option is to create and AngularJS factor to share data across your controllers for Authentication and user data. This is what i currently do. https://thinkster.io/egghead/sharing-data-between-controllers/
This makes like easier because you set $scope.auth to be your factory and then you can switch/hide on auth.IsAuthenticated (a property you add)

1 Like

Dear DaleFrancis88,

Thanks for your time on viewing my horrible code :smile: I know its hard. This is my first Ionic or Angular code. May be I can do better next time.

I tried to have it done via Services. But it was not working for me.

Could you please point me in right direction on using beforeEnter event for my scenario?

If you want me to use factory/service, how this parse user handling can be done? Any template code also would be helpful for me to learn.

Thanks a ton.

Hey,

This is my factory for authentication

.factory('Authentication', ['$http', '$localstorage', function ($http, $localstorage) {
    var localUserData = $localstorage.getObject('userData') || {
        email : '',
        picture : '',
        firstName : '',
        lastName : '',
        password : '',
        isNew : true,
        created : new Date()
    };
    
    var authenticated = false;

    return {
        authenticate : function () { 
            // Authentication code and logic here
           authenticated = true;
        },
        isAuthenticated : authenticated, 
        userData : localUserData,
        updateUser : function () {
            
            // update user data on server here
            
            localUserData.isNew = false;
            $localstorage.setObject('userData', localUserData);
        },
        activePersist : function ($scope) {
            var props = ['email', 'picture', 'firstName', 'lastName', 'password'];
            
            for (i = 0; i < props.length; i++) {
                $scope.$watch('data.' + props[i], function () {
                    localUserData.isNew = false;
                    $localstorage.setObject('userData', localUserData);
                });
            }
        }
    };
}])

heres my factory for local storage too

.factory('$localstorage', ['$window', function ($window) {
    return {
        set: function (key, value) {
            $window.localStorage[key] = value;
        },
        get: function (key, defaultValue) {
            return $window.localStorage[key] || defaultValue;
        },
        setObject: function (key, value) {
            $window.localStorage[key] = JSON.stringify(value);
        },
        getObject: function (key) {
            var local = $window.localStorage[key];
            
            if (local == undefined) {
                return undefined;
            }
            
            return JSON.parse(local);
        }
    }
}])

This is how you execute an event

$scope.$on('$ionicView.beforeEnter', function () {
    // Do cool stuff here
});
1 Like

The following coded saved me.

$scope.$on('$ionicView.beforeEnter', function() {
    $scope.currentUser = Parse.User.current() !== null;
});

Oh no!.. You saved me and not this code. :smile:

With the above logic it works inside conent.

<ion-content></ion-content>

But the same scope variable does not work inside the nav bars.The variable currentUser is not getting refreshed in ion-nav-buttons aslthough it does in ion-content.

<ion-nav-buttons side="right">
    <button class="button" ng-click="logoutUser()" ng-show="currentUser !== null">
        Logout
    </button>
</ion-nav-buttons>

Hey,

That means that your nav bar is in a different scope to your view/content. The scope for it is probally the controller thats attached to your first state. Mine looks like this;

  .state('app', {
        url: "/app",
        abstract: true,
        templateUrl: "templates/layout.html",
        controller: 'AppCtrl'
    })

This is where you may need to have the shared data concept. If you have it attached to your $scope by injecting it into each controller as needed and doing something like $scope.auth = Authentication

You could then have currentUser on Authentication and it becomes ng-show=“auth.currentUser !== null”

When its shared and its updated from another controller, all the other views and controllers get notified.

I am trying to understand here. Below is my code. Both sections are in the same view/controller.

Why does it work fine in ion-content and why not in ion-nav-buttons?

   <ion-nav-buttons side="right">
        <button class="button" ng-show="currentUser !== null">
            Logout
        </button>
    </ion-nav-buttons>

    <ion-content>
        <div ng-switch on="currentUser">

            <div id="forGuestUsers" ng-switch-when="false"></div>

            <div id="forLoginUsers" ng-switch-when="true"></div>
        </div>
    </ion-content>

If they are in two different views/controller, it makes sense to use shared data. Please correct me if my understanding is wrong.

Can you check in your latest fix to github.

I’ll check it out

Hey,

But while we wait, i’ll type some stuff out, ion-nav-buttons gets lifted and put inside your ion-nav-bar. If you look at your index.html …

<ion-nav-bar class="bar-stable" align-title="center">

    <ion-nav-back-button>
    </ion-nav-back-button>

</ion-nav-bar>

<ion-nav-view></ion-nav-view>

…they are seperate elements. When you switch states, angular/ionic gets a controller and view, connects them and places it inside ion-nav-view. Your application doesn’t actually have an app controller

.state('index', {
    url: "/index",
    abstract: true,
    templateUrl: "templates/index.html"
})

Add one to the above state, and do the events and other stuff your doinve in the view controller and expect the nav bar to have that controller.

I have pushed the latest code to GIT.

https://github.com/Purus/IonicTest/

As per you latest comment, I tried adding the existing controller for the abstract state.

The ion-nav-back-button never shows for me. But that’s a different issue which can be ignored for now.

Thanks a ton for your time on this.

OMG… its by bad… The below code works fine. I was checking for null instead of true/false. Please consider this as resolved.

<ion-nav-buttons side="right">
    <button class="button" ng-click="logoutUser()" ng-show="currentUser">
        Logout
    </button>
</ion-nav-buttons>

Can you please look on the back-button which is not showing up?

Hey,

I havn’t done navigation the way you are, i’ve always done it in the controller with $state.go

Sorry mate

Anyhow thanks a lot again for your help. Without you I could not have solved the main issue myself.

Thanks,
Purus