AngularJS 工厂不工作?
AngularJS Factory Not Working?
所以我正在跟进 thinkster.io MEAN stack tutorial,我已经完成了 "Beginning Node" 之前的所有工作,但我的应用程序没有按预期工作。
查看 post 的评论时,工厂似乎没有正确共享其变量。标题(和 link,如果出现在 post 记录中)不显示,评论也不显示(如果 post 记录有相关评论)。
我仔细检查了我的代码并确保它遵循了教程,但我无法让它工作!我做错了什么?
indexV2.html
<html>
<head>
<title>My Angular App!</title>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js"> </script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.js"></script>
<script src="appV3.js"></script>
<style> .glyphicon-thumbs-up { cursor:pointer } </style>
</head>
<body ng-app="flapperNews">
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<!-- where ui-router places templates, depending on the state -->
<ui-view></ui-view>
</div>
</div>
</div>
</div>
<script type="text/ng-template" id="/home.html">
<!-- begin home.html inline template -->
<div class="page-header">
<h1>Flapper News</h1>
</div>
<form ng-submit="addPostV2()">
<div class="form-group">
<input class="form-control" type="text" placeholder="Title" ng-model="title"></input>
</div>
<div class="form-group">
<input class="form-control" type="text" placeholder="Link" ng-model="link"></input>
</div>
<button type="submit" class="btn btn-primary">Add Post</button>
</form>
<div ng-repeat="post in posts | orderBy: '-upvotes'">
<span class="glyphicon glyphicon-thumbs-up" ng-click="incrementUpvotes(post)"></span>
<a href="{{post.link}}" ng-show="post.link">{{post.title}}</a>
<span ng-hide="post.link">{{post.title}}</span>
- upvotes: {{post.upvotes}}
- <span>
<a href="#/posts/{{$index}}">Comments</a>
</span>
</div>
</script>
<script type="text/ng-template" id="/posts.html">
<!-- begin posts.html inline template -->
<div class="page-header">
<h3>
<a ng-show="post.link" href="{{post.link}}">
{{post.title}}
</a>
<span ng-hide="post.link">
{{post.title}}
</span>
</h3>
</div>
<div ng-repeat="comment in post.comments | orderBy:'-upvotes'">
<span class="glyphicon glyphicon-thumbs-up" ng-click="incrementUpvotes(comment)"></span>
{{comment.upvotes}} - by {{comment.author}}
<span style="font-size:20px; margin-left:10px;">
{{comment.body}}
</span>
</div>
<form ng-submit="addComment()" style="margin-top:30px;">
<h3>Add a new comment</h3>
<div class="form-group">
<input type="text" class="form-control" placeholder="Comment" ng-model="body"></input>
</div>
<button type="submit" class="btn btn-primary">Post</button>
</form>
</script>
</body>
</html>
appV3.js
// instantiate app, call it flapperNews, and declare the ui.router dependency
var app = angular.module('flapperNews', ['ui.router']);
// Set up states using the config function
app.config([
'$stateProvider',
'$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', { // homepage state
url: '/home',
templateUrl: '/home.html', // specify template (will be inline, in index.html, for this example)
controller: 'MainCtrl' // assign a controller
})
.state('posts', { // state that will display comments associated with a post
url: '/posts/{id}', // id is a route parameter, made available to our controller
templateUrl: '/posts.html',
controller: 'PostsCtrl'
});
$urlRouterProvider.otherwise('home'); // redirect unspecified routes
}
]);
// factory that will share the posts array with controllers
app.factory('posts', [function () {
var o = { // create object that will hold our posts array
posts: []
};
return o;
}]);
// controller for "home" state
app.controller('MainCtrl', [
'$scope',
'posts', // inject service into controller (by adding it as a parameter)
function($scope, posts) {
// bind (not just assign) the service variable to our scope
// any changes in either will be reflected in the other
$scope.posts = posts.posts;
$scope.posts = [ // array of objects
{title: 'post 1', upvotes: 3, url: ''}, // object (collection of properties) with 2 properties
{title: 'post 2', upvotes: 4, url: ''},
{title: 'post 3', upvotes: 1, url: ''},
{title: 'post 4', upvotes: 2, url: ''},
{title: 'post 5', upvotes: 6, url: ''}
];
$scope.addPostV2 = function() {
if(!$scope.title || $scope.title === '') { // if empty or not set
return; // exit function
}
$scope.posts.push({ // push new object into array
title: $scope.title,
link: $scope.link,
upvotes: 0,
comments: [ // fake array
{author: 'Joe', body: 'Cool post!', upvotes: 0},
{author: 'Bob', body: 'Great idea but everything is wrong!', upvotes: 0}
]
});
$scope.title = ''; // empty the property (the model in the form)
$scope.link = '';
}
$scope.incrementUpvotes = function(post) { // pass the instance of post (passed in calling function, by reference - located in HTML)
post.upvotes += 1;
}
}
]);
// new controller for "posts" state
app.controller('PostsCtrl', [
'$scope',
'$stateParams',
'posts',
function($scope, $stateParams, posts) {
$scope.post = posts.posts[$stateParams.id]; // Grab a post from posts, using the id parameter from $stateParams (in URL)
$scope.addComment = function() {
if($scope.body === '') {
return;
}
$scope.post.comments.push({
body: $scope.body,
author: 'user',
upvotes: 0
});
$scope.body = '';
}
$scope.incrementUpvotes = function(comment) {
comment.upvotes += 1;
}
}
]);
感谢您提前的帮助
让我们检查一下您的代码:
$scope.posts = posts.posts;
在这行代码之后,你得到的是:
posts.posts -------> []
^
$scope.posts --------|
所以 $scope.posts 和 posts.posts 都引用同一个空数组。
现在是下面一行:
$scope.posts = [ // array of objects
{title: 'post 1', upvotes: 3, url: ''},
...
];
此行不填充服务和范围引用的数组。它将一个新数组分配给 $scope.posts。所以你最终得到
posts.posts -------> []
$scope.posts ------> [{title: 'post 1', upvotes: 3, url: ''}, ...]
因此,当您转到下一个屏幕并从 posts.posts 取回一个元素时:
$scope.post = posts.posts[$stateParams.id];
你什么也得不到,因为 posts.posts 仍然是原来的空数组。
而不是
$scope.posts = [ // array of objects
{title: 'post 1', upvotes: 3, url: ''},
...
];
你需要
$scope.posts.push({title: 'post 1', upvotes: 3, url: ''});
...
然后您将填充控制器和服务引用的数组。
请注意,让详细信息页面依赖于列表页面无论如何都是一个坏主意:如果用户刷新详细信息页面,应用程序将从头开始,详细信息页面将找不到任何东西在数组中。您应该通过向服务器发送 GET 请求来获取 post,以获取 post.
所以我正在跟进 thinkster.io MEAN stack tutorial,我已经完成了 "Beginning Node" 之前的所有工作,但我的应用程序没有按预期工作。
查看 post 的评论时,工厂似乎没有正确共享其变量。标题(和 link,如果出现在 post 记录中)不显示,评论也不显示(如果 post 记录有相关评论)。
我仔细检查了我的代码并确保它遵循了教程,但我无法让它工作!我做错了什么?
indexV2.html
<html>
<head>
<title>My Angular App!</title>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js"> </script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.js"></script>
<script src="appV3.js"></script>
<style> .glyphicon-thumbs-up { cursor:pointer } </style>
</head>
<body ng-app="flapperNews">
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<!-- where ui-router places templates, depending on the state -->
<ui-view></ui-view>
</div>
</div>
</div>
</div>
<script type="text/ng-template" id="/home.html">
<!-- begin home.html inline template -->
<div class="page-header">
<h1>Flapper News</h1>
</div>
<form ng-submit="addPostV2()">
<div class="form-group">
<input class="form-control" type="text" placeholder="Title" ng-model="title"></input>
</div>
<div class="form-group">
<input class="form-control" type="text" placeholder="Link" ng-model="link"></input>
</div>
<button type="submit" class="btn btn-primary">Add Post</button>
</form>
<div ng-repeat="post in posts | orderBy: '-upvotes'">
<span class="glyphicon glyphicon-thumbs-up" ng-click="incrementUpvotes(post)"></span>
<a href="{{post.link}}" ng-show="post.link">{{post.title}}</a>
<span ng-hide="post.link">{{post.title}}</span>
- upvotes: {{post.upvotes}}
- <span>
<a href="#/posts/{{$index}}">Comments</a>
</span>
</div>
</script>
<script type="text/ng-template" id="/posts.html">
<!-- begin posts.html inline template -->
<div class="page-header">
<h3>
<a ng-show="post.link" href="{{post.link}}">
{{post.title}}
</a>
<span ng-hide="post.link">
{{post.title}}
</span>
</h3>
</div>
<div ng-repeat="comment in post.comments | orderBy:'-upvotes'">
<span class="glyphicon glyphicon-thumbs-up" ng-click="incrementUpvotes(comment)"></span>
{{comment.upvotes}} - by {{comment.author}}
<span style="font-size:20px; margin-left:10px;">
{{comment.body}}
</span>
</div>
<form ng-submit="addComment()" style="margin-top:30px;">
<h3>Add a new comment</h3>
<div class="form-group">
<input type="text" class="form-control" placeholder="Comment" ng-model="body"></input>
</div>
<button type="submit" class="btn btn-primary">Post</button>
</form>
</script>
</body>
</html>
appV3.js
// instantiate app, call it flapperNews, and declare the ui.router dependency
var app = angular.module('flapperNews', ['ui.router']);
// Set up states using the config function
app.config([
'$stateProvider',
'$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', { // homepage state
url: '/home',
templateUrl: '/home.html', // specify template (will be inline, in index.html, for this example)
controller: 'MainCtrl' // assign a controller
})
.state('posts', { // state that will display comments associated with a post
url: '/posts/{id}', // id is a route parameter, made available to our controller
templateUrl: '/posts.html',
controller: 'PostsCtrl'
});
$urlRouterProvider.otherwise('home'); // redirect unspecified routes
}
]);
// factory that will share the posts array with controllers
app.factory('posts', [function () {
var o = { // create object that will hold our posts array
posts: []
};
return o;
}]);
// controller for "home" state
app.controller('MainCtrl', [
'$scope',
'posts', // inject service into controller (by adding it as a parameter)
function($scope, posts) {
// bind (not just assign) the service variable to our scope
// any changes in either will be reflected in the other
$scope.posts = posts.posts;
$scope.posts = [ // array of objects
{title: 'post 1', upvotes: 3, url: ''}, // object (collection of properties) with 2 properties
{title: 'post 2', upvotes: 4, url: ''},
{title: 'post 3', upvotes: 1, url: ''},
{title: 'post 4', upvotes: 2, url: ''},
{title: 'post 5', upvotes: 6, url: ''}
];
$scope.addPostV2 = function() {
if(!$scope.title || $scope.title === '') { // if empty or not set
return; // exit function
}
$scope.posts.push({ // push new object into array
title: $scope.title,
link: $scope.link,
upvotes: 0,
comments: [ // fake array
{author: 'Joe', body: 'Cool post!', upvotes: 0},
{author: 'Bob', body: 'Great idea but everything is wrong!', upvotes: 0}
]
});
$scope.title = ''; // empty the property (the model in the form)
$scope.link = '';
}
$scope.incrementUpvotes = function(post) { // pass the instance of post (passed in calling function, by reference - located in HTML)
post.upvotes += 1;
}
}
]);
// new controller for "posts" state
app.controller('PostsCtrl', [
'$scope',
'$stateParams',
'posts',
function($scope, $stateParams, posts) {
$scope.post = posts.posts[$stateParams.id]; // Grab a post from posts, using the id parameter from $stateParams (in URL)
$scope.addComment = function() {
if($scope.body === '') {
return;
}
$scope.post.comments.push({
body: $scope.body,
author: 'user',
upvotes: 0
});
$scope.body = '';
}
$scope.incrementUpvotes = function(comment) {
comment.upvotes += 1;
}
}
]);
感谢您提前的帮助
让我们检查一下您的代码:
$scope.posts = posts.posts;
在这行代码之后,你得到的是:
posts.posts -------> []
^
$scope.posts --------|
所以 $scope.posts 和 posts.posts 都引用同一个空数组。
现在是下面一行:
$scope.posts = [ // array of objects
{title: 'post 1', upvotes: 3, url: ''},
...
];
此行不填充服务和范围引用的数组。它将一个新数组分配给 $scope.posts。所以你最终得到
posts.posts -------> []
$scope.posts ------> [{title: 'post 1', upvotes: 3, url: ''}, ...]
因此,当您转到下一个屏幕并从 posts.posts 取回一个元素时:
$scope.post = posts.posts[$stateParams.id];
你什么也得不到,因为 posts.posts 仍然是原来的空数组。
而不是
$scope.posts = [ // array of objects
{title: 'post 1', upvotes: 3, url: ''},
...
];
你需要
$scope.posts.push({title: 'post 1', upvotes: 3, url: ''});
...
然后您将填充控制器和服务引用的数组。
请注意,让详细信息页面依赖于列表页面无论如何都是一个坏主意:如果用户刷新详细信息页面,应用程序将从头开始,详细信息页面将找不到任何东西在数组中。您应该通过向服务器发送 GET 请求来获取 post,以获取 post.