first of all to note that I am a very new on AngularJS and I try to create my first app by using the reed.co.uk API, for this reason, please don't shut me .. !! :)
The current state of my application is very basic and consists of the following:
index.html
<!DOCTYPE html>
<html lang="en" ng-app="reed" class="no-js">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Reed Start Up App</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap-theme.min.css" />
<link rel="stylesheet" href="app.css">
<script src="bower_components/html5-boilerplate/js/vendor/modernizr-2.6.2.min.js"></script>
</head>
<body>
<div class="container">
<div ng-view></div>
</div>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="bower_components/angular-resource/angular-resource.min.js"></script>
<script src="bower_components/jquery/dist/jquery.min.js"></script>
<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="app.js"></script>
<script src="components/services/services.js"></script>
<script src="viewHome/home.js"></script>
</body>
</html>
app.js
'use strict';
// Declare app level module which depends on views, and components
angular.module('reed', ['ngRoute', 'reed.home', 'reedService'])
.config(['$routeProvider', function($routeProvider){
$routeProvider.otherwise(
{
redirectTo : '/'
}
);
}]);
home.js
'use strict';
angular.module('reed.home', ['ngRoute', 'reedService'])
.config(['$routeProvider', function($routeProvider){
$routeProvider.when(
'/', {templateUrl : 'viewHome/home.html', controller : 'HomeCtrl'}
);
}])
.controller('HomeCtrl',['$scope', 'Jobs', function($scope, jobs){
$scope.performSearch = function()
{
console.log(
jobs.query(
{
keywords : $scope.jobTitle
},
{
method : 'GET',
headers : {
username : '9f0ebf61-8795-49d7-a1d7-123456789123'
}
}
)
);
};}
]);
home.html
<div class="row">
<div class="col-sm-12">
<form role="form">
<div class="form-group">
<label form="job-title">
Job Title
</label>
<input ng-model="jobTitle" id="job-title" placeholder="Please enter your desired job title" class="form-control" type="text" />
</div>
<div>
<button type="submit" class="btn btn-default" ng-click="performSearch()">Submit</button>
</div>
</form>
</div>
</div>
services.js
'use strict';
var jobsServices = angular.module('reedService', ['ngResource']);
jobsServices.factory('Jobs', ['$resource', '$http', function($resource, $http){
return $resource(
'http://www.reed.co.uk/api/1.0/search',
{},
{
query : {
method : 'GET',
headers : {
username : '9f0ebf61-8795-49d7-a1d7-123456789123'
}
}
}
)
}]);
The Reed.co.uk API documentation says the following:
Important:
You will need to include your api key for all requests in a basic authentication http header as the username, leaving the password empty.
Based on the above message I try to set my API key as username on my request headers. When I try the above approach with API Request plugins on my Chrome, the request is ok. I get normally whatever I requesting with no issue.
In my AngularJS app, the problem is that while I send a GET request, the AngularJS changing my request method to OPTIONS when I set my headers.
If I remove the headers, then the request performed with GET, but ofcourse I get Unothorized request error from the server.
Can somebody help me please ?
Question is not angular specific. Answer here is pretty good:
The OPTIONS request what you see is the preflight request, you can read about that here:
https://developer.mozilla.org/En/HTTP_access_control
http://www.w3.org/TR/cors/
http://msdn.microsoft.com/en-us/library/cc288060(VS.85).aspx
It's there because you're requesting a cross-domain XMLHttpRequest so the browser has to check whether your request is allowed on the remote server or not.
There are two solutions to solve the problem (as mentioned above):
implement the response for the OPTIONS request with the corresponding Access-Control-* headers
use a JSONP request instead of simple JSON
Related
I'm building an app with an Express/Node backend and Angular JS for the front end. Kinda new to using this stack and I'm having a hard time receiving the data in an Angular Service + Controller
Backend: Users can authenticate with Facebook using Passport JS that attaches a users object to every request. I opened up an endpoint that checks if req.user exists, like so:
app.get('/checklogin', function(req,res,next){
if(req.user){
console.log("we found a user!!!");
console.log("name:" + req.user.displayName);
console.log("user id" + req.user.id);
return res.status(201).json(req.user);
} else {
console.log("there is no user logged in");
}
});
If the req.user exists, so the user is authenticated, it sends a JSON response.
What I'm trying to do is in Angular is sending a http.get to this /checklogin endpoint and handle the response. I want to bind to the scope if the user is authenticated (req.user exists or not), and if so bind displayName and Id as well, and hide show nav links and pages.
But my setup in Angular hits the API endpoint but doesnt seem to receive any data????:
.service("Login", function($http){
this.isLoggedIn = function(){
return $http.get("/checklogin")
.then(function(response){
console.log(response)
return response;
}, function(response){
console.log("failed to check login");
});
};
})
.controller("mainController", function($scope, Login){
Login.isLoggedIn()
.then(function(doc){
console.log(doc);
console.log(doc.data);
}, function(response){
alert(response);
});
})
the console.log(doc) and console.log(doc.data) don't log anything...... What am I doing wrong here?????
More info: the mainController is loaded in the index.html file:
<html lang="en" ng-app="myApp" ng-controller="mainController">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--load jQuery-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<!--load Bootstrap JS-->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<!--load Angular JS-->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-route.js"></script>
<!--latest compiled and minified Bootstap CSS-->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<!--link custom CSS file-->
<link rel="stylesheet" type="text/css" href="/css/style.css">
<script src="/js/app.js"></script>
</head>
<body>
<!-- NAVBAR ================== ---->
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
<div class="nav-header">
<a class="navbar-brand" href="#/">Votely</a>
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav navbar-right">
<li class="active">Home</li>
<li>Sign in with Facebook</li>
<li>Sign Out</li>
</ul>
</div>
</div>
</nav>
<!-- Dynamically render templates Angular JS -->
<div class="container" ng-view>
</div>
</body>
Any help much appreciated, thanks!
You should return a promise from service if you are using then inside controller i.e.
.service("Login", function($http){
this.isLoggedIn = function(){
return $http.get("/checklogin");
};
.isLoggedIn function in your service should looks like this:
this.isLoggedIn = function(){
return $http.get("/checklogin");
}
thanks, I got it working now. I was using the browser in Cloud 9 IDE and the server was sending a 503 response, not sure why. It works now in Chrome and Firefox etc. after I set the service to return a promise!
AngularJS is new to me (and difficult). So I would like to learn how to debug.
Currently I'm following a course and messed something up. Would like to know how to interpret the console error and solve the bug.
plnkr.co code
index.html
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="MainController">
<h1>{{message}}</h1>
{{ username }}
<form action="searchUser" ng-submit="search(username)">
<input type="search"
required placeholder="Username to find"
ng-model="username"/>
<input type="submit" value="search">
</form>
<div>
<p>Username found: {{user.name + error}}</p>
<img ng-src="http://www.gravatar.com/avatar/{{user.gravatar_id}}" title="{{user.name}}"/>
</div>
</body>
</html>
script.js
(function() {
var app = angular.module("githubViewer", []);
var MainController = function($scope, $http) {
var onUserComplete = function(response) {
$scope.user = response.data;
};
var onError = function(reason) {
$scope.error = "could not fetch data";
};
$scope.search = function(username) {
$http.get("https://api.github.com/users/" + username)
.then(onUserComplete, onError);
};
$scope.username = "angular";
$scope.message = "GitHub Viewer"; };
app.controller("MainController", MainController);
}());
The console only says
searchUser:1 GET http://run.plnkr.co/lZX5It1qGRq2JGHL/searchUser? 404
(Not Found)
Any help would be appreciated.
In your form, action you have written this
<form action="searchUser"
What this does is it will try to submit to a url with currentHostName\searchUser, so in this case your are testing on plunker hence the plunker url.
You can change the url where the form is submitted. Incase you want to search ajax wise then you dont even need to specify the action part. You can let your service/factory make that call for you.
Though not exactly related to debugging this particular error, there is a chrome extension "ng-inspector" which is very useful for angularJS newbies. You can view the value each of your angular variable scopewise and their value. Hope it helps!
Here is the link of the chrome extension: https://chrome.google.com/webstore/detail/ng-inspector-for-angularj/aadgmnobpdmgmigaicncghmmoeflnamj?hl=en
Since you are using ng-submit page is being redirected before the response arrives and you provided any action URL as searchUser which is not a state or any html file so it being used to unknown address, it is async call so it will take some time you can use input types as button instead of submit.
Here is the working plunker.
<!DOCTYPE html>
<html ng-app="githubViewer">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="MainController">
<h1>{{message}}</h1>
{{ username }}
<form >
<input type="search"
required placeholder="Username to find"
ng-model="username"/>
<input type="button" ng-click="search(username)" value="search">
</form>
<div>
<p>Username found: {{user.name + error}} {{user}}</p>
<img ng-src="http://www.gravatar.com/avatar/{{user.gravatar_id}}" title="{{user.name}}"/>
</div>
</body>
</html>
I am trying to load templates in angular but get an error:
Failed to load resource: net::ERR_FILE_NOT_FOUND angular.js:102 Error:
[$compile:tpload]
http://errors.angularjs.org/1.3.15/$compile/tpload?p0=pages%2Fhome.html
at Error (native)
at file:///C:/Users/Abu-Mustaqiima/Documents/AngularJS/WeatherApp/Video1/Starter/angular.js:6:417
at file:///C:/Users/Abu-Mustaqiima/Documents/AngularJS/WeatherApp/Video1/Starter/angular.js:137:25
at file:///C:/Users/Abu-Mustaqiima/Documents/AngularJS/WeatherApp/Video1/Starter/angular.js:112:113
at n.$eval (file:///C:/Users/Abu-Mustaqiima/Documents/AngularJS/WeatherApp/Video1/Starter/angular.js:126:15)
at n.$digest (file:///C:/Users/Abu-Mustaqiima/Documents/AngularJS/WeatherApp/Video1/Starter/angular.js:123:106)
at n.$apply (file:///C:/Users/Abu-Mustaqiima/Documents/AngularJS/WeatherApp/Video1/Starter/angular.js:126:293)
at l (file:///C:/Users/Abu-Mustaqiima/Documents/AngularJS/WeatherApp/Video1/Starter/angular.js:81:240)
at M (file:///C:/Users/Abu-Mustaqiima/Documents/AngularJS/WeatherApp/Video1/Starter/angular.js:85:342)
at XMLHttpRequest.e (file:///C:/Users/Abu-Mustaqiima/Documents/AngularJS/WeatherApp/Video1/Starter/angular.js:86:418)
Here's my index.html
<!DOCTYPE html>
<html lang="en-us" ng-app="weatherApp">
<head>
<title>AngularJS Weather Forecast SPA</title>
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta charset="UTF-8">
<!-- load bootstrap and fontawesome via CDN -->
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<style>
html, body, input, select, textarea
{
font-size: 1.05em !important;
}
</style>
<!-- load angular via CDN -->
<script src="http://code.angularjs.org/1.3.0-rc.2/angular.min.js"></script>
<script src="http://code.angularjs.org/1.3.0-rc.2/angular-route.min.js"></script>
<script src="http://code.angularjs.org/1.3.0-rc.2/angular-resource.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<header>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/">AngularJS Weather</a>
</div>
<ul class="nav navbar-nav navbar-right">
<li><i class="fa fa-home"></i> Home</li>
</ul>
</div>
</nav>
</header>
<div class="container">
<div ng-view></div>
</div>
</body>
</html>
// MODULE
var weatherApp = angular.module('weatherApp', ['ngRoute', 'ngResource']);
// ROUTES
weatherApp.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'pages/home.htm',
controller: 'homeController'
})
.when('/forecast', {
templateUrl: 'pages/forecast.htm',
controller: 'forecastController'
})
});
// CONTROLLERS
weatherApp.controller('homeController', ['$scope', function($scope) {
}]);
weatherApp.controller('forecastController', ['$scope', function($scope) {
}]);
I tried to use WAMP server to load the pages from, but still get the same error.
Currently your template protocol contains file:// which would not accessible through your browser.
You need to host your code on some server(like IIS, WAMP, etc.) & paste your whole code directory on the server, in order to work your code. Other wise your code looks fine.
So the URL should be either http:// or https:// then your template will fetch from server directly.
Use https or http in URL .Example:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
I'm using angular-file-upload.js and uploading an image. When the upload is successful, it returns a URL to where the image is hosted, which is hosted as a blob on Azure.
The upload is successful, and the URL is returned correctly, however when I push this URL on an "images" stack to view this image in the browser, it won't work properly. For example, the URL I get back looks like this:
"https://searlesmedia.blob.core.windows.net/event-images/4_slide-archive.jpg"
Controller.js
uploader.onSuccessItem = function (fileItem, response, status, headers) {
console.info('onSuccessItem', fileItem, response, status, headers);
$scope.uploadcomplete = "Upload Successful";
var url = $sce.trustAsResourceUrl(response);
$scope.images.push(url);
};
Html
<div class="row" data-ng-repeat="image in images">
<img ng-src="{{image}}" class="img-responsive" />
</div>
Hi it looks like you miss something please see here: http://plnkr.co/edit/1PpscI4dOMYpYRf6fbUS?p=preview
angular.module('mySceApp', ['ngSanitize'])
.controller('AppController', ['$http', '$scope', '$sce',
function($http, $scope, $sce) {
$scope.image = {};
$http.get("test_data.json").success(function(data) {
console.log(data.url);
// $scope.userComments = userComments;
$scope.image.url = $sce.trustAsResourceUrl(data.url);
});
}
]);
HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-example64-production</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.16/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.16/angular-sanitize.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="mySceApp">
<div ng-controller="AppController as myCtrl">
<div class="well">
<b>{{userComments.name}}</b>:
<img ng-src="{{image.url}}">
<br>
</div>
</div>
</body>
</html>
This issue is most likely due to my naivity as I am just beginning to teach myself JS and AngularJS in parallel. I have put together a simple example of what I am seeing in this plunker. Basically, my app handles an ng-repeat correctly, but as soon as I add the config method it does not replace {{menuItem.itemName}} with the value of the variable. Now, my config method is currently empty, so that may be the problem. But, I assumed I could just have a no-op method and add routes as I went, testing each one.
Here is my HTML:
<html ng-app="site">
<head>
<script src = https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.5/angular.min.js></script>
<script src ="script.js"></script>
<link href="http://fonts.googleapis.com/css?family=Great+Vibes" rel="stylesheet" type="text/css">
<title>Site</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body ng-controller='mainCtrl'>
<div id="main-container">
<div id="header">Site
</div>
<div id="side-bar">
<ul id="side-bar-menu">
<li ng-repeat="menuItem in menuItems"><span class="underline"><a ng-href={{menuItem.itemLink}}>{{menuItem.itemName}}</a></span></li>
</ul>
</div>
</div>
</body>
</html>
JS:
'use strict';
angular.module('site',[]).
controller('mainCtrl', ['$scope', function($scope) {
$scope.menuItems = [{
itemName: "Home",
itemLink: "#Home"
}];
}]);
//enabling the config breaks the output (and of course ;
//above needs to be replaced with . when config enabled)
/*config(['$routeProvider', function($routeProvider) {}]);*/