(function() {
var app = angular.module('gemStore', ['store-directives']);
//StoreController dependency-injection of $http
//This controller will store a product's information in store.products
app.controller('StoreController', ['$http', function($http){
var store = this;
store.products = [];
//Get a product's JSON information and store it in store.products
$http.get('store-products.json').success(function(data){
store.products = data;
});
}]);
//ReviewController handles user reviews. Reviews start out as empty objects
app.controller('ReviewController', function() {
this.review = {};
//add a review to this product and push it into empty object (see above)
this.addReview = function(product) {
product.reviews.push(this.review);
//Clear review form upon submit.
this.review = {};
};
});
})();
<!DOCTYPE html>
<html ng-app="gemStore">
<head>
<meta charset="utf-8" />
<title>AngularJS</title>
<link data-require="bootstrap-css" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
<link data-require="semantic-ui@*" data-semver="0.9.6" rel="stylesheet" href="https://raw.github.com/Semantic-Org/Semantic-UI/0.9.6/build/packaged/css/semantic.min.css" />
<script data-require="semantic-ui@*" data-semver="0.9.6" src="https://raw.github.com/Semantic-Org/Semantic-UI/0.9.6/build/packaged/javascript/semantic.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js@1.2.x" src="http://code.angularjs.org/1.2.15/angular.js" data-semver="1.2.15"></script>
<script data-require="jquery@*" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="app.js"></script>
<script src="products.js"></script>
</head>
<body ng-controller="StoreController as store">
<!-- Store Header -->
<header>
<h1 class="text-center">Flatlander Crafted Gems</h1>
<h2 class="text-center">– an Angular store –</h2>
</header>
<!-- Products Container -->
<div class="list-group">
<!-- Product Container -->
<div class="list-group-item" ng-repeat="product in store.products">
<h3>{{product.name}} <em class="pull-right">{{product.price | currency}}</em></h3>
<!-- Image Gallery -->
<product-gallery></product-gallery>
<!-- Product Tabs -->
<product-tabs></product-tabs>
</div>
</div>
</body>
</html>
body{
max-width: 500px;
margin: 0 auto;
}
a {
color: #ac005f;
}
a:hover,
a:focus {
text-decoration: underline;
}
ul{
padding: 0;
}
li{
list-style: none;
}
li.small-image{
width: 50px;
}
li.small-image img{
width: 100%;
}
img{
max-width: 230px;
max-height: 230px;
}
.img-wrap {
background: #f8f8f8;
height: 200px;
margin: 0 auto 20px;
padding: 10px;
width: 200px;
}
.img-thumbnail {
background: none;
border: 0;
height: auto;
max-width: 100%;
}
.img-thumbnails {
margin: 0 auto 10px;
width: 200px;
}
.img-thumbnails .thumbnail {
background: #f8f8f8;
border: 0;
margin-right: 25px;
min-height: 50px;
}
.img-thumbnails .thumbnail:last-child {
margin-right: 0;
}
.nav-pills {
margin-bottom: 30px;
}
.nav-pills > li > a:hover,
.nav-pills > li > a:focus{
color: #ac005f;
}
.nav-pills > li.active > a,
.btn-primary,
.btn-primary:focus {
background: #ac005f;
border: 0;
}
.nav-pills > li.active > a:hover,
.btn-primary:hover {
background: #ac005f;
}
<!-- Description Tab's Content -->
<div ng-show="tab.isSet(1)">
<h4>Description</h4>
<blockquote>{{product.description}}</blockquote>
</div>
<!-- Tabs Go Here -->
<section>
<ul class="nav nav-pills">
<li ng-class="{ active:tab.isSet(1) }">
<a href="" ng-click="tab.setTab(1)">Description</a>
</li>
<li ng-class="{ active:tab.isSet(2) }">
<a href="" ng-click="tab.setTab(2)">Specs</a>
</li>
<li ng-class="{ active:tab.isSet(3) }">
<a href="" ng-click="tab.setTab(3)">Reviews</a>
</li>
</ul>
<!-- Description Tab's Content -->
<product-description ng-show="tab.isSet(1)" ></product-description>
<!-- Spec Tab's Content -->
<div product-specs ng-show="tab.isSet(2)"></div>
<!-- Review Tab's Content -->
<product-reviews ng-show="tab.isSet(3)"></product-reviews>
</section>
(function(){
var app = angular.module('store-directives', []);
app.directive("productDescription", function() {
return {
restrict: "E",
templateUrl: "product-description.html"
};
});
app.directive("productReviews", function() {
return {
restrict: "E",
templateUrl: "product-reviews.html"
};
});
app.directive("productSpecs", function() {
return {
restrict:"A",
templateUrl: "product-specs.html"
};
});
app.directive("productTabs", function() {
return {
restrict: "E",
templateUrl: "product-tabs.html",
controller: function() {
this.tab = 1;
this.isSet = function(checkTab) {
return this.tab === checkTab;
};
this.setTab = function(activeTab) {
this.tab = activeTab;
};
},
controllerAs: "tab"
};
});
app.directive("productGallery", function() {
return {
restrict: "E",
templateUrl: "product-gallery.html",
controller: function() {
this.current = 0;
this.setCurrent = function(imageNumber){
this.current = imageNumber || 0;
};
},
controllerAs: "gallery"
};
});
})();
<!-- Product Reviews List -->
<ul>
<h4>Reviews</h4>
<li ng-repeat="review in product.reviews">
<blockquote>
<strong>{{review.stars}} Stars</strong>
{{review.body}}
<cite class="clearfix">—{{review.author}}</cite>
</blockquote>
</li>
</ul>
<!-- Review Form -->
<form name="reviewForm" ng-controller="ReviewController as reviewCtrl" ng-submit="reviewCtrl.addReview(product)">
<!-- Live Preview -->
<blockquote >
<strong>{{reviewCtrl.review.stars}} Stars</strong>
{{reviewCtrl.review.body}}
<cite class="clearfix">—{{reviewCtrl.review.author}}</cite>
</blockquote>
<!-- Review Form -->
<h4>Submit a Review</h4>
<fieldset class="form-group">
<select ng-model="reviewCtrl.review.stars" class="form-control" ng-options="stars for stars in [5,4,3,2,1]" title="Stars">
<option value>Rate the Product</option>
</select>
</fieldset>
<fieldset class="form-group">
<textarea ng-model="reviewCtrl.review.body" class="form-control" placeholder="Write a short review of the product..." title="Review"></textarea>
</fieldset>
<fieldset class="form-group">
<input ng-model="reviewCtrl.review.author" type="email" class="form-control" placeholder="jimmyDean@example.org" title="Email" />
</fieldset>
<fieldset class="form-group">
<input type="submit" class="btn btn-primary pull-right" value="Submit Review" />
</fieldset>
</form>
<!-- Spec Tab's Content -->
<h4>Specs</h4>
<ul class="list-unstyled">
<li>
<strong>Shine</strong>
: {{product.shine}}</li>
<li>
<strong>Faces</strong>
: {{product.faces}}</li>
<li>
<strong>Rarity</strong>
: {{product.rarity}}</li>
<li>
<strong>Color</strong>
: {{product.color}}</li>
</ul>
[
{
"name": "Azurite",
"description": "Some gems have hidden qualities beyond their luster, beyond their shine... Azurite is one of those gems.",
"shine": 8,
"price": 110.50,
"rarity": 7,
"color": "#CCC",
"faces": 14,
"images": [
"http://cl.zdn.io/UuY7/gem-02.gif",
"http://cl.zdn.io/UuWP/gem-05.gif",
"http://cl.zdn.io/UuD4/gem-09.gif"
],
"reviews": [{
"stars": 5,
"body": "I love this gem!",
"author": "joe@thomas.com",
"createdOn": 1397490980837
}, {
"stars": 1,
"body": "This gem sucks.",
"author": "tim@hater.com",
"createdOn": 1397490980837
}]
},
{
"name": "Bloodstone",
"description": "Origin of the Bloodstone is unknown, hence its low value. It has a very high shine and 12 sides, however.",
"shine": 9,
"price": 22.90,
"rarity": 6,
"color": "#EEE",
"faces": 12,
"images": [
"http://cl.zdn.io/UvAK/gem-01.gif",
"http://cl.zdn.io/Uuwd/gem-03.gif",
"http://cl.zdn.io/UuVP/gem-04.gif"
],
"reviews": []
},
{
"name": "Zircon",
"description": "Zircon is our most coveted and sought after gem. You will pay much to be the proud owner of this gorgeous and high shine gem.",
"shine": 70,
"price": 1100,
"rarity": 2,
"color": "#000",
"faces": 6,
"images": [
"http://cl.zdn.io/Uv3v/gem-06.gif",
"http://cl.zdn.io/Uu84/gem-07.gif",
"http://cl.zdn.io/Uuky/gem-10.gif"
],
"reviews": []
}
]
<div ng-show="product.images.length">
<div class="img-wrap">
<img ng-src="{{product.images[gallery.current]}}" />
</div>
<ul class="img-thumbnails clearfix">
<li class="small-image pull-left thumbnail" ng-repeat="image in product.images">
<img ng-click="gallery.setCurrent($index)" ng-src="{{image}}" />
</li>
</ul>
</div>
# Codeschool: Shaping Up with Angular.js Tutorial
This is a sample Angular.js application. The application was apart of [CodeSchool's](http://codeschool.com) [AngularJS](https://www.codeschool.com/courses/shaping-up-with-angular-js/goto) tutorial.
# Live Preview
http://plnkr.co/edit/moDMH7?p=preview
# Objective
Using Angular.js, create an online store that showcases a number of products and their respective descriptions, images, specifications, and reviews.
Enable users to submit and preview their own reviews in real-time. Store the latest reviews in a JSON file which corresponds to the appropriate product. Review forms should have proper validation.
# Features
[**Directives**](https://docs.angularjs.org/guide/directive) - "...markers on a DOM element (such as an attribute, element name, comment or CSS class) that tell AngularJS's HTML compiler ($compile) to attach a specified behavior to that DOM element or even transform the DOM element and its children.
Angular comes with a set of these directives built-in, like ngBind, ngModel, and ngClass. Much like you create controllers and services, you can create your own directives for Angular to use. When Angular bootstraps your application, the HTML compiler traverses the DOM matching directives against the DOM elements."
[**Expressions**](https://docs.angularjs.org/guide/expression) - "Angular expressions are JavaScript-like code snippets that are usually placed in bindings such as {{ expression }}."
[**Filters**](https://docs.angularjs.org/guide/filter) - "A filter formats the value of an expression for display to the user. They can be used in view templates, controllers or services and it is easy to define your own filter" (e.g {{ expression | filter }} )
[**Modules**](https://docs.angularjs.org/guide/module) - "You can think of a module as a container for the different parts of your app – controllers, services, filters, directives, etc."
[**Controllers**](https://docs.angularjs.org/guide/controller) - "In Angular, a Controller is a JavaScript constructor function that is used to augment the Angular Scope.
When a Controller is attached to the DOM via the ng-controller directive, Angular will instantiate a new Controller object, using the specified Controller's constructor function. A new child scope will be available as an injectable parameter to the Controller's constructor function as $scope."