I've created a modular structure for my Angular application.
The main idea is to have a folder of modules which may be reusable later by simple copying them to the new project. With help of Gulp I created a tasks which iterates over each folder in modules and makes a final build.
Here is my source and build
I would appreciate if you could point my weak parts and suggest how I may optimize my code to footer-proof its logic and maintainability.
Here is my angular.app:
var app = angular.module('store', [
'ngRoute',
'catalog',
'store-gallery',
'store-panel',
'contact',
'scopeTest',
'cart'
]);
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider
// Home
.when("/", {templateUrl: "layout/home.html", controller: "PageCtrl"})
// main page modules
.when("/catalog", {templateUrl: "layout/catalog.html" })
.when("/contact", {templateUrl: "layout/contact.html" })
.when("/cart", {templateUrl: "layout/cart.html" })
.when("/test", {templateUrl: "layout/test.html" })
// else 404
.otherwise("/404", {templateUrl: "layout/404.html" })
}]);
app.controller('PageCtrl', function (/* $scope, $location, $http */) {
console.log("Page Controller reporting on duty.");
});
app.service('productService', function() {
var productList = [];
var addProduct = function(obj) {
productList.push(obj);
};
// TODO create a callback func
var getProducts = function(){
return productList;
};
return {
addProduct: addProduct,
getProducts: getProducts
};
});
app.factory('getProductsJson', ['$http', function ($http) {
return $http.get('products.json');
}]);
(function () {
var app = angular.module('cart', []);
app.controller('CartCtrl', function ($scope, productService) {
$scope.products = productService.getProducts();
this.products = $scope.products;
this.qty = 1;
console.log(this.products.length);
});
}());
(function () {
var app = angular.module('catalog', []);
app.controller('CatalogController', function (getProductsJson) {
var store = this;
store.products = [];
getProductsJson.success(function (data) {
store.products = data;
});
});
}());
(function () {
angular.module('contact', [])
.controller('ContactCtrl', function () {
// Activates Tooltips for Social Links
$('.tooltip-social').tooltip({
selector: "a[data-toggle=tooltip]"
});
});
}());
angular.module('scopeTest', [])
.controller('FirstCtrl', function () {
}).controller('SecondCtrl', function () {
});
(function () {
var app = angular.module('store-gallery', []);
app.directive('productGallery', function () {
return{
restrict: 'A',
templateUrl: 'layout/product-gallery.html',
controller: function () {
this.pic = 1;
this.setPic = function(pic){
if (pic !== null) {
this.pic = pic;
} else {
this.pic = 0;
}
};
},
controllerAs: 'gallery'
};
});
}());
(function(){
var app = angular.module('store-panel', []);
app.controller('ProductController', function($scope, productService) {
this.sendToCart = function(product){
var productNew = product;
var alreadyInCart = productService.getProducts();
var existInCart = jQuery.inArray(productNew, alreadyInCart);
function checkExist() {
if (existInCart === -1 ){
productService.addProduct(productNew);
}
}
checkExist();
console.log(alreadyInCart);
};
});
app.directive('productPanel', function () {
return{
restrict: 'A',
templateUrl: 'layout/product-panel.html',
controller: function () {
this.tab = 1;
this.selectTab = function(setTab) {
this.tab = setTab;
};
this.isSet = function (checkTab) {
return this.tab === checkTab;
};
},
controllerAs: 'panel'
};
});
app.directive('productDescription', function(){
return {
restrict: 'E',
templateUrl: 'layout/product-description.html'
};
});
app.directive('productSpecs', function () {
return{
restrict: 'E',
templateUrl: 'layout/product-specs.html'
};
});
app.directive('productReview', function () {
return{
restrict: 'E',
templateUrl: 'layout/product-review.html',
controller: function () {
this.review = {};
this.addReview = function(product){
this.review.createdOn = Date.now();
product.reviews.push(this.review);
this.review = {};
};
},
controllerAs: 'reviewCtrl'
};
});
}());