return FALSE; $r = well_tag_thread__update(array('id' => $id), $update); return $r; } function well_tag_thread_find($tagid, $page, $pagesize) { $arr = well_tag_thread__find(array('tagid' => $tagid), array('id' => -1), $page, $pagesize); return $arr; } function well_tag_thread_find_by_tid($tid, $page, $pagesize) { $arr = well_tag_thread__find(array('tid' => $tid), array(), $page, $pagesize); return $arr; } ?>javascript - Why does Closure Compiler break this AngularJS script? - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why does Closure Compiler break this AngularJS script? - Stack Overflow

programmeradmin3浏览0评论

I'm testing AngularJs with Play Framework 2.0 (Scala). Play uses Closure to minimize Javascript files.

My file is as follows:

// Define a Module 'todoList' for Angular that will load the views. In this example the views are very simple, it's just to show
// the concept
angular.module('todoList', ['taskDoneFilter', 'todoServices']).
    config(['$routeProvider', function($routeProvider) {
        $routeProvider.
            when('/all', {templateUrl: 'assets/angular/all.html',   controller: TodoCtrl}).
            when('/task/:id', {templateUrl: 'assets/angular/task.html', controller: TaskDetailCtrl}).
            otherwise({redirectTo: '/all'});
    }]);


// This filter allows us to convert strings. In this case, it adds an extra tick besides a task indicating if it's done or no
angular.module('taskDoneFilter', []).filter('checkmark', function() {
    return function(input) {
        return input ? '\u2713' : '\u2718';
    };
});


// When running tests with Jasmine the jsRoutes object is not defined, which means we need to use a default route for the http call below
// This kind of defeats the purpose of retrieving the routes via Play instead of hardcoding them, as we need a fallback for the tests
// but I decided to leave the code just to see that we have the possibility, in case I find a way to improve this.
var tasksUrl = '/tasks/all';
if(!(typeof jsRoutes === "undefined")) {
  tasksUrl = jsRoutes.controllers.Application.tasks().url ;
}

// Definition of a Service, that stores all the REST requests independently from the controllers, facilitating change
angular.module('todoServices', ['ngResource']).
    factory('All', function ($resource) {
        return $resource(tasksUrl, {}, {
            //The data model is loaded via a GET request to the app
            query: {method: 'GET', params: {}, isArray: true}
        });
    })
    .factory('Task', function ($resource) {
        return $resource('tasks', {}, {
            add: {method: 'POST'}
        });
    });

/**
 * This is the controller behind the view, as declared by ng-controller
 * All references to methods and data model in the view map to this controller
 * @param $scope model data injected into the controller
 * @constructor
 */
var TodoCtrl = ['$scope', 'All', 'Task', function($scope, All, Task) {
    // We use the service to query for the data
    $scope.todos = All.query();

    //when submitting the form, this is called. Model in the form is referenced (todoText) and we add the task to
    //the data model
    $scope.addTodo = function() {
        var txt = $scope.todoText;
        $scope.todos.push({text: txt, done: false});
        Task.save({msg: txt});
        $scope.todoText = '';  //clear the input!
    };

    // calculates the remaining todos, automatically called when the model changes to update the view
    // notice the use of 'angular' ponent for functional approach
    $scope.remaining = function() {
        var count = 0;
        angular.forEach($scope.todos, function(todo) {
            count += todo.done ? 0 : 1;
        });
        return count;
    };

    //another acton triggered by click (in this case on an anchor), which archives pleted tasks
    $scope.archive = function() {
        var oldTodos = $scope.todos;
        $scope.todos = [];
        angular.forEach(oldTodos, function(todo) {
            if (!todo.done) $scope.todos.push(todo);
        });
    };
}];

// Task details controller, used in the routes to provide a second view for the application
var TaskDetailCtrl = ['$scope', '$routeParams', function($scope, $routeParams) {
    $scope.id = $routeParams.id;
}];

But when minimizing, it bees:

