Introduction
Recently, I started doing some projects while learning Angularjs. I managed to create and deploy a webapi and a single page app into Windows Azure. I used SQL compact file to store my data, when I had some time, I also played with bootstrap CSS, then applied less CSS. This article is suitable for those ones who want to learn about Angularjs and quickly build something simple.
The project solution is too large to upload, so I left it in my Google drive.
Background
Angularjs is built on MVC concept. It has Views, Controllers and Models/ViewModels. View is the HTML template responsible for rendering content in a browser. Controller prepares the data and passes it to the view based on the user logic. Model/View Model is the bridge between Controller and View. Angularjs has the $Scope
which communicates to the View and Controller.
ASP.NET Web API is a framework that makes it easy to build HTTP services that reach a broad range of clients, including browsers and mobile devices. ASP.NET Web API is an ideal platform for building RESTful applications on the .NET Framework. As soon as web API receives the request, it will returns the data we specified in json format.
Using the Code
Let's get started. Firstly, I built a webapi which exposes the restful service. The data layer code is very straight forward.
- We use entity framework as ORM to retrieve the products from db file.
- Controller consumes Service while Service depends on a few Repositories. In the example, we only have one
ProductController
which consumes ShoppingService
.
- If we enter localhost/api/product, it hits method
IEnumerable<Product> Get()
.
WebAPI Controller
private readonly IShoppingService _service;
public ProductController(IShoppingService service)
{
this._service = service;
}
public IEnumerable<Product> Get()
{
var products = _service.GetAllProducts();
return products;
}
ShoppingService
public class ShoppingService: IShoppingService
{
private readonly IRepository<Category> _categoryRepository;
private readonly IRepository<Product> _productRepository;
private readonly IRepository<Image> _imageRepository;
public ShoppingService(IRepository<Category> categoryRepository,
IRepository<Product> productRepository, IRepository<Image> imageRepository)
{
this._categoryRepository = categoryRepository;
this._productRepository = productRepository;
this._imageRepository = imageRepository;
}
public List<Product> GetAllProducts()
{
return _productRepository.GetAll();
}
public List<Category> GetAllCategories()
{
return _categoryRepository.GetAll();
}
ProductRepository
public class ProductRepository : IRepository<Product>
{
private readonly DataContext _dbContext;
public ProductRepository(DataContext dbContext)
{
_dbContext = dbContext;
}
public List<Product> GetAll()
{
return _dbContext.Products.ToList();
}
Since we use sqlcompact file to store our data, we need to install SQL compact package from nuget, point the SQL connection to <add name="DefaultConnection" connectionString="Data Source =|DataDirectory|Tourism.sdf" providerName="System.Data.SqlServerCe.4.0" />
.
Then install SQL compact package from nuget, point the SQL connection to <add name="DefaultConnection" connectionString="Data Source =|DataDirectory|Tourism.sdf" providerName="System.Data.SqlServerCe.4.0" />
.
Now, we just finished writing web API to retrieve data from SQL compact file. we can test it by entering "http://angular-webapi.azurewebsites.net/api/product" in the browser, to see if we can get back the products back in json.
If the web API is working as expected, I now start creating the single page app, install angularjs packages.
productController.js
var App = angular.module('App', ['ngRoute']);
App.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'Pages/product.html',
controller: 'productController'
})
.when('/detail/:id', {
templateUrl: 'Pages/detail.html',
controller: 'detailController'
})
.when('/contact', {
templateUrl: 'Pages/contact.html',
controller: 'contactController'
});
});
App.controller('productController', function ($scope, $http) {
$http({
method: 'GET',
url: 'http://angular-webapi.azurewebsites.net/api/product'
})
.success(function (data) {
$scope.products = data;
});
});
App.controller('detailController', function ($scope, $http, $routeParams) {
$http({
method: 'GET',
url: 'http://angular-webapi.azurewebsites.net/api/product/' + $routeParams.id
})
.success(function (data) {
$scope.product = data;
});
});
App.controller('contactController', function ($scope) {
$scope.message = 'Contact us! JK. This is just a demo.';
});
- The JavaScript creates a module called
App
and a controller productController
.
- It also introduces a web route using Angular Route. It will choose the right page and controller based on the URL.
- Every controller has some methods. As soon as it is called, it will go and get the data and stick the data to the
$scope
for future use.
index.html
<body ng-app="App">
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle"
data-toggle="collapse"
data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a href="#/" title="SPA - TechFunda"
class="navbar-brand">SPA</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active">
<a href="#/">Home</a></li>
<li><a href="#/PD">Personal Details</a>
</li>
<li><a href="#/about">About us</a>
</li>
<li><a href="#/contact">Contact us</a>
</li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
<div id="divLoading" ng-show="loading"
style="font-size:50px;">
<div class="loading">
Loading .....
</div>
</div>
<div ng-view></div>
<hr />
</div>
</body>
- The
ng-app
value needs to be the same as what is defined in the js. It is the module name. var App = angular.module('App', ['ngRoute']);
product.html
<div ng-controller="productController">
<div ng-repeat="item in products"
class="col-sm-4 col-lg-4 col-md-4"
style="margin-bottom: 10px;">
<a href="#detail/{{item.Id}}"
style="text-decoration: none;">
<div class="thumbnail">
<img src="{{item.Images[0].Url}}"
style="height:250px;" alt="">
<div class="caption price-color" >
<h4 class="pull-right">${{item.Price}}</h4>
<h4>
{{item.Name}}
</h4>
</div>
<div class="caption description-color">
<p>{{item.Description}}</p>
</div>
<div class="caption description-color">
</div>
</div>
</a>
</div>
</div>
- Each child view has its own controller, and it is responsible for retrieving and rendering the data in the view.
- Directive
ng-repeat
is like a foreach
, which is responsible for looping through the products.
In order to get less CSS to work, in the HTML header, put the following:
<link href="./Content/my.less" rel="stylesheet/less" type="text/css" />(my own css file)
<script src="./Content/less.min.js" type="text/javascript"></script>(less js file)
You then can use your variable like this:
@light-red:#f05050;
.price-color
{
background-color:@light-red;
color:@white;
}