configure routes and sub-routes using ui-router

8

I am migrating an application to angular, but I got a bit involved with the routes, especially with the sub-routes, which I have the following problems and doubts:

Structure of my application

The passage of the index to the loading is done, also the menu and views, but the error always occurs to always load the teachers' menu first, I suppose it could be by the order of the folders of the templates.

My doubts would be:

  • When templates or nested templates should be used
  • If the structure of the folders or folders affects the template that loads
  • Structure

    Module

    angular.module('unicesarApp', ['ionic'])
               .controller('formulario', formulario)
               .service('obtenerDatos', obtenerDatos)
               .config(config);
    

    Config

    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
            };
    
        };
    
        
    asked by Pedro Miguel Pimienta Morales 11.03.2016 в 00:44
    source

    1 answer

    3
      

    but the error occurs of always loading the teachers' menu first, I suppose it could be by the order of the folders of the templates.

    The first thing I'm going to tell you is that setTimeout does not work well with angular, unless you call $scope.apply in your callback; because, on its own, it does not trigger the digest cycle and angular " he does not know "that the event has happened.

    So the function alerta , should be like this:

    function alerta() {
      $scope.$apply(function(){ 
         $state.go('menuestu'); // para el otro estado (menuprof) hacer lo mismo
      });
    };
    

    $apply force Angular's internal cycle to run.

    Now, angular has its own timers service, and it would be logical: $timeout , which already invokes the $apply method internally.

    $timeout(function() {
        $state.go('menuestu'); // para el otro estado (menuprof) hacer lo mismo
    }, 3000);
    

    You should not forget to inject $timeout into your controller.

      

    Q: When should templates or nested templates be used?

    When the nested states have a common template between them. That is, within the template of the parent state, there is a 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 internal frame that can have only 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 model view), you could refactor it there to expose the common in the parent state and the views with their particular details.

      

    Q: Does the structure of the folders affect the template you load?

    No, not at all. It only indicates where the navigator should go to look for each piece.

    In relation to obtenerDatos I will say that you have used the names getDatos and setDatos in a confusing way, because the names should be the other way around. set to set and get to get. Besides that I'm not sure for you to keep it there, because it's not used anywhere else, I would eliminate it.

    Other suggestions

    On the other hand, there is no need to do that, I mean: put a timer. Much better would be to change to 'Loading' before to place the order ajax ... it is more organic.

    If you are interested in this change, you could completely eliminate the getDatos and setDatos method (which you say has no use) and directly establish the corresponding state. In the case of text errors, you return to the login state, so that the error is displayed in the login view, where you 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 ...

    // cambiamos a loading
    $state.go('Loading');
    
    // solicitamos los datos
    obtenerDatos.Autenticacion(datos).then(function(response) {
    
      if(response.data) {
        datosRespuesta = response.data;
    
        if (datosRespuesta === "Usuario no registrado" || 
              datosRespuesta === "Contraseña incorrecta") {    
          $scope.respuesta = datosRespuesta;
          $state.go('login');
        } else {
          // aquí estableces el estado.
          $state.go(datosRespuesta.estudiante ? 'menuestu' : 'menuprof');
        }   
    
      } else {
        // probablemente esto nunca pase.. salvo que el server no mande datos.
        console.log(response.status);
        $scope.respuesta = response.status;
        $state.go('login');
    
        // quizá lo mejor seria cambiarlo por 
        // throw "No Data"; // esto llama automáticamente a catch.
      };      
    
    }).catch(function(reason) {
      // ademas te facilita manejar el estado 'Error de conexion'.
      $state.go('offline'); // este lo invente yo
    });
    

    Note: I assume that datosRespuesta.estudiante arrives and is true in at least one case.

        
    answered by 11.03.2016 / 03:28
    source