var module$todo={};angular.module("todoList",["taskDoneFilter","todoServices"]).config(["$routeProvider",function($routeProvider){$routeProvider.when("/all",{templateUrl:"assets/angular/all.html",controller:TodoCtrl$$module$todo}).when("/task/:id",{templateUrl:"assets/angular/task.html",controller:TaskDetailCtrl$$module$todo}).otherwise({redirectTo:"/all"})}]);angular.module("taskDoneFilter",[]).filter("checkmark",function(){return function(input){return input?"\u2713":"\u2718"}});
var tasksUrl$$module$todo="/tasks/all";if(!(typeof jsRoutes==="undefined"))tasksUrl$$module$todo=jsRoutes.controllers.Application.tasks().url;angular.module("todoServices",["ngResource"]).factory("All",function($resource){return $resource(tasksUrl$$module$todo,{},{query:{method:"GET",params:{},isArray:true}})}).factory("Task",function($resource){return $resource("tasks",{},{add:{method:"POST"}})});
var TodoCtrl$$module$todo=["$scope","All","Task",function($scope,All,Task){$scope.todos=All.query();$scope.addTodo=function(){var txt=$scope.todoText;$scope.todos.push({text:txt,done:false});Task.save({msg:txt});$scope.todoText=""};$scope.remaining=function(){var count=0;angular.forEach($scope.todos,function(todo){count+=todo.done?0:1});return count};$scope.archive=function(){var oldTodos=$scope.todos;$scope.todos=[];angular.forEach(oldTodos,function(todo){if(!todo.done)$scope.todos.push(todo)})}}];
var TaskDetailCtrl$$module$todo=["$scope","$routeParams",function($scope,$routeParams){$scope.id=$routeParams.id}];

And then it stops working. Notice the:

var module$todo={};

and

var TodoCtrl$$module$todo=

which break the app.

Anyone knows why may this be happening?

I'm testing AngularJs with Play Framework 2.0 (Scala). Play uses Closure to minimize Javascript files.

My file is as follows:

// Define a Module 'todoList' for Angular that will load the views. In this example the views are very simple, it's just to show
// the concept
angular.module('todoList', ['taskDoneFilter', 'todoServices']).
    config(['$routeProvider', function($routeProvider) {
        $routeProvider.
            when('/all', {templateUrl: 'assets/angular/all.html',   controller: TodoCtrl}).
            when('/task/:id', {templateUrl: 'assets/angular/task.html', controller: TaskDetailCtrl}).
            otherwise({redirectTo: '/all'});
    }]);


// This filter allows us to convert strings. In this case, it adds an extra tick besides a task indicating if it's done or no
angular.module('taskDoneFilter', []).filter('checkmark', function() {
    return function(input) {
        return input ? '\u2713' : '\u2718';
    };
});


// When running tests with Jasmine the jsRoutes object is not defined, which means we need to use a default route for the http call below
// This kind of defeats the purpose of retrieving the routes via Play instead of hardcoding them, as we need a fallback for the tests
// but I decided to leave the code just to see that we have the possibility, in case I find a way to improve this.
var tasksUrl = '/tasks/all';
if(!(typeof jsRoutes === "undefined")) {
  tasksUrl = jsRoutes.controllers.Application.tasks().url ;
}

// Definition of a Service, that stores all the REST requests independently from the controllers, facilitating change
angular.module('todoServices', ['ngResource']).
    factory('All', function ($resource) {
        return $resource(tasksUrl, {}, {
            //The data model is loaded via a GET request to the app
            query: {method: 'GET', params: {}, isArray: true}
        });
    })
    .factory('Task', function ($resource) {
        return $resource('tasks', {}, {
            add: {method: 'POST'}
        });
    });

/**
 * This is the controller behind the view, as declared by ng-controller
 * All references to methods and data model in the view map to this controller
 * @param $scope model data injected into the controller
 * @constructor
 */
