Reputation: 2921
I posted this question earlier and I honestly don't know what im doing wrong. I have being trying to solve this all day.
I'm going to post as much code as possible to give you guys as much details as possible.
The problem I'm having is that im trying to load a 3 child views after i login. after logged in i can see all 3 child views render in my html tool inspector but there partially render in the browser view. Upon research I think my problem is that I need to use a property called resolve to wait for all my templates and http to be finish before I transition to the next page after the login.
this is the login page
<ion-view view-title="login">
<ion-content class="padding has-header">
<div class="row">
<div class="col col-50 col-offset-25">
<div class="card">
<div class="item item-text-wrap">
<form ng-submit="processForm()">
<div class="list">
<label class="item item-input">
<input type="text" placeholder="First Name" ng-model="formData.AccessKey" required="true">
</label>
<label class="item item-input">
<input type="text" placeholder="Last Name" ng-model="formData.Password" required="true">
</label>
</div>
<button class="button button-full button-positive">
Sign me in
</button>
</form>
</div>
</div>
</div>
</div>
</ion-content>
this is my app js responsible for all the routing
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
});
})
.config(function($stateProvider, $urlRouterProvider, $ionicConfigProvider){
$ionicConfigProvider.views.transition('none')
$urlRouterProvider.otherwise('/');
$stateProvider
.state('login',{
url: '/',
templateUrl: 'templates/login.html',
controller:'loginController'
})
.state('main', {
url: '/main',
templateUrl: 'templates/main.html',
abstract: true
})
.state('main.panels', {
views: {
'ticketsPanel': {
templateUrl: 'templates/ticketsPanel.html'
},
'productsPanel': {
templateUrl: 'templates/productsPanel.html'
},
'categoriesPanel': {
templateUrl: 'templates/categoriesPanel.html',
controller: 'categoriesController'
}
}
})
})
this is my services
angular.module('starter.services', [])
.factory('Authentication', function($http, $q){
var deferred = $q.defer();
return {
login: function(formData) {
$http({
method : 'GET',
url : 'http://localhost:8888/employees/login',
params : formData
})
.success(function(respond){
deferred.resolve(respond);
})
},
getEmployee: function () {
return deferred.promise;
}
}
})
.factory('Categories', function($http){
//get the company id so i can get all the categories belong to that company
var CompanyId = JSON.parse(localStorage.getItem('employee'));
CompanyId = CompanyId[0].CompanyId;
return {
getCategories : function() {
$http({
method : 'GET',
url : 'http://localhost:8888/Categories/ajax_getCompaniesCategories',
params : {CompanyId: CompanyId}
})
.success(function(respond){
localStorage.setItem('categories', JSON.stringify(respond));
})
}
}
})
this is my controller
angular.module('starter.controllers', [])
.controller('loginController', function($scope, Authentication, $log, $state){
$scope.formData = {};
$scope.processForm = function(){
Authentication.login($scope.formData);
var promise = Authentication.getEmployee();
promise.then(function(respond){
localStorage.setItem('employee', JSON.stringify(respond));
$state.go('main.panels');
})
}
})
.controller('categoriesController', function($scope, Categories){
console.log('categories controller')
Categories.getCategories();
$scope.categories = JSON.parse(localStorage.getItem('categories'));
})
Sorry I usually try to only post a little bit of code but I'm desperate. Thanks in advance.
Upvotes: 0
Views: 108
Reputation: 6173
It's not quite clear about your templates displayed in half... Why are you sure you have correct markup for them?
However your code is not supposed to work. You have completely messed up processing promises. You'd better read more about it.
I will post only the code that should be changed:
Don't wrap existing promises into deferreds. Don't hesitate to return the promise. Remember that promises are supposed to work in chain. I.e. promise.then().then()
is also a promise and you can attach .then
to it after it was returned from a function.
.factory('Authentication', function ($http) {
return {
login: function (formData) {
return $http({
method: 'GET',
url: 'http://localhost:8888/employees/login',
params: formData
});
}
//also you don't need any extra functions to return the http response
//getEmployee was redundant
}
})
Same stuff applies to Categories
service.
Also service in this case shouldn't be aware of app business logic - where to take the companyId
. It should receive this info as a parameter. Not a showstopper but a good practice.
.factory('Categories', function ($http) {
return {
getCategories: function (companyId) {
//return the promise $http().success()
return $http({
method: 'GET',
url: 'http://localhost:8888/Categories/ajax_getCompaniesCategories',
params: {
CompanyId: CompanyId
}
})
.success(function (respond) {
localStorage.setItem('categories', JSON.stringify(respond));
//this will be parameter of next `.then` handler
return respond;
})
}
}
})
Now in controller we use it the following way
$scope.processForm = function(){
Authentication.login($scope. formData)
.then(function(respond){
localStorage.setItem('employee', JSON.stringify(respond));
$state.go('main.panels');
})
}
And in categoriesController
you tried to use localStorage.getItem('categories')
before the async operation finished. Thus it was always empty. You should wait until it's done and that's why promises are in place. In .then
handler operation is complete, however due to proper return from getCategories
last .then
handler we don't need to get item from localStorage and parse it. We get the object as an argument of handler!
.controller('categoriesController', function ($scope, Categories) {
//good practice: controller is a proper place to retrieve id for request
var company = JSON.parse(localStorage.getItem('employee'));
var companyId = CompanyId[0].CompanyId;
Categories.getCategories(companyId)
.then(function (categories) {
//at this moment localStorage.getItem('categories') is already populated
//it can be used for later. At the moment we get categories as an argument
$scope.categories = categories;
})
})
Hope this helps
Upvotes: 1
Reputation: 1991
In the specific route you are calling, you can add:
.state('route', {
templateUrl: 'url/to/template.html',
resolve: {
myCategories: function(Categories) {
return Categories.getCategories();
}
}
})
And in your controller, you can pass in myCategories
like this:
.controller('categoriesController', function($scope, myCategories){
$scope.categories = JSON.parse(myCategories);
})
Change your factory to return the response value instead of using localStorage:
.factory('Categories', function($http){
//get the company id so i can get all the categories belong to that company
var CompanyId = JSON.parse(localStorage.getItem('employee'));
CompanyId = CompanyId[0].CompanyId;
return {
getCategories : function() {
$http({
method : 'GET',
url : 'http://localhost:8888/Categories/ajax_getCompaniesCategories',
params : {CompanyId: CompanyId}
})
.success(function(respond){
return respond;
})
}
}
})
The route will wait for the resolve to return before proceeding. If the resolve fails, so will the route.
Let me know if this helps or if you need more detail.
Upvotes: 0