Load templates and angular controllers using require.js

0

I have a problem using require.js and angular.js to load modules asynchronously, and is that many times when making a minimum change I always get the following error:

  

Uncaught ReferenceError: angular is not defined

main.js

Configuring the javascript files in the main of require.js

require.config({    
    baseUrl: 'js',    

    paths : {      
        angular: 'libs/angular',
        ngRoute: 'libs/angular-route',
        ngResource: 'libs/angular-resource',
        uiRouter: 'libs/angular-ui-router',
        index: 'app/index'      
    },

    shim: {        
        angular: {
            exports : 'angular'
        }
    }


});

require(['index'], function (index){

});

index.js

define(['angular', 'uiRouter'], function (){


angular.module('AppUPC', ['ui-router'])
        .controller('formulario', formulario)
        .service('obtenerDatos', obtenerDatos)
        .config('rutas', rutas);

formulario.$inject = ['$scope', 'obtenerDatos'];

function formulario($scope, obtenerDatos){

    $scope.login = function(){

        var datos;

        datos = {

            Usuario: $scope.usuariotxt,
            Password: $scope.passwordtxt

        };

        obtenerDatos.Authentication(datos).then(function (response){

            if(response.data){
                console.log(response.data);
            }else{
                console.log(response.status);
            };

        });

     };         

};


obtenerDatos.$inject = ['$http', '$httpParamSerializer'];

function obtenerDatos($http, $httpParamSerializer){

    function Authentication(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' }

        });

    };

    return {
        Authentication: Authentication

    };

};

rutas.inject = ['$stateProvider', '$urlRouterProvider'];

function rutas($stateProvider, $urlRouterProvider){

    $urlRouterProvider.otherwise("/login");

     $stateProvider
        .state('login', {
            url: '/login',
            templateUrl: "templates/login.html",
            controller: "formulario"
        });

};


});

    
asked by Pedro Miguel Pimienta Morales 29.02.2016 в 17:40
source

1 answer

2

Using angular with require.js has never seemed a good idea since angular has the modules to encapsulate and divide the logic of your business and this is also one of the strongest points of require.js and the reason why what else is used This is just my opinion and in this question of SO you will see that the opinions are very diverse.

If the problem you are facing is a large number of files you can use automation with gulp and grunt to inject them into your index.html file. Using yeoman you can create a project that already does that by default with the advantage that you can use gulp-angular-filesort to infer which module depends on who automatically, task that you must do manually if you use require.js.

However, going back to the problem you are in:

The reason he is giving you the error is because the files are loading in random order as it requires.js by default he will try to infer the dependencies and load them all as quickly as possible. At the end of the file upload section you can read:

  

Ideally the scripts you load will be modules that are defined by calling define (). However, you may need to use some traditional / legacy "browser globals" scripts that do not express their dependencies via define (). For those, you can use the shim config. To properly express their dependencies.

     

If you do not express the dependencies, you will likely get loading errors since RequireJS loads scripts asynchronously and out of order for speed.

That translates more or less in this:

  

Ideally, the scripts you will load are modules that have been defined using define (). However, you may need to use a traditional script that does not express its dependencies using define (). For those cases you can use the shim configuration, to express your dependencies appropriately.

     

If you do not express the dependencies, it is very likely that you have load errors since RequireJS loads the scripts asynchronously and without order to achieve greater speed.

The mechanics section describes the internal operation of require.js in a bit more detail. .

This is not a problem when your file is specified using the module pattern define(....); in any of its variants but unfortunately neither angular nor many other plugins are written in that format so you must specify its configuration using a shim

The solution is to specify the order of loading using the dependencies.

shim: {
   angular: { exports : 'angular' },
   ngRoute: { deps: ['angular'] },
   ngResource: { deps: ['angular'] },
   uiRouter: { deps: ['angular'] }
}

This way you are telling the other modules that are not AMD that they should wait for the angle to be evaluated.

Update

I forgot to mention that every time you define a module that exports a global variable you must capture it using the arguments of the function that you specify in the define . Read this section of the docs. Ex:

define(['angular', 'uiRouter'], function (angular){
    // Usa una variable local para acceder a angular
    // Require.js te dará el módulo correcto si lo has configurado bien
});

You must use a local variable that matches the order of the dependencies you specify; ui-router does not export anything so it is not necessary to reference it.

    
answered by 29.02.2016 / 18:34
source