Passing Data to Controller using $http in AngularJS - angularjs

I'm creating a small contacts application in AngularJS and want to retrieve data by calling a web service.
I created two projects in VS (one Website for the angularJS code and one Web Application for the web service code). I put them both under the same Solution.
This is my index.html markup:
<body ng-app="app" ng-controller="controller" ng-cloak>
<div class="header" ng-bind="header"></div>
<div class="content">
<!-- This content will switch -->
<ui-view></ui-view>
</div>...
My contacts.html markup, which goes inside ui-view tag:
<ul>
<li ng-repeat="c in contacts" >...
In JS I created the following service:
// Contacts Service
app.service("getContacts", function ($http, $q) {
// web-service path
var ws = "http://localhost:65123/";
var getContact = function () {
//create defer object
var contactsPromise = $q.defer();
$http.get(ws + "api/Contact")
.then(function (res) { contactsPromise.resolve(res);
}, function (err) { contactsPromise.reject(err); });
return contactsPromise.promise;
};
return
{ getContact: getContact }
});
and the following index Controller:
//index(root) Controller
app.controller("controller", function ($scope,getContacts) {
$scope.contacts = getContacts.getContact().then(function(res){ $scope.contacts = res; });
});
In my Web Application I created a single Model:
public class Contact
{
public string name;
public string phone;
public string mail;
public string address;
public static List<Contact> getContacts() {
// TODO retrieve Contacts from DB
List<Contact> c = new List<Contact>();
c.Add(new Contact() { name="aaaa", phone="111", mail="aaaa#gmail.com",address="sdsd"});
c.Add(new Contact() { name = "bbbb", phone = "222", mail = "b#g.com", address = "sss" });
c.Add(new Contact() { name = "cc", phone = "444", mail = "a#l.com", address = "ggg" });
return c;
}
And its Controller:
namespace WebApplication1.Controllers
{
public class ContactController : ApiController
{
// GET: api/Contact
public List<Contact> Get()
{
return Contact.getContacts();
}
}
}
When I run the whole project (both Angular and WS) I get an ERR_CONNECTION_REFUSED error.
What could be the problem here? Is something wrong with my ajax call using $http?
P.S. I allowed CORS in my Web Application.

the "getContacts" added as a dependency will return only a promise and not the list you want. It should look like this:
//index(root) Controller
app.controller("controller", function ($scope,getContacts) {
getContacts.then(function(contacts){ $scope.contacts = contacts; });
});
I hope this is the answer you're looking for!

Related

Cannot use angular to call web api in cshtml

I have to add an AngularJs control to my cshtml file in a project but as I couldn't make it work I tried to create a simple test application, and now it seems that even this simple app (including only an app module and a controller) is not working!
app.js
(function() {
angular.module('testApp', []);
});
GetProductsCtrl.js
angular.module('testApp.controllers', []); //this is supposed to go in a separate file
angular.module('testApp.controllers')
.controller("GetProductsCtrl", function ($scope, $http) {
$scope.greetings = "hi";
$http({
method: 'GET',
url: "http://localhost:54327/api/products"
})
.success(function (data) {
$scope.products = data;
});
});
ProductsController.cs
public class ProductsController : ApiController
{//inside the web api project and running on http://localhost:54327/
Product[] products = new Product[]
{
new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
};
public IEnumerable<Product> GetAllProducts()
{
return products;
}
public IHttpActionResult GetProduct(int id)
{
var product = products.FirstOrDefault(p => p.Id == id);
if (product == null)
return NotFound();
return Ok(product);
}
}
usage
<script src="~/Scripts/angular/common/GetProductsCtrl.js"></script>
<div class="row" ng-app="testApp">
<div>
Here I want to add the control.
{{1+1}} #*even this is not evaluated by angular!(it was working)*#
<ul ng-controller="GetProductsCtrl">
<li ng-repeat="product in products">
{{product.Name}} : $ {{product.Price}}
</li>
</ul>
</div>
</div>
and finally bundle:
bundles.Add(new ScriptBundle("~/bundles/angular").Include(
"~/Scripts/angular.min.js",
"~/Scripts/angular/app.js"
));
What I can guess is that Bundle will try rename your $http provider.
So try .controller("GetProductsCtrl", ["$scope", "$http", function ($scope, $http){
}] instead.

Angular 1 + typescript: Populate html with data retrieved from api calls all at the same time

I am working on a messaging app in angular 1 with typescript that allows you to send any type of file. When the page loads I make api calls to retrieve the fileNames of the files already in the chat history.
Problem is, those api calls happen at different times so the html is populated with fileNames at different times causing this jumpy unclean look. How can I populate the html with data from the server at the same time?
//Controller
export class MessageController {
fileName: string;
mediaId: string;
constructor() {
this.init();
}
protected init() {
this.mediaId = "34567890"
this.service.getFileName(this.mediaId)
.then(data => {
// interpolated in html as messageController.fileName
this.fileName = data.fileName;
})
.catch(error => {
this.$log.error(error);
});
}
}
// Directive
export class MessageDirective implements ng.IDirective {
public restrict = 'E';
public scope = true;
public bindToController = {
};
public templateUrl = "someWhere;
public controllerAs = 'MessageController';
public controller = MessageController;
}
// Service
public getFileName(id: string): ng.IPromise<ContentItem> {
var deferred: ng.IDeferred<ContentItem> = this.$q.defer();
this.contentApiClient.get().one(id.toString()).get()
.then((contentItem: ContentItem) => {
deferred.resolve(contentItem);
})
.catch((error: any) => {
deferred.reject(error);
});
return deferred.promise;
}
<div class="td-fsMessage">
<p class="td-fsMessage-content-title">{{ messageController.fileName }}</p>
</div>

Linking user's contacts in firebase with md-contacts-chips

I am having difficulty getting my head around on how I could link my users contacts in Firebase with md-contacts-chips from https://material.angularjs.org/0.11.2/#/demo/material.components.chips
Basically, each registered user can add people they know via email to their contacts list. The users firebase structure is as follows:
firebase
-$uid1
contacts
$uid2 - userObject
$uid3 - userObject
-$uid2
contacts
$uid1 - userObject
$uid3 - userObject
-$uid3
contacts
$uid1 - userObject
$uid2 - userObject
etc..
Is it possible to ng-repeat a users contacts as an array of objects?
How should I configure the md-contacts-chip?
The example has a function called loadContacts() which has the contacts set.
How would I be able to set my user objects as contacts? The return object is contact and I would like to find a way for it to return the queried object.
function loadContacts() {
var contacts = [
'Marina Augustine',
'Oddr Sarno',
'Nick Giannopoulos',
'Narayana Garner',
'Anita Gros',
'Megan Smith',
'Tsvetko Metzger',
'Hector Simek',
'Some-guy withalongalastaname'
];
return contacts.map(function (c, index) {
var cParts = c.split(' ');
var contact = {
name: c,
email: cParts[0][0].toLowerCase() + '.' + cParts[1].toLowerCase() + '#example.com',
image: 'http://lorempixel.com/50/50/people?' + index
};
contact._lowername = contact.name.toLowerCase();
return contact;
});
}
Thanks
I'm by no means an expert, just a trial and error fanatic. That being said I did get this to work. I the issues is that "md-contact-chip" uses "push and splice" to adjust the array, and as firebase states that's a bad idea. If we had access to replace push with $add() or splice with $remove() this should work properly.
I was looking at the custom chips setup and it seems possible because you can call a function during the chip's add and remove, then with a custom chip template could maybe get the same look as the contact-chips.
Anyway here is what I did to get it working with md-contact-chips. Also I've adjusted this one to work with a list of items, not contacts, cause I wanted the picture for the items.
The key to it should be get your whole person obj, then set the ng-model="ctrl.person.contacts" inside the controller make sure to have an array created if person.contacts does not exist. "ctrl.person.contacts = ctrl.person.contacts || [];
Yes your are not properly updating the firebase object but you when you run
ctrl.person.$save() you are just completely updating the db.
Html
<div layout="column" ng-cloak>
<div>
<p>Items selected</p>
<pre>{{ctrl.item.installedItems}}</pre>
</div>
<input type="button" ng-click="ctrl.updateInstalledItems()" value='update'>
<md-content class="md-padding autocomplete" layout="column">
<md-contact-chips
ng-model="ctrl.item.installedItems"
md-contacts="ctrl.querySearch($query)"
md-contact-name="alseSn"
md-contact-image="image"
md-require-match="true"
md-highlight-flags="i"
filter-selected="ctrl.filterSelected"
placeholder="Select installed items">
</md-contact-chips>
</md-content>
</div>
Controller
app.controller('ItemChipCtrl', ['items', 'item', '$q', '$log',
function (items, item, $q, $log) {
var ctrl = this;
ctrl.items = items;
ctrl.item = item;
ctrl.item.installedItems = ctrl.item.installedItems || [];
ctrl.querySearch = querySearch;
ctrl.allItems = loadItems(ctrl.items);
ctrl.filterSelected = true;
ctrl.updateInstalledItems = function() {
$log.info('Update....')
$log.log(ctrl.installedItems);
ctrl.item.$save();
}
/**
* Search for contacts.
*/
function querySearch (query) {
var results = query ?
ctrl.allItems.filter(createFilterFor(query)) : [];
return results;
}
/**
* Create filter function for a query string
*/
function createFilterFor(query) {
var lowercaseQuery = angular.lowercase(query);
return function filterFn(item) {
return (item.alseSn.indexOf(lowercaseQuery) != -1);
};
}
function loadItems(items) {
/*var items = $scope.items */
return items.map(function (c, index) {
var item = {
alseSn: c.alseSn || c,
alseCard: c.alseCard,
installedOn: c.installedOn || null,
image: 'img/items/47/'+c.alseCard+'.jpg' || null
};
return item;
});
}
}
]);
route injections
.when('/settings/:alseSn', {
templateUrl: 'settings.html',
controller: 'ItemChipCtrl as ctrl',
resolve: {
auth: function($location, Auth){
return Auth.$requireAuth().then(function(auth) {
return auth;
},function(error){
$location.path('/login');
});
},
item: function($route, Items, Auth){
return Auth.$requireAuth().then(function(){
return Items.getItem($route.current.params.alseSn).$loaded();
});
},
items: function(Items, Auth){
return Auth.$requireAuth().then(function(){
return Items.all.$loaded();
});
}
}
})

Map AngularJS restAPI request via URL

Being new to angular I'm stocked to figure out how to call a web service which should be parsed and maped via URL, like if the URL is getting called directly to get listed request with the given params
what I mean let say I have
/api/products -- calling all products(this is the access point)
/api/products/?page=2&orderby=asc -- calls products with pagination and orderby and here is what's bothering me because the api is getting called via ajax and there is no URL mapping of the target
My Codes
Html markup
<div ng-controller="MainCtrl">
<div class="row">
<div class="col-lg-7 col-md-7 col-sm-7">
<pagination total-items="totalItems" num-pages="totalPages" ng-model="currentPage" ng-change="selectPage(currentPage)" max-size="5" class="pagination-sm" boundary-links="true"></pagination>
</div>
<div ng-repeat="product in products"></div>
</div>
</div>
contoller
//called when navigate to another page in the pagination
$scope.selectPage = function(page) {
$scope.filterCriteria.pageNumber = page;
$scope.fetchResult();
};
//The function that is responsible of fetching the result from the server and setting the grid to the new result
$scope.fetchResult = function() {
return api.items.search($scope.filterCriteria).then(function(data) {
$scope.products = data;
$scope.totalPages = data.total;
$scope.productsCount = data.TotalItems;
}, function() {
$scope.products = [];
$scope.totalPages = 0;
$scope.productsCount = 0;
});
};
Service
.factory('api', function(Restangular) {
//api call to
return {
products: function() {
return Restangular.all('products').getList();
},
product: function(id) {
Restangular.one("products", id ).get().then(function(c) {
return c;
});
},
update: function(id) {
Restangular.one("products", id).put().then(function(c) {
return c;
});
},
items: {
search: function(query) {
return Restangular.all('products').getList(query);
}
},
};
});
How do I create params URL and function of this make restAPI calls or what are the workarounds in this case
You can get at the search parameters with the $location service. So if a user goes to somedomain.com/products/?page=2&orderby=asc then $location.search() will equal {page: 2, orderby: 'asc'}.
So when your controller loads you just need to set the filterCriteria and fetch the results.
controller
var myCtrl = function($location, $scope) {
$scope.selectPage = function(page) {
...
};
$scope.fetchResult = function() {
...
};
$scope.filterCriteria = $location.search();
$scope.fetchResults();
}
First you need to create a restangular object by mentioning the base url. In your case it will be
// It will creat a url /api
var base = Restangular.all('api');
Now you can create multiple scenarios like if you want to get all products then it will be:
// /api/products/
base.getList('products')
.then(function(products) {
$scope.products= products
})
Now if you want to apply pagination as well as include orderBy param
$scope.products = base.getList("products", [{page: 2},{orderby:asc}]);

Workout on restful services for single page applications

I am just a beginner in Angularjs. I have been trying for consuming WebApi service by angularjs. I am following this
1: http://weblogs.asp.net/dwahlin/using-an-angularjs-factory-to-interact-with-a-restful-service documentation. It has been clearly documented about use of factories and services. I want to perform crud operations and I am following the same way but I am not even getting the methods called in the Api controller and how can I get the data to be listed in the view?
I have done this: My factory is defined in index.cshtml
In the Main view ie. Index.cshtml
#{
ViewBag.Title = "Index";
}
<style>
.container {
float: left;
width: 100%;
}
</style>
<script src="~/Scripts/angular.min.js"></script>
<h2>Practising Angular</h2>
List
Edit
<div ng-app="demoApp">
<div class="container">
<div ng-view=""></div>
</div>
</div>
<script>
var demoApp = angular.module('demoApp', []);
demoApp.config(function ($routeProvider) {
$routeProvider.when('/', { controller: 'SimpleController', templateUrl: 'Home/List' })
.when('/Edit', { controller: 'SimpleController', templateUrl: 'Home/Edit' })
.otherwise({ redirectTo: '/' });
});
demoApp.factory('dataFactory', ['$http', function ($http) {
var urlBase = '/api/Customer';
var dataFactory = {};
dataFactory.getCustomers = function () {
return $http.get(urlBase);
};
dataFactory.getCustomer = function (id) {
return $http.get(urlBase + '/' + id);
};
return dataFactory;
}]);
demoApp.controller('customersController', ['$scope', 'dataFactory', function ($scope, dataFactory) {
$scope.status;
$scope.customers;
getCustomers();
function getCustomers() {
dataFactory.getCustomers()
.success(function (custs) {
$scope.customers = custs;
})
.error(function (error) {
$scope.status = 'Unable to load customer data: ' + error.message;
});
}
}]);
</script>
I have this controller which runs by default as it is an MVC 4.0 project and "Home Controller" and "Index" is defined in the route.
namespace Routing_Angular.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
public ActionResult List()
{
return PartialView();
}
public ActionResult Edit()
{
return PartialView();
}
}
}
The List and Edit Action methods are returned as partialviews because they will act as views to render data in angular js.
So, this is what I have in both of the partial views..
List.cshtml
#{
ViewBag.Title = "List";
}
<h2>Listing the users in order </h2>
<div class="container">
Name: <input type="text" ng-model="filter.name" />
<ul>
<li ng-repeat="objCust in customers | filter:filter.name">{{objCust.name }}-{{objCust.city}}
</li>
</ul>
Customer Name:<br />
<input type="text" ng-model="newCustomer.name" /><br />
Customer city:<br />
<input type="text" ng-model="newCustomer.city" /><br />
<button ng-click="addCustomer()">Add customer</button>
</div>
Edit.cshtml
#{
ViewBag.Title = "Edit";
}
<h2>Edit the particular user. Things are under construction</h2>
<h2>Listing the users in order </h2>
<div class="container">
Name: <input type="text" ng-model="city" />
<ul>
<li ng-repeat="objCust in customers | filter:city">{{objCust.name }}-{{objCust.city}}
</li>
</ul>
</div>
This is the Api controller/Service that is being getting called from Factory in the index.cshtml. But none of the methods are getting called. How the data got from the factory objects will be shown in the View?
ApiController
namespace Routing_Angular.Controllers
{
public class CustomerController : ApiController
{
//
// GET: /Customer/
public HttpResponseMessage Get()
{
CustomerService ObjService = new CustomerService();
var Clients = ObjService.GetClients();
if (Clients.Count < 1) throw new HttpResponseException(HttpStatusCode.NotFound);
return Request.CreateResponse<IEnumerable<tblreferralService>>(HttpStatusCode.OK, Clients);
}
// GET api/customers/5
public HttpResponseMessage Get(int id)
{
CustomerService ObjService = new CustomerService();
var Client = ObjService.GetClient(id);
if (Client == null) throw new HttpResponseException(HttpStatusCode.NotFound);
return Request.CreateResponse<tblreferralService>(HttpStatusCode.OK, Client);
}
}
}
Below I am attaching the image for project structure. It is just a basic structure.

Resources