-->

OnsenUi Angular and Login

2019-04-11 14:41发布

问题:

I'm trying to develop a mobile app with onsen+cordova

What i need is:

When the app start it load login.html page. If the app detect that the user is logged then it redirect to the home.html

For each "protected page" i want to call a function that detected if user is logged. If not i want to redirect to login page.

All the "protected pages" have a slide menu.

Following what i've done:

index.html

<html ng-app="app2gest">
    <head>
        <meta charset="utf-8">
        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="mobile-web-app-capable" content="yes">
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height"/>

        <title>App2Gest</title>

        <link rel="stylesheet" type="text/css" href="vendors/onsen/css/onsenui.css"/>

        <link rel="stylesheet" type="text/css" href="vendors/onsen/css/onsen-css-components.css"/>

        <!-- Download also your onsen-css-components.css stylesheet using the integrated CSS Components Theme Roller
        http://components.onsenui.io -->

        <link rel="stylesheet" type="text/css" href="vendors/onsen/css/onsen-css-components-blue-theme.css"/>
        <!--<link rel="stylesheet" type="text/css" href="vendors/onsen/css/onsen-css-components-default.css"/>-->
        <!--<link rel="stylesheet" type="text/css" href="vendors/onsen/css/onsen-css-components-blue-basic-theme.css"/> -->
        <!--<link rel="stylesheet" type="text/css" href="vendors/onsen/css/onsen-css-components-dark-theme.css"/> -->
        <!--<link rel="stylesheet" type="text/css" href="vendors/onsen/css/onsen-css-components-sunshine-theme.css"/> -->
        <!--<link rel="stylesheet" type="text/css" href="vendors/onsen/css/onsen-css-components-purple-theme.css"/> -->

        <link rel="stylesheet" type="text/css" href="css/angular-carousel.css"/>

        <!-- NVD3 re-usable charting library (based on D3) -->
        <link rel="stylesheet" type="text/css" href="css/nvd3/nv.d3.min.css">

        <link rel="stylesheet" type="text/css" href="css/style.css"/>

    </head>
    <body>

        <ons-sliding-menu menu-page="menu.html" main-page="login.html" side="left" max-slide-distance="85%" swipable="true" swipe-target-width="100" var="menu">
        </ons-sliding-menu>

        <!-- Javascripts -->
        <script type="text/javascript" src="vendors/onsen/js/angular/angular.js"></script>    
        <script type="text/javascript" src="js/angular-touch.js"></script>

        <script type="text/javascript" src="vendors/onsen/js/onsenui.js"></script>        

        <script type="text/javascript" src="js/lodash.underscore.min.js"></script>
        <script type="text/javascript" src="js/bluebird.js"></script>        

        <script type="text/javascript" src="js/event.js"></script>        
        <script type="text/javascript" src="js/angular-local-storage.js"></script>
        <script type="text/javascript" src="js/angular-sanitize.js"></script>        


        <script type="text/javascript" src="js/app.js"></script>
        <script type="text/javascript" src="js/data.js"></script>
        <script type="text/javascript" src="js/app-local-storage.js"></script>

        <script src="js/jquery-1.11.1.min.js"></script>    

        <script type="text/javascript" src="cordova.js"></script>

        <script type="text/javascript">
            app.initialize();
        </script>                        


    </body>
</html>

home.html

 <ons-page ng-controller="HomeController" ng-init="LoginUtility.checkLogin()">

        <ons-toolbar fixed-style>
            <div class="left">
                <ons-toolbar-button onclick="ons.slidingMenu.toggleMenu()">
                    <ons-icon icon="bars">
                </ons-toolbar-button>
            </div>

            <div class="center">App2Gest</div>

            <div class="right">
                <ons-toolbar-button onclick="appNavigator.pushPage('settings.html', {title: 'Settings', animation: 'slide'})">
                    <ons-icon icon="gears">
                </ons-toolbar-button>
            </div>
        </ons-toolbar>

        <ons-scroller>
            <section class="home-grid">
                <div class="grid-menu">
                    <div class="centering-and-alignment" ng-repeat="row in items| partition:2">
                        <div class="grid-menu-item list__item list__item--tappable" ng-repeat="item in row" ng-click="showDetail(($parent.$index * row.length) + $index);">
                            <ons-icon icon="{{item.icon}}"></ons-icon>
                            <div class="grid-menu-item-label">{{item.title}}</div>
                        </div>                                                
                    </div>
                </div>               
            </section>

        </ons-scroller>

        <div>

        </div>

    </ons-page>

