I'm migrating an application to angular, but I got a bit confused with that of the routes, especially with the sub-routes, which I have the following problems and doubts:
Structure of my application
I did the step from index to loading, also that of the menus and views, but the error of always loading the teachers' menu first occurs, I suppose it could be due to the order of the template folders.
My doubts would be:
- When to use templates or nested templates
- If the structure of the folders or folders affects the template you load
Structure
module
angular.module('unicesarApp', ['ionic'])
.controller('formulario', formulario)
.service('obtenerDatos', obtenerDatos)
.config(config);
Settings
config.$inject = ['$stateProvider', '$urlRouterProvider'];
function config($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/login");
$stateProvider
.state('login', {
url: '/login',
templateUrl: "Templates/login.html",
controller: "formulario"
})
.state('Loading',{
url: '/loading',
templateUrl: "Templates/loading.html"
})
.state('menuestu',{
url: '/menuestu',
templateUrl: "Templates/Estudiante/menuestu.html"
})
.state('perfilestu',{
url: '/perfilestu',
templateUrl: "Templates/Estudiante/perfilestu.html"
})
.state('horarioestu',{
url: '/horarioestu',
templateUrl: "Templates/Estudiante/horarioestu.html"
})
.state('calificaciones',{
url: '/calificaciones',
templateUrl: "Templates/Estudiante/calificaciones.html"
})
.state('menuprof',{
url: '/menuprof',
templateUrl: "Templates/Docente/menuprof.html"
});
};
Controller
formulario.$inject = ['$scope', 'obtenerDatos', '$state'];
function formulario($scope, obtenerDatos, $state){
$scope.login = function(){
var datos, datosRespuesta;
datos = {
Usuario: $scope.usuariotxt,
Password: $scope.passwordtxt
};
if(datos.Usuario == undefined && datos.Password == undefined){
$scope.respuesta = "Los campos estan vacios";
}else{
obtenerDatos.Autenticacion(datos).then(function (response){
if(response.data){
datosRespuesta = response.data;
if(datosRespuesta === "Usuario no registrado"){
$scope.respuesta = datosRespuesta;
}else if(datosRespuesta === "Contraseña incorrecta"){
$scope.respuesta = datosRespuesta;
}else if(datosRespuesta.estudiante){
obtenerDatos.getDatos(datosRespuesta);
$state.go('Loading');
setTimeout(alerta, 3000);
function alerta(){
$state.go('menuestu');
};
}else{
obtenerDatos.getDatos(datosRespuesta);
$state.go('Loading');
setTimeout(alerta, 3000);
function alerta(){
$state.go('menuprof');
};
};
}else{
console.log(response.status);
$scope.respuesta = response.status;
};
});
};
};
};
Services
obtenerDatos.$inject = ['$http', '$httpParamSerializer'];
function obtenerDatos($http, $httpParamSerializer){
var datosIngreso;
function Autenticacion(datos){
var url = 'http://190.109.185.138/Apipedro/api/login';
return $http.post(url, $httpParamSerializer(datos), {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
};
function getDatos(info){
datosIngreso = info;
};
function setDatos(){
return datosIngreso;
};
return {
Autenticacion: Autenticacion,
getDatos: getDatos,
setDatos: setDatos
};
};
The first thing I'm going to tell you is that
setTimeout
it doesn't work well with angular, unless you call$scope.apply
in its callback; Well, by itself, it doesn't fire the digest cycle and Angular "doesn't know" that the event has occurred.So the function
alerta
should be like this:$apply
forces Angular's internal loop to run.Now, Angular has its own timer service, and it would be the most logical:
$timeout
, which already internally calls the$apply
.You must not forget to inject
$timeout
into your controller.When the nested states have a common template with each other. That is, within the template of the parent state, there is one
ng-view
which will change according to the sub state. Since A, B, C, and D are sub-views, it seems confusing, but they are not sub-states. That would be if you have a single inner box that can only have one at a time: A or B or C or D, but not all together.Unless all these states have "a common part" (in the view or the view-model), there you could refactor it to expose what is common in the parent state and the views with their particular details.
Not at all. It only indicates where the browser should go to find each piece.
In relation to
obtenerDatos
I am going to say that you have used the namesgetDatos
andsetDatos
in a confusing way, because the names should be the other way around. set to set and get to get. Also, I'm not sure why you keep them there, since it's not used anywhere else, I would delete it.Other suggestions
On the other hand, there is no need to do that, I mean: set a timer. Much better would be to switch to 'Loading' before doing the ajax request... it's more organic.
getDatos
If you are interested in this change, you could completely remove the y methodsetDatos
(which you tell me is useless) and directly set the corresponding state. In cases of text errors, you return to the login state, so that the error shows up in the login view, where it should.Finally you add the
catch
to your promise. And you close a state machine that uses the benefits of angular and ui-router. That is to say that before any exit, it will end in one or another state or in error but never in loading.Something like that...
Note: I assume that it
datosRespuesta.estudiante
arrives and is true in at least one case.