我目前正在研究这个AngularJS教程:学习使用Angular和Rails https://thinkster.io/angular-rails/构建现代Web应用程序,我认为这是一个很好的资源,展示了如何使用AngularJS构建Rails Web应用程序。
到目前为止,我已经成功完成了超过三分之二的教程,但现在我面临着工厂服务的一些问题。当我点击帖子按钮创建新帖子时,我收到以下错误:
错误消息
angular.js?body=1:11608 TypeError: undefined is not a function
at Scope.$scope.addPost (http://0.0.0.0:3000/assets/home/mainCtrl.js?body=1:23:24)
它指向 mainCtrl.js 文件中的以下代码:
posts.create({
title: $scope.title,
link: $scope.link,
});
整个 mainCtrl.js 文件:
angular.module('flapperNews')
.controller('MainCtrl', ['$scope', 'posts', function ($scope, posts) {
$scope.test = 'Hello world!';
$scope.posts = posts.posts;
$scope.posts.push({
title: $scope.title,
link: $scope.link,
upvotes: 0,
comments: [
{ author: 'Joe', body: 'Cool post!', upvotes: 0 },
{ author: 'Bob', body: 'Great idea but everything is wrong!', upvotes: 0 }
]
});
$scope.addPost = function () {
if (!$scope.title || $scope.title === '') { return; }
posts.create({
title: $scope.title,
link: $scope.link,
});
$scope.title = '';
$scope.link = '';
};
$scope.incrementUpvotes = function(post) {
posts.upvote(post);
};
}]);
在上面的控制器中,如果在引入工厂创建方法之前将addPost
函数替换为教程中使用的函数,那么它可以正常工作。
工作代码:
$scope.addPost = function(){
if(!$scope.title || $scope.title === '') { return; }
$scope.posts.push({
title: $scope.title,
link: $scope.link,
upvotes: 0
});
$scope.title = '';
$scope.link = '';
};
所以不知何故工厂的posts.create方法引起了问题(尽管posts.posts是可访问的)。
以下是 post.js 文件o.create
方法导致当前问题
angular.module('flapperNews').factory('posts', ['$http',
function($http){
var o = {
posts: []
};
return o;
o.getAll = function() {
return $http.get('/posts.json').success(function(data){
angular.copy(data, o.posts);
});
};
o.create = function(post) {
console.log("o.create");
return $http.post('/posts.json', post).success(function(data){
o.posts.push(data);
});
};
o.upvote = function(post) {
return $http.put('/posts/' + post.id + '/upvote.json')
.success(function(data){
post.upvotes += 1;
});
};
resolve: {
postPromise: ['posts', function(posts){
return posts.getAll();
}]
}
}
]);
app.js 文件
angular.module('flapperNews', ['ui.router', 'templates'])
.config([
'$stateProvider',
'$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'home/_home.html',
controller: 'MainCtrl'
})
.state('posts', {
url: '/posts/{id}',
templateUrl: 'posts/_posts.html',
controller: 'PostsCtrl'
})
$urlRouterProvider.otherwise('home')
}]);
如果有人知道这里的根本问题,请提供建议。非常感谢: - )
我的rails版本4.0.2,我正在使用Linux Ubuntu 12.04
有些想法,如果我不能让工厂方法有效,那么我可能会将这些方法直接放在控制器中解决问题,希望如下:-)
答案 0 :(得分:1)
你过早地返回了这个对象,其他函数没有注册(因为它们是函数表达式,而不是函数声明,它们没有得到hoisted)。将return o;
移到最后,它会起作用:
app.factory('posts', ['$http',
function($http){
var o = {
posts: []
};
o.getAll = function() {
return $http.get('/posts.json').success(function(data){
angular.copy(data, o.posts);
});
};
o.create = function(post) {
alert('In create!');
console.log("o.create");
return $http.post('/posts.json', post).success(function(data){
o.posts.push(data);
});
};
o.upvote = function(post) {
return $http.put('/posts/' + post.id + '/upvote.json')
.success(function(data){
post.upvotes += 1;
});
};
resolve: {
postPromise: ['posts', function(posts){
return posts.getAll();
}]
}
return o;
}
])
请参见此工作Fiddle。
答案 1 :(得分:1)
您的解决方案声明应该在您的app.js中处于主页状态正如教程所说,&#34;通过这种方式使用resolve属性,我们确保无论何时进入我们的home状态,我们都会在状态实际完成加载之前自动查询后端的所有帖子。&#34; < / p>
App.js:
angular.module('flapperNews', ['ui.router', 'templates'])
.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'home/_home.html',
controller: 'MainCtrl',
resolve: {
postPromise: ['posts', function(posts){
return posts.getAll();
}]
}
})
.state('posts', {
url: '/posts/{id}',
templateUrl: 'posts/_posts.html',
controller: 'PostsCtrl'
})
$urlRouterProvider.otherwise('home');
}]);