This is my first tutorial in the long tutorial series on “Getting started with Firebase & Ionic“. I have integrated crosswalk and Ionic Materiel, to bring a significant improvement in performance and UI (Will discuss in detail in the upcoming tutorials) . Please make sure to read the complete series and follow me on git for the latest updates.
[wpi_designer_button text=’Download’ link=’https://github.com/arjunsk/ionic-firebase-shopping-cart’ style_id=’48’ icon=’github’ target=’_blank’]
So lets get started.
Firebase:
- Firebase is a real-time database service, i.e your modification are updated in real time and you don’t need to refresh a page, to see the changes.
- Firebase uses NoSQL. So leave aside some of the old school SQL concepts.
- Firebase is not suitable for all occasions. Here I have used it basically for the reason that, I need a Real time Cart and a Real time Order Tracking.
Index:
[color-box] index.html [The container] [/color-box]
This is the main container that holds Sliding Drawer and Navigation Bar. We need to hide some of this segments before login. You can find the respective sections in the below code.
#1. The custom headers for Ionic Material and Firebase
#2. To obtain your Firebase configuration part follow this.
#3. $root.extras is used for hiding user features, ie cart icon, menu drawer, navigation icon etc.
We initialize $root.extras to false in the app.js
.run(function($ionicPlatform,$rootScope) { $rootScope.extras = false; $ionicPlatform.ready(function() {
#4.get_total() returns the total number of cart items.
#5.In-order to access $root.extras and get_total(), we have added an additional controller i.e indexCtrl. Currently we wont be looking into it, as it will only come after login.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> <title></title> <!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above <link href="css/ionic.app.css" rel="stylesheet"> --> http://lib/ionic/js/ionic.bundle.js <!-- cordova script (this will be a 404 during development) --> http://cordova.js <link href="lib/ionic/css/ionic.css" rel="stylesheet"> <!--=========================================#1. Custom Header Part====================================--> <!-- Ionic Meterial Header--> http://lib/ionic-material/dist/ionic.material.min.js http://lib/ionicuirouter/ionicUIRouter.js <link href="lib/ionic-material/dist/ionic.material.min.css" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=RobotoDraft%3A400%2C500%2C700%2C400italic" rel="stylesheet"> <link href="css/style.css" rel="stylesheet"> <!--Firebase Header--> https://cdn.firebase.com/js/client/2.2.4/firebase.js https://cdn.firebase.com/libs/angularfire/1.2.0/angularfire.min.js https://www.gstatic.com/firebasejs/live/3.0/firebase.js <script> //#2. Initialize Firebase // Refer to #2 in the article // You have to replace this section with your custome config var config = { apiKey: "apiKey", authDomain: "projectId.firebaseapp.com", databaseURL: "https://databaseName.firebaseio.com", storageBucket: "bucket.appspot.com", }; firebase.initializeApp(config); </script> <!--======================================================================================================--> <style type="text/css"> .platform-ios .manual-ios-statusbar-padding{ padding-top:20px; } .manual-remove-top-padding{ padding-top:0px; } .manual-remove-top-padding .scroll{ padding-top:0px !important; } ion-list.manual-list-fullwidth div.list, .list.card.manual-card-fullwidth { margin-left:-10px; margin-right:-10px; } ion-list.manual-list-fullwidth div.list > .item, .list.card.manual-card-fullwidth > .item { border-radius:0px; border-left:0px; border-right: 0px; } </style> http://js/app.js http://js/controllers.js http://js/routes.js http://js/services.js http://js/directives.js </head> <body ng-app="app" animation="slide-left-right-ios7"> <div style=""> <!--#5. indexCtrl --> <ion-side-menus ng-controller="indexCtrl" data-componentid="side-menu21" style="" enable-menu-with-back-views="false"> <ion-side-menu-content > <ion-nav-bar class="bar-assertive" > <ion-nav-back-button></ion-nav-back-button> <ion-nav-buttons side="left"> <!-- #3. $root.extras --> <button ng-if="$root.extras" class="button button-icon button-clear ion-navicon" menu-toggle="left"> </button> </ion-nav-buttons> <ion-nav-buttons side="right"> <!-- #3. $root.extras --> <!-- #4. get_total() --> <button ui-sref="myCart" ng-if="$root.extras" class="button button-icon button-clear ion-ios-cart-outline"> {{get_total()}} </button> </ion-nav-buttons> </ion-nav-bar> <ion-nav-view></ion-nav-view> </ion-side-menu-content> <!-- #3. $root.extras --> <ion-side-menu side="left" id="side-menu21" ng-if="$root.extras"> <ion-header-bar class="expanded"> <img ng-src="{{'img/fk/'+ user_info.photoURL +'.jpg'}}" class="avatar motion spin fade"> <div class="menu-bottom"> {{user_info.displayName}} </div> </ion-header-bar> <ion-content class="stable-bg has-expanded-header"> <ion-list data-componentid="list1" class=" " id="menu-list1"> <ion-item data-componentid="list-item1" style="" menu-close="" ui-sref="menu2" id="menu-list-item1" class="item-icon-left "> <i class="icon ion-ios-home-outline"></i>Menu</ion-item> <ion-item data-componentid="list-item2" style="" menu-close="" ui-sref="offers" id="menu-list-item2" class="item-icon-left "> <i class="icon ion-ios-pricetag-outline"></i>Offers</ion-item> <ion-item data-componentid="list-item8" style="" menu-close="" ui-sref="myCart" id="menu-list-item8" class="item-icon-left "> <i class="icon ion-ios-cart-outline"></i>My Cart</ion-item> <ion-item data-componentid="list-item3" style="" menu-close="" ui-sref="lastOrders" id="menu-list-item3" class="item-icon-left "> <i class="icon ion-ios-clock-outline"></i>Orders</ion-item> <ion-item data-componentid="list-item4" style="" menu-close="" ui-sref="favourite" id="menu-list-item4" class="item-icon-left "> <i class="icon ion-ios-star-outline"></i>Favourite</ion-item> <ion-item data-componentid="list-item5" style="" menu-close="" ui-sref="settings" id="menu-list-item5" class="item-icon-left "> <i class="icon ion-ios-gear-outline"></i>Settings</ion-item> <ion-item data-componentid="list-item6" style="" menu-close="" ui-sref="support" id="menu-list-item6" class="item-icon-left "> <i class="icon ion-ios-help-outline"></i>Support</ion-item> <ion-item ng-click="logout()" data-componentid="list-item7" style="" id="menu-list-item7" class="item-icon-left "> <i class="icon ion-log-out"></i>Logout</ion-item> </ion-list> </ion-content> </ion-side-menu> </ion-side-menus> </div> </body> </html>
Login:
[color-box] login.html [The login page] [/color-box]
Find following sections in the below code
#1. style attribute for adding full screen background
#2. Will be implementing FB login in a while.
<ion-view style="" class=" " id="page5" title="Login"> <!-- #1. style --> <ion-content class="has-header" padding="true" style="background: url(img/bg1.jpg) center; background-size: cover;"> <form name="loginForm" class="list " id="login-form1"> <ion-list class=" " id="login-list2"> <div class="app-icon"></div> <label class="item item-input item-floating-label"> <span class="input-label" style="color: #9F9F9F;">Email</span> <input ng-model="user.email" style="color: white;" type="email" placeholder="Email"> </label> <label class="item item-input item-floating-label"> <span class="input-label" style="color: #9F9F9F;" >Password</span> <input ng-model="user.password" style="color: white;" type="password" placeholder="Password"> </label> </ion-list> <div style="height: 40px;" class="spacer"></div> <button ng-click="loginEmail(loginForm,user)" class=" button button-assertive button-block icon-left ion-ios-email-outline " id="signup-button3">LOGIN WITH EMAIL</button> <!-- #2. FB login--> <button ng-click="loginFb('facebook')" class=" button button-positive button-block icon-left ion-social-facebook " id="signup-button4">LOGIN WITH FACEBOOK</button> </form> <a class=" button button-stable button-block button-clear icon-left ion-ios-email-outline " id="login-button5" ui-sref="tabsController.forgotPassword">FORGOT PASSWORD</a> </ion-content> </ion-view>
[color-box] controllers.js [ loginCtrl ] [/color-box]
/* ionicSideMenuDelegate : used to access the slidable functionality of the menu drawer */ .controller('loginCtrl', function($scope,$rootScope,$ionicHistory,sharedUtils,$state,$ionicSideMenuDelegate) { $rootScope.extras = false; // For hiding the side bar and nav icon // When the user logs out and reaches login page, // we clear all the history and cache to prevent back link $scope.$on('$ionicView.enter', function(ev) { if(ev.targetScope !== $scope){ $ionicHistory.clearHistory(); $ionicHistory.clearCache(); } }); //Check if user already logged in firebase.auth().onAuthStateChanged(function(user) { if (user) { //Removes back link to login page $ionicHistory.nextViewOptions({ historyRoot: true }); $ionicSideMenuDelegate.canDragContent(true); // Sets up the sideMenu dragable $rootScope.extras = true; sharedUtils.hideLoading(); $state.go('menu2', {}, {location: "replace"}); } }); $scope.loginEmail = function(formName,cred) { if(formName.$valid) { // Check if the form data is valid or not sharedUtils.showLoading(); //starts the loading popup //Email Login via Firebase firebase.auth().signInWithEmailAndPassword(cred.email,cred.password).then(function(result) { // You dont need to save the users session in your local session or cookies. Firebase handles it. // You only need to : // 1. clear the login page history from the history stack so that you cant come back // 2. Set rootScope.extra; // 3. Turn off the loading // 4. Got to menu page $ionicHistory.nextViewOptions({ historyRoot: true //1 }); $rootScope.extras = true; //2 sharedUtils.hideLoading(); //3 $state.go('menu2', {}, {location: "replace"}); //4 }, function(error) { sharedUtils.hideLoading(); sharedUtils.showAlert("Please note","Authentication Error"); } ); }else{ sharedUtils.showAlert("Please note","Entered data is not valid"); } }; $scope.loginFb = function(){ //Facebook Login }; $scope.loginGmail = function(){ //Gmail Login }; })
[color-box] services.js [ sharedUtils and fireBaseData ] [/color-box]
sharedUtils : Contains commonly used functions like show_loading_popup, show_alert etc.
fireBaseDate : Contains the Reference URL of all the tables in your firebase database.
.factory('fireBaseData', function($firebase) { var ref = new Firebase("https://projectId.firebaseio.com/"), refCart = new Firebase("https://projectId.firebaseio.com/cart"), refUser = new Firebase("https://projectId.firebaseio.com/users"), refCategory = new Firebase("https://projectId.firebaseio.com/category"), refOrder = new Firebase("https://projectId.firebaseio.com/orders"), refFeatured = new Firebase("https://projectId.firebaseio.com/featured"), refMenu = new Firebase("https://projectId.firebaseio.com/menu"); return { ref: function() { return ref; }, refCart: function() { return refCart; }, refUser: function() { return refUser; }, refCategory: function() { return refCategory; }, refOrder: function() { return refOrder; }, refFeatured: function() { return refFeatured; }, refMenu: function() { return refMenu; } } }) .factory('sharedUtils',['$ionicLoading','$ionicPopup', function($ionicLoading,$ionicPopup){ var functionObj={}; functionObj.showLoading=function(){ $ionicLoading.show({ content: '<i class=" ion-loading-c"></i> ', // The text to display in the loading indicator animation: 'fade-in', // The animation to use showBackdrop: true, // Will a dark overlay or backdrop cover the entire view maxWidth: 200, // The maximum width of the loading indicator. Text will be wrapped if longer than maxWidth showDelay: 0 // The delay in showing the indicator }); }; functionObj.hideLoading=function(){ $ionicLoading.hide(); }; functionObj.showAlert = function(title,message) { var alertPopup = $ionicPopup.alert({ title: title, template: message }); }; return functionObj; }])
Register :
[color-box] signup.html [The Signup page] [/color-box]
<ion-view style="" class=" " id="page6" title="Signup"> <ion-content class="has-header" padding="true" style="background: url(img/bg1.jpg) center; background-size: cover;"> <form name="signupForm" class="list " id="signup-form2"> <ion-list class=" " id="signup-list3"> <div class="app-icon"></div> <label class="item item-input item-floating-label"> <span style="color: #9F9F9F;" class="input-label">Name</span> <input style="color: #ffffff;" ng-model="user.name" type="text" placeholder="Name"> </label> <label class="item item-input item-floating-label"> <span style="color: #9F9F9F;" class="input-label">Phone</span> <input style="color: #ffffff;" ng-model="user.phone" type="tel" placeholder="Phone"> </label> <label class="item item-input item-floating-label"> <span style="color: #9F9F9F;" class="input-label">Email</span> <input style="color: #ffffff;" ng-model="user.email" type="email" placeholder="Email"> </label> <label class="item item-input item-floating-label"> <span style="color: #9F9F9F;" class="input-label">Password</span> <input style="color: #ffffff;" ng-model="user.password" type="password" placeholder="Password"> </label> </ion-list> <div style="width: 279px; height: 35px;" class="spacer"></div> <button ng-click="signupEmail(signupForm,user)" class=" button button-assertive button-block icon-left ion-ios-email-outline " style="border-radius:0px 0px 0px 0px;" id="signup-button3">SIGN UP WITH YOUR EMAIL</button> <button class=" button button-positive button-block icon-left ion-social-facebook " style="border-radius:0px 0px 0px 0px;" id="signup-button4">SIGN UP WITH FACEBOOK</button> </form> </ion-content> </ion-view>
[color-box] controllers.js [The Signup page] [/color-box]
.controller('signupCtrl', function($scope,$rootScope,sharedUtils,$ionicSideMenuDelegate, $state,fireBaseData,$ionicHistory) { $rootScope.extras = false; // For hiding the side bar and nav icon $scope.signupEmail = function (formName, cred) { if (formName.$valid) { // Check if the form data is valid or not sharedUtils.showLoading(); //Main Firebase Authentication part firebase.auth().createUserWithEmailAndPassword(cred.email, cred.password).then(function (result) { //Add name and default dp to the Autherisation table result.updateProfile({ displayName: cred.name, photoURL: "default_dp" }).then(function() {}, function(error) {}); //We create a user table to store users additional information.Here, telephone //Add phone number to the user table fireBaseData.refUser().child(result.uid).set({ telephone: cred.phone }); //Registered OK $ionicHistory.nextViewOptions({ historyRoot: true }); $ionicSideMenuDelegate.canDragContent(true); // Sets up the sideMenu dragable $rootScope.extras = true; sharedUtils.hideLoading(); $state.go('menu2', {}, {location: "replace"}); }, function (error) { sharedUtils.hideLoading(); sharedUtils.showAlert("Please note","Sign up Error"); }); }else{ sharedUtils.showAlert("Please note","Entered data is not valid"); } } })
Profile :
[color-box] settings.html [The Profile Page] [/color-box]
<ion-view style="" class=" " id="page12" title="Settings"> <ion-content class="has-header" padding="false" > <form name="settingForm" class="list " id="settings-form"> <ion-list class=" " > <!-- Profile Cover Page --> <div class="profile-nav col-md-3"> <div class="panel"> <div class="user-heading round"> <a href="#"> <img ng-src="{{'img/fk/'+ user_info.photoURL +'.jpg'}}" > </a> <p style="color: #ffffff;">{{user_info.displayName}}</p> </div> </div> </div> <label class="item item-input ic-selected"> <a class="icon icon-right ion-android-call" style="margin-right: 10px;"></a> <input style="color: #000;" ng-model="user_extras.telephone" type="text" placeholder="Telephone" > </label> <label class="item item-input ic-selected"> <a class="icon icon-right ion-email" style="margin-right: 10px;"></a> <input style="color: #000;" ng-model="data_editable.email" type="email" placeholder="Email"> </label> <label class="item item-input ic-selected"> <a class="icon icon-right ion-locked" style="margin-right: 10px;"></a> <input style="color: #000;" ng-model="data_editable.password" type="password" placeholder="Update Password"> </label> <!--Address Header--> <label ng-click="addManipulation()" class="item item-input item ic-selected" > <a class="icon icon-right ion-ios-location" style="margin-right: 10px;" ></a> Address <i class="icon icon-right ion-android-add-circle" style="font-size: larger ;margin-left: 10px;"></i> </label> <div ng-repeat="item in addresses" > <div class="list card" > <div style="min-height: 30px;" class="item item-divider"> <a class="icon icon-right ion-ios-location"></a> {{item.nickname}} <div style="float: right;"> <a ng-click="addManipulation(item)" class="icon icon-right ion-edit" style="font-size: 20px;"></a> <a ng-click="deleteAddress(item.$id)" class="icon icon-right ion-android-delete" style="font-size: 20px;"></a> </div> </div> <div class="item item-body" > <span> {{item.address}} </span> <span>Pin: {{item.pin}}</span> <span>Tel: {{item.phone}}</span> </div> </div> </div> </ion-list> </form> </ion-content> <!-- Floating action bar on the bottom of the app --> <div id="footer" class="button-bar" > <a style="min-width: 50%;border-radius: 0px;" ng-click="cancel()" class="button button-lite icon-left ion-close">Cancel</a> <a style="min-width: 50%;border-radius: 0px;" ng-click="save(user_extras,data_editable)" class="button button-assertive icon-left ion-checkmark">Save</a> </div> </ion-view>
[color-box] controllers.js [ settingsCtrl ] [/color-box]
/* firebaseArray: for accessing synchronized array of objects firebaseObject: for accessing single synchronized object */ .controller('settingsCtrl', function($scope,$rootScope,fireBaseData,$firebaseObject, $ionicPopup,$state,$window,$firebaseArray, sharedUtils) { //Bugs are most prevailing here $rootScope.extras=true; //Shows loading bar sharedUtils.showLoading(); //Check if user already logged in firebase.auth().onAuthStateChanged(function(user) { if (user) { //Accessing an array of objects using firebaseObject, does not give you the $id , so use firebase array to get $id $scope.addresses= $firebaseArray(fireBaseData.refUser().child(user.uid).child("address")); // firebaseObject is good for accessing single objects for eg:- telephone. Don't use it for array of objects $scope.user_extras= $firebaseObject(fireBaseData.refUser().child(user.uid)); $scope.user_info=user; //Saves data to user_info //NOTE: $scope.user_info is not writable ie you can't use it inside ng-model of <input> //You have to create a local variable for storing emails $scope.data_editable={}; $scope.data_editable.email=$scope.user_info.email; // For editing store it in local variable $scope.data_editable.password=""; $scope.$apply(); sharedUtils.hideLoading(); } }); //Function 1 $scope.addManipulation = function(edit_val) { // Takes care of address add and edit ie Address Manipulator if(edit_val!=null) { $scope.data = edit_val; // For editing address var title="Edit Address"; var sub_title="Edit your address"; } else { $scope.data = {}; // For adding new address var title="Add Address"; var sub_title="Add your new address"; } // An elaborate, custom popup var addressPopup = $ionicPopup.show({ template: '<input type="text" placeholder="Nick Name" ng-model="data.nickname"> <br/> ' + '<input type="text" placeholder="Address" ng-model="data.address"> <br/> ' + '<input type="number" placeholder="Pincode" ng-model="data.pin"> <br/> ' + '<input type="number" placeholder="Phone" ng-model="data.phone">', title: title, subTitle: sub_title, scope: $scope, buttons: [ { text: 'Close' }, { text: '<b>Save</b>', type: 'button-positive', onTap: function(e) { if (!$scope.data.nickname || !$scope.data.address || !$scope.data.pin || !$scope.data.phone ) { e.preventDefault(); //don't allow the user to submit unless he enters full details } else { return $scope.data; } } } ] }); addressPopup.then(function(res) { if(edit_val!=null) { //Update address fireBaseData.refUser().child($scope.user_info.uid).child("address").child(edit_val.$id).update({ // update nickname: res.nickname, address: res.address, pin: res.pin, phone: res.phone }); }else{ //Add new address fireBaseData.refUser().child($scope.user_info.uid).child("address").push({ // push nickname: res.nickname, address: res.address, pin: res.pin, phone: res.phone }); } }); }; // A confirm dialog for deleting address $scope.deleteAddress = function(del_id) { var confirmPopup = $ionicPopup.confirm({ title: 'Delete Address', template: 'Are you sure you want to delete this address', buttons: [ { text: 'No' , type: 'button-stable' }, { text: 'Yes', type: 'button-assertive' , onTap: function(){return del_id;} } ] }); confirmPopup.then(function(res) { if(res) { fireBaseData.refUser().child($scope.user_info.uid).child("address").child(res).remove(); } }); }; //Function 2 $scope.save= function (extras,editable) { //1. Edit Telephone doesnt show popup 2. Using extras and editable // Bugs if(extras.telephone!="" && extras.telephone!=null ){ //Update Telephone fireBaseData.refUser().child($scope.user_info.uid).update({ // set telephone: extras.telephone }); } //Edit Password if(editable.password!="" && editable.password!=null ){ //Update Password in UserAuthentication Table firebase.auth().currentUser.updatePassword(editable.password).then(function(ok) {}, function(error) {}); sharedUtils.showAlert("Account","Password Updated"); } //Edit Email if(editable.email!="" && editable.email!=null && editable.email!=$scope.user_info.email){ //Update Email/Username in UserAuthentication Table firebase.auth().currentUser.updateEmail(editable.email).then(function(ok) { $window.location.reload(true); //sharedUtils.showAlert("Account","Email Updated"); }, function(error) { sharedUtils.showAlert("ERROR",error); }); } }; $scope.cancel=function(){ // Simple Reload $window.location.reload(true); console.log("CANCEL"); } })
UPDATE (14-07-2016) :-
Its almost done. Now you only need to configure some database elements.
CONFIGURE DATABASE:
1. Open up your project db.
2. Import the following JSON data to the Foodkart db.
https://github.com/arjunsk/ionic-firebase-shopping-cart/blob/master/www/DB/import.json
Note: Rest of the databases are automatically created, when making the database calls.
3. Add the following permissions to the database rules .
{ "rules": { ".read": true, ".write": true } }
Note: When you are publishing the app, make sure to update these permissions to a more constrained version.
Update (15-07-2016) :-
4. One last thing to go. Enable the Email/Password Sign in from the authentication.
This concludes the part for Login, Register and Profile Setting for FoodKart using Firebase.
If you happen to like this tutorial, then please spend some time to rate the Github Repo and follow me on Git.
If you have any issues, please do ping me on linked in.
VIDEO TUTORIAL :
For those who are still finding it difficult to setup, here is the video tutorial for the same.
Awesome Work !
created my projected id on firebase, confused on how to create tables on it
LikeLike
I will be updating the database part, very soon.
LikeLike
okay but to test your app without db it doesn’t work
LikeLike
Can you confirm,if the issue is resolved ?
LikeLike
Can you check if the issue, is resolved now?
LikeLike
ApaYour article was very nice but when executed appear “Authentication Error” where it died, I’ve done the steps as written in your article, if you can help me?
LikeLike
Your article was very nice but when executed appear “Authentication Error” where it died, I’ve done the steps as written in your article, if you can help me?
LikeLike
Ok… let me just check. I will create a demo video then.
LikeLike
LikeLike
oke thank you , sign in with facebook script not installed? I’ll wait for the next tutorial friend
LikeLike
Thank you. I will be updating it soon. I am currently busy with my placement procedures. To get the latest updates, please follow me on git.
LikeLike
okay I’ve been following you on github
LikeLike
sir its very awesome project but i want know how i can display all user in menu page those who are registered
LikeLike
Are you creating the admin app for the same? Just loop through the users table in firebase. Feel free to google.
LikeLike
Can You Make Tutorial On Admin App
LikeLike
How to sign in with facebook or google?
Thanks.
LikeLike
i didn’t implement it…
May be this will help…
http://ngcordova.com/docs/plugins/facebook/
LikeLike
Sir, how to sign in with facebook or google?
Thanks.
LikeLike
Did you got any solution?
LikeLike
Hi nice app, the rules: is public
{
“rules”: {
“.read”: true,
“.write”: true
}
}
i like: private…
How can I set the rules so that only authenticated users can access?
If I put this:
{
“Rules”: {
“.read”: “auth! = Null”,
“.write”: “auth! = Null”
}
}
The application does not show me the data and the console gives me a permission error …
how can I solve that? thank you very much!
LikeLike
Can I work with firebase without internet connection?
LikeLike
http://stackoverflow.com/questions/14670394/does-firebase-allow-an-app-to-start-in-offline-mode
LikeLike
Hi Arjunsk sir……
this app is awesome….but i would like to use this app without login/signup step…how do i place “skip this step” on login/signup…..after adding to cart i would like to have login/signup credentials……can u please guide me how to avoid login/signup in launch of app?
LikeLike
Hye,
Nice tutorial …but after running app items are not loading would u help me where i’m getting wrong?
LikeLike
Hi can anyone help me with making a role based login authentication. example say you have two user account roles like admin and guest. now once you logged in as admin the UI should look differently and when you logged in as guest it should be look differently as well.
Admin??
LikeLike
Hello can anyone help me how did he configure things in his video tutorial. When i tried to follow the tutorial the site can’t be reached
LikeLike
how to give the apps shipping feature? and how to make more data in the address table? thanks
LikeLike
Absolutely brilliant.Thank you
LikeLike
Hello, Where is the Indian rupee symbol in the code…Can’t seem to find it anywhere
LikeLike