I'm very new to Angular and am try to make a simple "Hello World" webservice call to a simple Rest web service that I've verified returns "Hello World" when you hit it.
I have 3 alerts in the method. I see the "In method" alert and then don't see any of the other alerts. I've attached fiddler and the web service request is never made. I've got to be overlooking something basic here I would think....any ideas on what am I may be missing?
Fiddler shows that the web service call is successful and I can see the results from the Web Service I expect but using Chrome's developer tools shows me that the call to the service is being cancelled by something inside of Angular.
Thanks in advance to any help provided.
(function () {
var app = angular.module("loginApp", ['ngResource'])
.config(function ($httpProvider) {
// Enable CORS
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
});
app.controller('LoginController', function ($scope, $http) {
this.loginImage = "images/ActiveView_ContentMgm_140x40.png";
this.loginUser = function () {
var token = "";
var loginUrl = "http://ten1.com/services/rest/demoservice.svc/Login";
delete $http.defaults.headers.common['X-Requested-With'];
var result = $http({ method: 'GET', url: loginUrl, params: { userName: this.userName, passWord: this.passWord } })
.success(function (data, status) {
$scope.status = status;
$scope.data = data;
})
.error(function (data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
});
token = data.Token;
};
});
})();
UPDATE:
Right now I'm clicking the submit button on a login form and just attempting to get back a string so I can verify basic communication with the web service. My goal is to pass the username/password in and get a token back. Here's the form:
<form ng-submit="loginCtrl.loginUser()" novalidate>
<div class="form-group">
<label for="exampleInputEmail1">Username</label>
<input type="text" class="form-control" style="border-radius:0px" ng-model="loginCtrl.loginForm.userName" placeholder="Enter username">
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password </label>
<input type="password" class="form-control" style="border-radius:0px" ng-model="loginCtrl.loginForm.passWord" placeholder="Password">
</div>
<button type="submit" class="btn btn-sm btn-default">Log in</button>
Inject $scope and $http into your controller, not in your loginUser() function:
app.controller('LoginController', function ($scope, $http) {
I found that the service I was hitting was returning a "No 'Access-Control-Allow-Origin' " message which would allow the service to complete but would cause Angular to short circuit. I fixed this by adding an "Access-Control-Allow-Origin" to the Response header in the service.
Links:
Cross Origin Resource Sharing for c# WCF Restful web service hosted as Windows service
"Access-Control-Allow-Origin:*" has no influence in REST Web Service
Related
I am doing an online tutorial where they teach you to make a simple web-app using MEAN.The code below is for editing the given collection of JSON objects(Videos are JSON objects here)
The collection is at
/api/videos
So I have to click on a href="/#/video/{{video._id}} which takes me to form.html and I have the option of editing the 'title' and 'description' parameters of the JSON object.
What I can't seem to understand is:
a)Why is this (full code below in the question) required
var Videos = $resource('/api/videos/:id', { id: '#_id' },
{
update: { method: 'PUT' }
});
Since I am on href="/#/video/{{video._id}} can't I directly take the id from the URL
var Videos=$resource('api/videos)
Videos.get({ id: $routeParams.id }, function(video){
$scope.video = video;
});
b)Whait is the workflow(i.e when is the router.get() request exactly made and when is the router.put() request made)
According to me when I click on the save button the Controller makes a put request to the API but I can't figure out when the router.get() request is being made
I am trying to read up express and angular documentations but they don't seem to explain the workflow.
Could you also please tell me what should I read up to get a better understanding?
This is the form.html code
<h1>Add a Video</h1>
<form>
<div class="form-group">
<label>Title</label>
<input class="form-control" ng-model="video.title"></input>
</div>
<div>
<label>Description</label>
<textarea class="form-control" ng-model="video.description"></textarea>
</div>
<input type="button" class="btn btn-primary" value="Save" ng-click="save()"></input>
</form>
This is the controller code
app.controller('EditVideoCtrl', ['$scope', '$resource', '$location', '$routeParams',
function($scope, $resource, $location, $routeParams){
var Videos = $resource('/api/videos/:id', { id: '#_id' },
{
update: { method: 'PUT' }
});
Videos.get({ id: $routeParams.id }, function(video){
$scope.video = video;
});
$scope.save = function(){
Videos.update($scope.video, function(){
$location.path('/');
});
}
}]);
This is the API Endpoint Code
router.get('/:id', function(req,res){
var collection =db.get('videos');
collection.findOne({_id: req.params.id},function(err,video){
if(err) throw err;
res.json(video);
});
});
router.put('/:id', function(req, res){
var collection=db.get('videos');
collection.update({_id:req.params.id},
{title: req.body.title,
description: req.body.description
},
function (err,video)
{if (err) throw err;
res.json(video);
});
});
Well, according to AngularJS docs for $resouce, $resource is:
A factory which creates a resource object that lets you interact with
RESTful server-side data sources.
In other words is a shortcut for RESTful services operations. The code bellow creates an interface with an API endpoint to make REST operations more easy to do.
Once you have this:
var User = $resource('/user/:userId', {userId:'#id'});
Is much easier to do this:
User.get({userId:123}, function(user) {
user.abc = true;
user.$save();
});
Because RESTful is a standard, and $resource is the Angular's implementation of the consumption of API's in this standard. On his internals, is made an assynchronous request with the propper headers and method according to the operation you conigured and choosed.
I'am trying to make simple web application using TMDB api but I'm having trouble with some request.
I'am successfully connecting to its api and getting all needed data and displaying it nicely. Problem is when i load my Homepage which has poster_path of movie, i get all posters nicely and displayed but in chrome dev tools I can see there is one more extra request sent (not sent by me... at least not on purpose) and its failing and wracking my app.
Chrome displays following for bad request:
GET file:///C:/Users/Ivan/Documents/testProject/fmdb-fjume-movie-database/app/%7B%7BimageBaseUrl%7D%7D/%7B%7Bmovie.poster_path%7D%7D net::ERR_FILE_NOT_FOUND
Status: failed
Initiator: other
Here's my code for getting information and html:
Home view
<div class="well main-frame">
<h1>MY MOVIE DATABASE</h1>
<div class="row row-centered">
<div class="col-sm-2 col-centered" style="text-align:center;" ng-repeat="movie in movies | limitTo:2">
<img id="homeThumbnailImg" src="{{imageBaseUrl}}/{{movie.poster_path}}"></img>
{{movie.original_title}}
</div>
</div>
</div>
Home controller
'use strict';
angular.module('home', ['services'])
.controller('homeCtrl', ['$scope', '$q', 'api', 'globals', function($scope, $q, api, globals) {
$scope.imageBaseUrl = globals.getImageBaseUrl();
$scope.getData = function() {
$q.all([
api.discover('movie')
]).then(
function(data) {
$scope.movies = data[0].data.results;
//console.log(data[0].data.results);
},
function(reason) {
console.log(reason);
});
}
$scope.getData();
}]);
API
'use strict';
angular.module('services', [])
.constant('baseUrl', 'http://api.themoviedb.org/3/')
.constant('apiKey', 'myKey...')
.factory('api', function($http, apiKey, baseUrl) {
return {
discover: function(category) {
var url = baseUrl + 'discover/' + category + '?certification_country=US&certification.lte=G&sort_by=popularity.desc&api_key=' + apiKey;
return $http.get(url).success(function(data) {
return data;
});
},
search: function() {
},
...
Thank you all for your time!
You should change your img tag to look like this:
<img id="homeThumbnailImg" ng-src="{{imageBaseUrl}}/{{movie.poster_path}}"></img>
Note the ng-src attribute that replaces the src attribute. This will prevent the browser from trying to fetch the literal string {{imageBaseUrl}}/{{movie.poster_path}} before angular has a chance to eval that expression.
I have an HTML which looks like -
<div ng-controller="PostsCtrl">
<ul ng-repeat="post in posts" style="list-style: none;">
<li style="padding: 5px; background-color: #f5f5f5;">
<h4>
{{post.postTitle}}
</h4>
<div class="post-details" ng-show="showDetails">
<p>{{post.postContent}}</p>
</div>
</li>
</ul>
</div>
Now the data is being populated from a JSON based REST URL and being displayed. I also have a form that will be adding new post to the database-
<form data-ng-submit="submit()"
data-ng-controller="FormSubmitController">
<h3>Add Post</h3>
<p>
Title: <input type="text" data-ng-model="postTitle">
</p>
<p>
Content: <input type="text" data-ng-model="postContent">
</p>
<p>
Tags: <input name="postTags" data-ng-model="postTags" ng-list
required>
</p>
<input type="submit" id="submit" value="Submit" ng-click="loadPosts()" /><br>
</form>
I basically want to achieve two things -
1. As soon as i add new post it shows up in the list of posts above.
2. As soon as i manually add a new post in the backend, front end automatically updates.
Is it possible to achieve both using angular and if yes how will i be able to do that.
Below is my controller code, which as of now is showing me existing posts as well as letting me add new post to DB.
<script>
var app = angular.module("MyApp", []);
app.controller("PostsCtrl", function($scope, $http) {
$http.get('http://localhost:8080/MyApp/posts')
.success(function(data, status, headers, config) {
$scope.posts = data;
}).error(function(data, status, headers, config) {
console.log("Error in fetching the JSON data.");
});
$scope.$watch('posts', function(newVal, oldVal){
console.log('changed');
alert('hey, myVar has changed!');
}, true);
/*$scope.$watch('posts', function() {
alert('hey, myVar has changed!');
console.log("test log");
$scope.$digest();
});*/
});
app.controller('FormSubmitController', [ '$scope', '$http',
function($scope, $http) {
$scope.loadPosts = function() {
$http.get('http://localhost:8080/MyApp/posts')
.success(function(data, status, headers, config) {
$scope.posts = data;
alert(JSON.stringify(data));
//$scope.posts_updated = data;
}).
error(function(data, status, headers, config) {
console.log("Error in fetching the JSON data.");
});
}
$scope.list = [];
$scope.submit = function() {
var formData = {
"postTitle" : $scope.postTitle,
"postContent" : $scope.postContent,
"postTags" : $scope.postTags,
"postedBy" : "admin"
};
var response = $http.post('addPost', formData);
response.success(function(data, status, headers, config) {
console.log("na");
});
response.error(function(data, status, headers, config) {
alert("Exception details: " + JSON.stringify({
data : data
}));
});
//Empty list data after process
$scope.list = [];
};
} ]);
</script>
Any help on this will be really appreciable.
1: on your success of post, you can just push the added object into your posts list. This will trigger the two-way-binding, and the object will "automatically" appear in your ng-repeater.
$scope.posts.push(element);
2: This one is a bit tricky, since angular is a client-side application, it doesn't recognize what happens on the server-side. What you have to do to make this work is to look at websockets (like SignalR or similar) that can make a push to your client whenever something gets added. This also depends on that your "manual" insert is done using a programatically method. Doing it directly from database-changes is going to be alot more painfull
Initialize $scope.posts before invoking $http request
$scope.posts = [];
Since you are using $http service, it should automatically repaint ng-repeat when new data found. So you don't need be to worried about it
Very important thing is that you don't need to call $digest when you use $http service. Using $digest blindly is a very bad practice and is major performance issue. In the end of $http service angular automatically call $digest so you don't need to call again
My setup is NodeJS, MongoDB, and Angular. I'm currently trying to add POSTing capability to my test code but can't quite wrap my head around it. Currently I can pull data from the DB and I threw together a quick and dirty form/factory based on a number of examples I've seen to try to get the POST function working.
The problem I'm running into is actually getting the values to be added to the DB. When I submit the form, a new ObjectID is created in the DB with a "_v" field and a value of 0. So I know the POST is at least being sent to the DB, but the values I want are not. I'm sure I'm doing something stupid and any help is greatly appreciated.
Here is my controller/factory setup: (I named the POST factory "taco" so it would stand out. Also because they're delicious.)
angular.module('app', ['ngRoute'])
.factory('Users', ['$http', function($http) {
return $http.get('/users');
}])
.factory('taco', ['$http', function($http) {
return $http.post('/users');
}])
.controller('UserController', ['$scope', 'Users', function($scope, Users) {
Users.success(function(data) {
$scope.users = data;
}).error(function(data, error) {
console.log(error);
$scope.users = [];
});
}])
.controller('ExampleController', ['$scope', 'taco', function($scope, taco) {
$scope.submit = function() {
if ($scope.users.name) {
$scope.name.post(this.name);
$scope.name = '';
}
};
}]);
Here is my form:
<div>
<form ng-submit="submit()" ng-controller="ExampleController">
Enter the things:<br/>
<input type="text" ng-model="name" name="user.name" placeholder="name" /><br/>
<input type="text" ng-model="emp_id" name="user.emp_id" placeholder="EID" /><br/>
<input type="text" ng-model="loc" name="user.loc" placeholder="location" /><br/>
<input type="submit" id="submit" value="Submit" />
</form>
</div>
To post using the $http service you can do:
angular.module('myApp')
.controller('MyController', function($scope, $http) {
$http.post('/destination', {my: 'data'});
});
You're not sending any data in your POST request. The taco service just executes a $http.post call and returns the promise.
Please look at the $http service documents: https://docs.angularjs.org/api/ng/service/$http
I would define a function submit that would send the data once a user clicks on submit:
$scope.submit = function() {
$http.post('/destination', {my: 'data'});
}
I'm new to Angularjs and I'm trying to build a simple location finder widget. I have a service set up to contain the location data in a json block. Then I have a controller for the search form that makes a http call to get the json. Then I update the data in service. The service is also used in the location results controller to set the data for the directives on the front end. I've tried a bunch of different things and I'm not sure what I'm doing wrong. Thanks!
(function() { // start closure wrap
var app = angular.module('store_locator', []);
app.service('$store_location_data', function() {
var store_location_data = this;
store_location_data.data = [];
store_location_data.update_data = function(data) {
store_location_data.data = data;
}
});
app.controller('StoreLocatorFormControllor', [ '$http', '$store_location_data', function($http, $store_location_data) {
this.search_form = {};
this.searchLocations = function() {
$http.get('services/locations/').
success(function(data, status, headers, config) {
$store_location_data.update_data(data);
}).
error(function(data, status, headers, config) {
alert('fail');
});
this.search_form = {};
} // end form submit
}]);
app.controller('location_results', [ '$store_location_data', function($store_location_data) {
this.locations = $store_location_data.data;
}]);
})(); // end closure wrap
HTML:
<form name="storeLocatorForm" ng-controller="StoreLocatorFormControllor as storeLocFormCtrl" ng-submit="storeLocFormCtrl.searchLocations()">
<p>
<input ng-model="storeLocFormCtrl.search_form.zip_code" type="text" name="zip_code" value="" />
</p>
<p>
<select ng-model="storeLocFormCtrl.search_form.distance">
<option value="20">20</option>
<option value="40">40</option>
<option value="60">60</option>
</select>
</p>
<p><input type="submit" value="Submit" /></p>
</form>
<div ng-controller="location_results as results" ng-show="results.locations.length">
<div ng-repeat="location in results.locations">
<h1>{{ location.name }}</h1>
</div>
</div>
You are directly assigning service data at the time of loading controller.
You shouldn't do that because when you are assigning data from service the ajax call may just started or might not, but for sure it hasn't completed. So for that reason you service data is empty always.
I'd suggest you to use $broadcast, this will be useful in your case.
When you get the locations data inside your controller you will $broadcast event inside your controller, and that will listen by the controller whichever listing to that event using $on
StoreLocatorFormControllor
app.controller('StoreLocatorFormControllor', [ '$http', '$rootScope', '$store_location_data', function($http, $rootScope, $store_location_data) {
this.search_form = {};
this.searchLocations = function() {
$http.get('services/locations/').
success(function(data, status, headers, config) {
$store_location_data.update_data(data);
$rootScope.$broadcast('locationFetched');
}).
error(function(data, status, headers, config) {
alert('fail');
});
this.search_form = {};
} // end form submit
}]);
location_results
app.controller('location_results', [ '$store_location_data', function($store_location_data) {
//will call when locationFetched event gets broadcast
$rootScope.$on('locationFetched', function(event, data){
this.locations = $store_location_data.data;
});
}]);
Hope this will be helpful to you. Thanks.