var TodoCtrl = ['$scope', 'All', 'Task', function($scope, All, Task) {
    // We use the service to query for the data
    $scope.todos = All.query();

    //when submitting the form, this is called. Model in the form is referenced (todoText) and we add the task to
    //the data model
    $scope.addTodo = function() {
        var txt = $scope.todoText;
        $scope.todos.push({text: txt, done: false});
        Task.save({msg: txt});
        $scope.todoText = '';  //clear the input!
    };

    // calculates the remaining todos, automatically called when the model changes to update the view
    // notice the use of 'angular' ponent for functional approach
    $scope.remaining = function() {
        var count = 0;
        angular.forEach($scope.todos, function(todo) {
            count += todo.done ? 0 : 1;
        });
        return count;
    };

    //another acton triggered by click (in this case on an anchor), which archives pleted tasks
    $scope.archive = function() {
        var oldTodos = $scope.todos;
        $scope.todos = [];
        angular.forEach(oldTodos, function(todo) {
            if (!todo.done) $scope.todos.push(todo);
        });
    };
}];

// Task details controller, used in the routes to provide a second view for the application
var TaskDetailCtrl = ['$scope', '$routeParams', function($scope, $routeParams) {
    $scope.id = $routeParams.id;
}];

But when minimizing, it bees:

var module$todo={};angular.module("todoList",["taskDoneFilter","todoServices"]).config(["$routeProvider",function($routeProvider){$routeProvider.when("/all",{templateUrl:"assets/angular/all.html",controller:TodoCtrl$$module$todo}).when("/task/:id",{templateUrl:"assets/angular/task.html",controller:TaskDetailCtrl$$module$todo}).otherwise({redirectTo:"/all"})}]);angular.module("taskDoneFilter",[]).filter("checkmark",function(){return function(input){return input?"\u2713":"\u2718"}});
var tasksUrl$$module$todo="/tasks/all";if(!(typeof jsRoutes==="undefined"))tasksUrl$$module$todo=jsRoutes.controllers.Application.tasks().url;angular.module("todoServices",["ngResource"]).factory("All",function($resource){return $resource(tasksUrl$$module$todo,{},{query:{method:"GET",params:{},isArray:true}})}).factory("Task",function($resource){return $resource("tasks",{},{add:{method:"POST"}})});
var TodoCtrl$$module$todo=["$scope","All","Task",function($scope,All,Task){$scope.todos=All.query();$scope.addTodo=function(){var txt=$scope.todoText;$scope.todos.push({text:txt,done:false});Task.save({msg:txt});$scope.todoText=""};$scope.remaining=function(){var count=0;angular.forEach($scope.todos,function(todo){count+=todo.done?0:1});return count};$scope.archive=function(){var oldTodos=$scope.todos;$scope.todos=[];angular.forEach(oldTodos,function(todo){if(!todo.done)$scope.todos.push(todo)})}}];
var TaskDetailCtrl$$module$todo=["$scope","$routeParams",function($scope,$routeParams){$scope.id=$routeParams.id}];

And then it stops working. Notice the:

var module$todo={};

and

var TodoCtrl$$module$todo=

which break the app.

Anyone knows why may this be happening?

Share Improve this question edited Jan 6, 2013 at 17:08 Pere Villega asked Jan 6, 2013 at 17:00 Pere VillegaPere Villega 16.4k5 gold badges65 silver badges100 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 10

Your All & Task services are not 'minify safe'. You must use the array notation.

angular.module('todoServices', ['ngResource']).
    factory('All', ['$resource', function ($resource) {
        return $resource(tasksUrl, {}, {
            //The data model is loaded via a GET request to the app
            query: {method: 'GET', params: {}, isArray: true}
        });
    }])
    .factory('Task', ['$resource', function ($resource) {
        return $resource('tasks', {}, {
            add: {method: 'POST'}
        });
    }]);

Also, define your controller with angular.module(...).controller():

angular.module(...).controller('TodoCtrl', ['$scope', 'All', 'Task', function($scope, All, Task) {
}]);

... and if you have a larger app, you can find where you aren't using named references by turning on strictDi (option to bootstrap call or ng-strict-di attribute in tag with ng-app attribute).

发布评论

评论列表(0)

  1. 暂无评论