Build an Instagram clone with AngularJS, Satellizer, Node.js and MongoDB
#17.Detail 页面
还有一个重要部分没有实现就是这个一张照片的详细页面了 – 为每张照片设置一个独立的页面,包含放大的图片,说明,吐槽,点赞数量。
创建一个新的模板 views/detail.html 内容如下:
<!-- lang: js -->
<div class="container">
<div class="panel panel-default">
<div class="panel-body">
<div class="row">
<div class="col-xs-6">
<img ng-src="{{photo.images.standard_resolution.url}}" class="img-responsive">
</div>
<div class="col-xs-6">
<div class="caption">
<h5><a href="http://instagram.com/{{photo.user.username}}">{{photo.user.username}}</a></h5>
<h6 class="text-muted"><i class="ion-clock"></i> {{photo.created_time * 1000 | date:'short'}}</h6>
<p>{{photo.caption.text}}</p>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<h5><i class="ion-heart text-danger"></i> {{photo.likes.count}} likes</h5>
<hr class="soften">
<h5 class="text-center"><i class="ion-chatbox-working text-primary"></i> Comments</h5>
<ul class="media-list">
<li ng-repeat="comment in photo.comments.data" class="media">
<a class="pull-left" href="http://instagram.com/{{comment.from.username}}">
<img class="media-object img-rounded" ng-src="{{comment.from.profile_picture}}">
</a>
<div class="media-body">
<a class="media-heading" href="http://instagram.com/{{comment.from.username}}">@{{comment.from.username}}</a>
{{comment.text}}
</div>
</li>
<li ng-if="!photo.comments.data.length">No comments</li>
</ul>
<hr class="soften">
<div class="btn-group">
<button class="btn" ng-class="{ 'btn-danger': hasLiked, 'btn-default': !hasLiked }" ng-click="like()">
<i class="ion-heart" ng-class="{ 'text-danger': !hasLiked}"></i>
<span ng-if="hasLiked">Liked</span>
<span ng-if="!hasLiked">Like</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
这个模板通篇没有撸点,因为这里面都没什么新概念值得去提了。里面有很多 Bootstrap 的 classe 把页面打扮的漂漂亮亮的,不过也就那样了。
如果你刷新浏览器,然后点其中一张缩略图,然后你就能看到新创建的这个模板了。不过,因为我们没有给这个页面创建 controller 来获取数据,所以它还什么都没有。
在 controllers 目录,创建一个新的文件叫做 detail.js。它的主要职责是处理 <em>Like</em> 动作和获取媒体数据的。
<!-- lang: js -->
angular.module('Instagram')
.controller('DetailCtrl', function($scope, $rootScope, $location, API) {
var mediaId = $location.path().split('/').pop();
API.getMediaById(mediaId).success(function(media) {
$scope.hasLiked = media.user_has_liked;
$scope.photo = media;
});
$scope.like = function() {
$scope.hasLiked = true;
API.likeMedia(mediaId).error(function(data) {
sweetAlert('Error', data.message, 'error');
});
};
});
注意我是怎样的把 Instagram 媒体 id 从 URL 路径剥离开来并把它传到 API.getMediaById(mediaId) 的。当我们点击缩略图被引导到详细页面的时候,我们知道这张图的 id,所以锚点是这样的:
<!-- lang: js -->
<a href="#/photo/{{photo.id}}">
但当我们直接访问的时候,比如说,直接访问 http://localhost:8000/#/photo/861959103308715759_787132 或者刷新页面的时候,我们就拿不到 $scope.photos,因为它是 HomeCtrl controller 的一部分,而只在 home 页面 (“/” 路由)。
第二个方法,$scope.like(),这有一个临时变量叫做 hasLiked,如果被设为 true 它会把心形标签♥设为红色并把 Like 变成 Liked。看看上面的 detail.html 模板。假如发生了异常,比如达到了 API 请求次数限制,一个漂亮的消息框就会弹出来显示异常信息。正如 @kukac7 指出 的那样,还有一种方式来检查用户是否已经对这张照片点赞。
下面一节我们将实现 NavbarCtrl controller 来处理 Logout 动作,还有如果用户已经被认证,那么我们会把 Log in/Sign up 隐藏,而如果用户没有被认证,我们会把 Logout 隐藏。