login.html

<ons-navigator title="Navigator" var="appNavigator">
    <ons-page sliding-menu-ignore="true" ng-controller="LoginController" ng-init="LoginUtility.checkLogin()">

        <ons-toolbar>
            <div class="left">           
            </div>
            <div class="center">App2Gest - Login</div>
        </ons-toolbar>

        <div class="main-image-wrapper">
            <i class="fa fa-sign-in main-image"></i>
        </div>
        <form ng-submit="LoginUtility.login()">
            <input type="email" class="text-input--underbar" placeholder="Username" value="" ng-model="username">
            <input type="password" class="text-input--underbar" placeholder="Password" value="" ng-model="password">
            <br>
            <button class="button login-button">Log in</button>
            <br>
        </form>    

    </ons-page>


</ons-navigator>

app.js

var app = {
    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);

    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicity call 'app.receivedEvent(...);'
    onDeviceReady: function() {
        app.receivedEvent('deviceready');

        ons.setDefaultDeviceBackButtonListener(function() {
            if (navigator.notification.confirm("Vuoi chiudere l\'app?",
                    function(index) {
                        if (index == 1) { // OK button
                            navigator.app.exitApp(); // Close the app
                        }
                    }
            ))
                ;
        });

        // Open any external link with InAppBrowser Plugin
        $(document).on('click', 'a[href^=http], a[href^=https]', function(e) {

            e.preventDefault();
            var $this = $(this);
            var target = $this.data('inAppBrowser') || '_blank';

            window.open($this.attr('href'), target);

        });

        // Initialize Push Notifications
        // Uncomment the following initialization when you have made the appropriate configuration for iOS - http://goo.gl/YKQL8k and for Android - http://goo.gl/SPGWDJ
        //app.initPushwoosh();

    },
    // Update DOM on a Received Event
    receivedEvent: function(id) {
        //var parentElement = document.getElementById(id);
        //var listeningElement = parentElement.querySelector('.listening');
        //var receivedElement = parentElement.querySelector('.received');

        //listeningElement.setAttribute('style', 'display:none;');
        //receivedElement.setAttribute('style', 'display:block;');

        console.log('Received Event: ' + id);
    },
    // Register device for Push Notifications
    initPushwoosh: function() {
        var pushNotification = window.plugins.pushNotification;

        if (device.platform == "Android") {
            registerPushwooshAndroid();
        }
        if (device.platform == "iPhone" || device.platform == "iOS") {
            registerPushwooshIOS();
        }
    }

};

