I have my web application deployed to tomcat with an applicatio context.
For example my URL looks something like this.
http://localhost:8080/myapp
myapp - is the application context here.
Now in an Angular service if i want to call a webservice say getusers. My URL should be this /myapp/getusers. But I want to avoid hardcoding the application context as it might change from one deployment to other.
I have managed to figureout the contextpath from $window.location.pathname but it looks very stupid. Is there a betterway?
FYI I am using Spring MVC for restful services.
What I have done is declared a variable in the main jsp file. Then that variable will be available throughout the angular application.
<script type="text/javascript">
var _contextPath = "${pageContext.request.contextPath}";
</script>
This code should be written in header before including other JavaScript libraries.
I'm also using tomcat and Spring MVC. Using relative url in JavaScript will do the trick.
For doing this you just need to remove the / at the begining of REST url. so that your url starts from the current url in your browser.
replace $resource('/getusers') with $resource('getusers')
Inject the $location service to your controller.
var path = $location.path(); // will tell you the current path
path = path.substr(1).split('/'); // you still have to split to get the application context
// path() is also a setter
$location.path(path[0] + '/getusers');
// $location.path() === '/myapp/getusers'
// ------------------ \\
// Shorter way
$location.path($location.path() + '/getusers');
// $location.path() === '/myapp/getusers'
In Angular 2 (if using hashbang mode). Below code can be used to form the url.
document.location.href.substr(0, document.location.href.lastIndexOf("/#")) + "/getusers";
Inspired from the answer of #jarek-krochmalski
if you are using hashbang mode, with "#", you can do something like that:
$location.absUrl().substr(0, $location.absUrl().lastIndexOf("#")) + "/getusers"
For AngularJS $http service you are good to go with url : 'getusers', as follows:
$scope.postCall = function(obj) {
$http({
method : 'POST',
url : 'getusers',
dataType : 'json',
headers : {
'Content-Type' : 'application/json'
},
data : obj,
});
};
In general, you should use injection in your controller like the following:
angular.module("yourModule").controller("yourController", ["$scope", "yourService", "$location", function($scope, yourService, $location){
....
//here you can send the path value to your model.
yourService.setPath($location.path());
....
}]);
Related
[Update] there is a 50 point bonus, which I will up to 200 for a working fiddle
[Update] while I prefer an AngualrJs solution, I will also accept plain JS - just anything to get me over this impasse ... a GET call to my server returns a URL and I want to embed that document into my HTML
With reference to my previous question, #MaximShoustin 's answer seemed perfect, but I am having problems.
The URL in that solution there is hard coded, but I want to get mine by AJAX. When I do, the document is not embedded, but I see no error in the developer console.
I made this fiddle, where I added these lines
to the HTML
<iframe ng-src="{{cvUrlTrusted_2}}"></iframe>
and, to the controller
app.controller('Ctrl', function($scope, $sanitize, $sce, $http) {
added , $http
and
// new stuff follows
var url = 'http://fiddleapi.rf.gd/getDocuemntUrl.php';
/* The URL contains this code ...
<?php
echo('https://d9db56472fd41226d193-1e5e0d4b7948acaf6080b0dce0b35ed5.ssl.cf1.rackcdn.com/spectools/docs/wd-spectools-word-sample-04.doc');
?>
*/
$http.get(url)
.success(function(data, status, headers, config)
{
var cvTrustedUrl_2 = 'http://docs.google.com/gview?url=' + data.trim() + '&embedded=true';
$scope.cvTrustedUrl = $sce.trustAsResourceUrl(cvTrustedUrl_2);
})
.error(function(data, status, headers, config)
{
alert('Urk!');
});
If you invoke the API at http://fiddleapi.rf.gd/getDocuemntUrl.php you will see that it returns the same document URL as was hard coded in the solution.
Please, first check my code, lest I have made a mistake.
Long description, short question : how can I embed a document who's URL is returned from an AJAX API into an HTML document using AngularJS? Free free to fork the fiddle.
Your fiddle doesn't work because of cross domain problem: http://fiddleapi.rf.gd/getDocuemntUrl.php
So I loaded simple JSON file with content:
{
"val":"https://d9db56472fd41226d193-1e5e0d4b7948acaf6080b0dce0b35ed5.ssl.cf1.rackcdn.com/spectools/docs/wd-spectools-word-sample-04.doc"
}
and:
$http.get('data.json').then(function (resp){
var cvTrustedUrl_2 = 'http://docs.google.com/gview?url=' + resp.data.val + '&embedded=true';
$scope.cvUrlTrusted_2 = $sce.trustAsResourceUrl(cvTrustedUrl_2);
});
Demo Plunker
It works fine so the problem is in your http://fiddleapi.rf.gd/getDocuemntUrl.php because this URL doesn't work in Postman too. I get:
This site requires Javascript to work, please enable Javascript in your browser or use a browser with Javascript support
be sure you configured it well
Is it possible to access / modify $http interceptors after the config phase? I'm debugging an app that only breaks in production due to being deployed on a different server, so unfortunately I can't change the interceptor code locally and figure out what's going on.
If it's not possible to access / modify the interceptors, perhaps it'd be possible to replace $http. Here's an example of replacing a hypothetical service:
var inj = angular.element('body').injector(),
oldGet = inj.get,
mockService = { secret: 'shhh' };
inj.get = function(str) {
if (str === 'some-service') {
return mockService;
} else {
return oldGet.apply(inj, arguments);
}
};
However, I'm not sure how I'd go about creating a new $http service (into which I could pass in the modified interceptors). I can't grab the $httpProvider, either.
Perhaps bootstrapping a new ng-app on a separate part of the page would work? Then I could grab the $http service and replace it, like above.
Other ideas:
With reference to: Right way to disable/remove http interceptors in Angular? , it does not seem like I can access the interceptors array if I don't hold on to it in the config phase.
Perhaps I can use grease monkey to inject something that runs in the config phase.
Thank you!
XMLHttpRequest cannot load http://mywebservice. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access.
I get this error when I try to run my web-service from inside my code. I tried finding about it and tried many solutions which were suggested which I found on net. Pasting the code below.
<form name="LoginForm" ng-controller="LoginCtrl" ng-submit="init(username,password,country)">
<label>Country</label><input type="text" ng-model="country"/><br/><br/>
<label>UserName</label><input type="text" ng-model="username" /></br></br>
<label>Password</label><input type="password" ng-model="password">
</br>
<button type="submit" >Login</button>
</form>
And controller form the corresponding js is:
app.controller('LoginController', ['$http', '$scope', function ($scope, $http) {
$scope.login = function (credentials) {
$http.get('http://mywebservice').success(function ( data ) {
alert(data);
});
}
}]);
The web-service works fine when I hit it from URL bar. How to resolve the problem? Kindly help!
The Chrome Webstore has an extension that adds the 'Access-Control-Allow-Origin' header for you when there is an asynchronous call in the page that tries to access a different host than yours.
The name of the extension is: "Allow-Control-Allow-Origin: *" and this is the link: https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi
On the client side you can enable cors requests in AngularJS via
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
]);
However if this still returns an error, this would imply that the server that you are making the request has to allow CORS request and has to be configured for that.
This is a CORS issue. There are some settings you can change in angular - these are the ones I typically set in the Angular .config method (not all are related to CORS):
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.withCredentials = true;
delete $httpProvider.defaults.headers.common["X-Requested-With"];
$httpProvider.defaults.headers.common["Accept"] = "application/json";
$httpProvider.defaults.headers.common["Content-Type"] = "application/json";
You also need to configure your webservice - the details of this will depend on the server side language you are using. If you use a network monitoring tool you will see it sends an OPTIONS request initially. Your server needs to respond appropriately to allow the CORS request.
The reason it works in your brower is because it isn't make a cross-origin request - whereas your Angular code is.
I have a solution below and its works for me:
app.controller('LoginController', ['$http', '$scope', function ($scope, $http) {
$scope.login = function (credentials) {
$http({
method: 'jsonp',
url: 'http://mywebservice',
params: {
format: 'jsonp',
callback: 'JSON_CALLBACK'
}
}).then(function (response) {
alert(response.data);
});
}
}]);
in 'http://mywebservice' there must be need a callback parameter which return JSON_CALLBACK with data.
There is a sample example below which works perfect
$scope.url = "https://angularjs.org/greet.php";
$http({
method: 'jsonp',
url: $scope.url,
params: {
format: 'jsonp',
name: 'Super Hero',
callback: 'JSON_CALLBACK'
}
}).then(function (response) {
alert(response.data);
});
example output:
{"name":"Super Hero","salutation":"Apa khabar","greeting":"Apa khabar Super Hero!"}
I added this and it worked fine for me.
web.api
config.EnableCors();
Then you will call the model using cors:
In a controller you will add at the top for global scope or on each class. It's up to you.
[EnableCorsAttribute("http://localhost:51003/", "*", "*")]
Also, when your pushing this data to Angular it wants to see the .cshtml file being called as well, or it will push the data but not populate your view.
(function () {
"use strict";
angular.module('common.services',
['ngResource'])
.constant('appSettings',
{
serverPath: "http://localhost:51003/About"
});
}());
//Replace URL with the appropriate path from production server.
I hope this helps anyone out, it took me a while to understand Entity Framework, and why CORS is so useful.
In my case, I was trying to hit a WebAPI service on localhost from inside an MVC app that used a lot of Angular code. My WebAPI service worked fine with Fiddler via http://localhost/myservice. Once I took a moment to configure the MVC app to use IIS instead of IIS Express (a part of Visual Studio), it worked fine, without adding any CORS-related configuration to either area.
I got
No 'Access-Control-Allow-Origin' header is present
and the problem was with the URL I was providing. I was providing the URL without a route, e.g., https://misty-valley-1234.herokuapp.com/.
When I added a path it worked, e.g.,
https://misty-valley-1234.herokuapp.com/messages. With GET requests it worked either way but with POST responses it only worked with the added path.
Use this extension for chrome.
Allows to you request any site with ajax from any source. Adds to response 'Allow-Control-Allow-Origin: *' header
https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi/related
Replace get with jsonp:
$http.jsonp('http://mywebservice').success(function ( data ) {
alert(data);
});
}
It is a problem on the server side. You have to add your client address to your server exposed API. If you are using Spring frame work you can annotate #CrossOrgin from org.springframework.web.bind.annotation.CrossOrigin;
Eg : #CrossOrigin(origins = "http://localhost:8080")
If you are using chrome: try open chrome with the args to disable web security like you see here:
Disable same origin policy in Chrome
This is how it worked for me. For Windows users testing with Bracket and AngularJS
1) Go to your desktop
2) Right click on your desktop and look for "NEW" in the popup drop down dialog box and it will expand
3) Choose Shortcut
4) A dialog box will open
5) Click on Browse and look for Google Chrome.
6) Click Ok->Next->Finish and it will create the google shortcut on your desktop
7) Now Right Click on the Google Chrome icon you just created
8) Click properties
9) Enter this in the target path
"C:\Program Files\Google\Chrome\Application\chrome.exe" --args --disable-web-security
10) Save it
11) Double click on your newly created chrome shortcut and past your link in the address bar and it will work.
I'm making a mobile app using ionic (based on the AngularJS framework) where I want to display data from a RESTfull API. I'm pretty new to AngularJS so I'm not familiar with the best practices. I want to get data from this API but with a weeknumber parameters in the URL so I can get data from specific weeks. I have looked especially to the example of the AngularJS website.
This is what I have in my services:
var eventServices = angular.module('starter.services', ['ngResource']);
eventServices.factory('EventServiceAPI',['$resource',
function($resource) {
return $resource('http://localhost:8080/schedulingAPI/plannedevents?weeknumber=:weeknumber', {}, {
query: { method: 'GET', params:{weeknumber:'weeknumber'}, isArray: true}
});
}]);
This is what I have in my controller to get the API data:
$scope.events = EventServiceAPI.get({weeknumber: 7});
However, I still keep getting the error:
Error: [$resource:badcfg] object
When I use the full API URL in services and $scope.events = EventServiceAPI.query() in my controller, the full API-data is displayed without error.
I also don't get where to put the parameters; in the brackets after the resource URL or the params option in the query method.
Edit:
The output of http://localhost:8080/schedulingAPI/plannedevents?weeknumber=:weeknumber
[{"id":2985,"event":{"eventId":589,"subject":"Masterproef","year":2014,"weekNumber":7,"dayNumber":6,"startHour":8,"startMinute":10,"endHour":12,"endMinute":45,"startTime":"2014-02-14T07:10:00Z","endTime":"2014-02-14T11:45:00Z","classgroups":[{"id":8,"name":"4ELICTI"},{"id":4,"name":"4ENAU"},{"id":10,"name":"4ELICTE"},{"id":1,"name":"4CHB"},{"id":3,"name":"4ENEL"},{"id":9,"name":"4EMEM"},{"id":2,"name":"4CHC"},[]],"teacher":null},"rooms":[{"id":24,"abbr":"D015"}]},{"id":4021,"event":{"eventId":604,"subject":"Bedrijfsbeleid 2 hc","year":2014,"weekNumber":7,"dayNumber":6,"startHour":8,"startMinute":10,"endHour":9,"endMinute":35,"startTime":"2014-02-14T07:10:00Z","endTime":"2014-02-14T08:35:00Z","classgroups":[{"id":6,"name":"4ELICT"},[]],"teacher":null},"rooms":[{"id":44,"abbr":"G120"}]}]
Replace params:{weeknumber:'weeknumber'} with params:{weeknumber:'#weeknumber'}, notice the #.
If the parameter value is prefixed with # then the value of that
parameter is extracted from the data object (useful for non-GET
operations).
From angular documentation
And call your function with query:
$scope.events = EventServiceAPI.query({weeknumber: 7});
Actually, you can simplify your resource declaration like this:
eventServices.factory('EventServiceAPI',['$resource',
function($resource) {
return $resource('http://localhost:8080/schedulingAPI/plannedevents');
});
}]);
Angular will automatically append the query string for you
I am using angular with MVC4. I would like to call a MVC controller method from javascript using $http.get(). It requires a url (obviously). I would like this to be a relative path, but how do I write that? My controller is in Controllers/Api/ExampleController. I would like the path to resolve even if I move the javascript file into another location, meaning I would like the path to be relative to application root as opposed to the javascript file. I Have tried "~/Controllers/Api/ExampleControllerMethod" and "Controllers/Api/ExampleController/Method.
The $location service does provide information from the url. So, you could construct something to then make the host and port dynamic:
var url = $location.host() + '/Controllers/Api/ExampleControllerMethod';
From the documentation:
**url: http://www.example.com/base/path?a=b#h**
$location.protocol() = http
$location.host() = www.example.com
$location.port() = 80
$location.path() = /path
$location.search() = {"a":"b"}
$location.hash() = h
Thanks for the ideas but this kind of thing is what I was looking for:
Configure the WebApiConfig to add a route like so (should have it as default):
config.Routes.MapHttpRoute(
name: "ApiMethods",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
So now I can go $http.get('api/{controller}/{method}')
What worked for me was to provide the Url as "/ControllerName/Action" (instead of "ControllerName/Action")