(function() {
    var app = angular.module('app2gest', ['onsen.directives', 'ngTouch', 'ngSanitize', 'appLocalStorage', 'LocalStorageModule', 'ui.event']);


    app.controller("LoginController", function($scope, LoginUtility) {                  

           $scope.LoginUtility = LoginUtility;
           $scope.LoginUtility.setScope($scope);                                                                               
    });

    // Home Controller
    app.controller('HomeController', function($scope, Data, LoginUtility) {

        $scope.items = Data.items;

        $scope.LoginUtility = LoginUtility;
        $scope.LoginUtility.setScope($scope);

        $scope.showDetail = function(index) {
            var selectedItem = $scope.items[index];
            Data.selectedItem = selectedItem;
            if (selectedItem.type === 'internal') {
                $scope.ons.navigator.pushPage(selectedItem.url, {title: selectedItem.title, animation: 'slide'});
            }
            else {
                window.open(selectedItem.url);
            }
        };


    });



    app.controller('CaricoHomeController', function($scope) {

    });

    // Menu Controller
    app.controller('MenuController', function($scope, MenuData) {

        $scope.items = MenuData.items;

        $scope.showDetail = function(index) {
            var selectedItem = $scope.items[index];
            MenuData.selectedItem = selectedItem;

            $scope.ons.slidingMenu.setMainPage(selectedItem.page, {closeMenu: true});

        };

    });




    // Barcodescanner Controller
    app.controller('BarcodescannerController', function($scope) {

        $scope.scan = function() {
            cordova.plugins.barcodeScanner.scan(function(result) {
                $scope.result = result;
                $scope.$apply();
            }, function(error) {
                $scope.error = error;
                $scope.$apply();
            });
        }

    });

    //dummy implementation 
    app.factory('LoginUtility', function() {

        var username;
        var password;
        var scopeVar;

        var loginObj = {};

        loginObj.setScope = function(elem) {
            scopeVar = elem;
        };

        loginObj.isGuest = function() {
            return username == null;
        };

        loginObj.login = function() {
            console.log('login called');
            username = scopeVar.username;
            password = scopeVar.password;
            //dummy login, we assume login always succeded
            scopeVar.ons.slidingMenu.setMainPage("home.html", {closeMenu: true});
        };

        loginObj.logout = function() {
            username = null;
        };

        loginObj.checkLogin = function() {               
            if (this.isGuest() && **imNotInLoginPage()**) {                  
                scopeVar.ons.slidingMenu.setMainPage("login.html", {closeMenu: true});
            }            
        };

        return loginObj;
    });



    // Filter
    app.filter('partition', function($cacheFactory) {
        var arrayCache = $cacheFactory('partition');
        var filter = function(arr, size) {
            if (!arr) {
                return;
            }
            var newArr = [];
            for (var i = 0; i < arr.length; i += size) {
                newArr.push(arr.slice(i, i + size));
            }
            var cachedParts;
            var arrString = JSON.stringify(arr);
            cachedParts = arrayCache.get(arrString + size);
            if (JSON.stringify(cachedParts) === JSON.stringify(newArr)) {
                return cachedParts;
            }
            arrayCache.put(arrString + size, newArr);
            return newArr;
        };
        return filter;
    });


})();

For the dummy function imNotInLoginPage() at the start of the app if use appNavigator.getCurrentPage() it works but appNavigator.getCurrentPage().page is empty

After Login instead if i call appNavigator.getCurrentPage() it is undefined and i receive a js undefined error.

How can i check if i'm in loginpage or in another?

And the very big question, is this a good praticse in angular?

Otherwise how can i achieve this goal with angular+onsen???

The support from the onsen's theme is very poor. I've found other solutions involving angular route, but there are not compatible with onsen.

I'm going crazy for implementing this standard thing. I hope that someone can help me, providing a complete example code.

Thank you

回答1:

I created sample. If I misunderstand what you mean, please tell me.

index.html

 <!DOCTYPE HTML>
<html ng-app="myApp">
<head>
    <script src="components/loader.js"></script>
    <link rel="stylesheet" href="components/loader.css">
    <link rel="stylesheet" href="css/style.css">
    <script src="js/app.js"></script>    
</head>
<body>
    <ons-navigator var="myNavigator" page="login.html">
    </ons-navigator> 
</body>
</html>

app.js

var myApp = angular.module("myApp", ['onsen']);

myApp.controller('loginCtrl', function($scope) {

    if(checkLogin()) {
        openProtectedPage();
    }

    function openProtectedPage() {
        alert("you are already logged in. open protected page");
        setTimeout(function() {
            myNavigator.pushPage('protected.html');    
        }, 1000);

    }

    function checkLogin() {
        //temporariry return true;
        // please write your own logic to detect user login;
        return true;
    }    
});

login.html

<ons-page ng-controller="loginCtrl">
    <ons-toolbar>
        <div class="center">Login Page</div>
    </ons-toolbar>

    <div style="text-align: center; margin-top: 30px;">
        Email: <input type="text" />
    </div>

    <div style="text-align: center; margin-top: 30px;">
        Password: <input type="text" />
    </div>  

    <div style="text-align: center;margin-top: 30px;">
        <ons-button>
            Sign In 
        </ons-button>
    </div>
</ons-page>

protected.html

<ons-page>
    <ons-sliding-menu var="app.slidingMenu" menu-page="menu.html" main-page="page1.html" side="left" type="overlay" max-slide-distance="200px">
    </ons-sliding-menu>
</ons-page>

I hope this example would help you.