I am loading JSON file from S3. File is loading successfully but problem is, I cannot access AnglarJS modules($scope, services and etc) in my callback function because it is written outside angularJS. Is there a way to access $scope in my callback?
AngularJS code
var url = "http://my_s3_url/abc/v1/klm/my.json"
$http.jsonp(url);
my.json
jsonp_callback({name:"xyz",age:2})
callback
<script>
function jsonp_callback(data) {
console.log(data.name);
// cannot access $scope here :(
}
</script>
Hmm you are using $http so I guess angular is generally available.
Is there a way to access $scope in my callback?
If the script block is within the same document, then any scope is accessible by doing i.e. angular.element('body').scope().
<script>
function jsonp_callback(data) {
console.log(data.name);
// access $scope here :)
var scope = angular.element('body').scope();
scope.$apply(function() {
scope.lastResult = data;
});
}
</script>
Element body is used only as an example. It might be adapted for any DOM element related to the target scope.
You shouldn't have to write the callback function yourself. It should be enough to use the special "success" method from the resulting promise from the $http.jsonp call. If the following code is in the controller, you should still have access to the $scope variable.
$http.jsonp(url).
success(function(data, status, headers, config) {
// The data is here
}).
Edit I've realised this answer depends on there being a string JSON_CALLBACK in the url passed to $http.jsonp, which I suspect Angular replaces with some unique callback function it's defined. The server must then interpret this, and output JSON wrapped in a call to this function. This might not work on S3, which just serves static files.
Use the $q promise library to pass the data back to the scope
In the director.js
function eventReturn($http, $q){
return {
getEvent: function(){
var deferred = $q.defer();
$http({method:'GET', url'http://my_s3_url/abc/v1/klm/my.json'}).
success(function(data, status, headers, config){
deferred.resolve(data);
});
return deferred.promise;
}
}
};
and in the controller.js
$scope.event = eventReturn.getEvent();
I have created the plunker for your scenario, its like when page loads it will read the json file from $http and then call the external js file function,to that function it will pass the $scope and result data, that external function take the result and display by using scope.
url : http://plnkr.co/edit/k66KevvcIyxiKA5QSBAc?p=preview
hope this is what ur looking.
I use the AWS javascript lib and had to use apply:
AWS.config.update({accessKeyId: '?', secretAccessKey: '?'});
var s3 = new AWS.S3({ maxRetries: 5});
console.log("S3 correctly configured");
s3.listObjects( {Bucket : 'bucketName', Prefix : 'foo/bar/' }, function (err, data) {
if (err) {
console.log(err); // an error occurred
} else {
console.log(data); // successful response
sc.$apply(function() {
sc.prefix = data.Prefix;
sc.data = data;
});
}
});
Related
I have some config data for my app that is stored on my API server (form.io in this case), and since it will be rarely changed, I want to store it in localStorage and then update it as needed. So in my getStationConfig service, I check for the data in localStorage, and if it's not there, get it from the API and store it locally for next time.
The issue is returning the data from localStorage in a promise so my controller code that is expecting a promise can handle it. The code to get the data from my controller is this:
var stationPromise = shiftService.getStationConfig().then(function(data) {
vm.configSlots = data;
});
and my service looks like this:
var getStationConfig = function() {
// First check to see if info is stored locally.
var config = JSON.parse(localStorage.getItem('cfdConfig'));
if (config) {
return config;
}
// Get position info from appropriate Config resource submission.
// Code borrowed from ngFormioHelper.FormioAuth.
var token = localStorage.getItem('formioToken');
var config = {
disableJWT: true,
headers: {
"x-jwt-token": token
}
};
return $http.get(Formio.getAppUrl() + '/config/submission', config)
.then(function(result) {
// Code goes here to format the data for return to the controller
// Now that it's all formatted, store the info in localstorage so that it can be retrieved from there
// later and we don't have to keep hitting the API for it.
localStorage.setItem('cfdConfig', JSON.stringify(allSlots));
return allSlots;
},
function(err) {
console.log(err);
});
};
As is is written, the data that is returned from localStorage (the config var at the top) is in the same format as allSlots at the bottom, but it's not in a promise, so the controller doesn't like it. How can I wrap or return it so that it's in a promise? Do I need to just call localStorage via $http.get() (if that's possible)? Or another way?
Thanks.
Inject $q promise service into your service and use it to return the data wrapped in a promise
if (config) {
return $q.resolve(config);
}
I'm trying to get a basic query going with the new V2 API and Angular in WordPress 4.4.1. Perhaps someone can help me understand why the URL, /wp-json/wp/v2/posts, gives a JSON response with a 404.
Browsing to that URL gives me JSON like this:
{"code":"rest_no_route","message":"No route was found matching the URL and request method","data":{"status":404}}
And here is the JavaScript I'm using to make that .GET
var base = 'http://localhost:8888/recruitler';
var posts = '/wp-json/wp/v2/posts';
var user = '/wp-json/wp/v2/users/'; // append user id
var s = '/wp-json/wp/v2/posts?filter[s]='; // append search term
// basic HTTP call with Angular
var app = angular.module('app', ['ngRoute'])
app.factory('myService', function($http) {
var myService = {
async: function() {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get( base+posts ).then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
// Return the promise to the controller
return promise;
}
};
return myService;
});
app.controller('MainCtrl', function( myService, $scope ) {
// Call the async method and then do stuff with what is returned inside our own then function
myService.async().then(function(d) {
$scope.data = d;
});
});
UPDATE:
This must be a local environment issue. Live websites work just fine. I've tested and this issue persists on all my local WAMP and MAMP dev sites. Restarting the server and or checking this answer got it working.
the factory looks right, according to the rest-api docs you need pretty permalinks plugin as well in order to rest-api plugin use custom url rewrites https://wordpress.org/plugins/rest-api/installation/
Sorry, I'm a newbie at this
Let's say i have the following in node express
router.get('/:name', function(req, res, next) {
res.render("test", {test:req.test});
});
how to do I get the angular to pick up the test variable?
i tried doing in the html page
<div ng-controller='UserCtrl'>{{ data }}</div>
<script>
var test=!{JSON.stringify(test)};
</script>
then on the angular page
productApp.controller('UserCtrl',function UserCtrl($scope){
$scope.data=test;
});
the req.test looks like this
[
{
name: 'test'
}
]
the 'data' shows empty everytime.
thank you for your help
If you want Angular to talk to a server, the most common way is through an AJAX request. Angular has a whole service to help you with this communication.
https://docs.angularjs.org/api/ng/service/$http
The first example pretty much does exactly what you are looking for:
$http({
method: 'GET',
url: '/testName'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
It uses promises for the response. Just add your actions in the proper call back function and away you go.
You will need to use ajax call from an angular script or service in order to get the express js backend response.
You can create a service like below -
productApp.service("API", function($http){
this.callAPI = function(name){
return $http({
url : "localhost:3000/"+name,
data : "", // pass data if any here
method: "get"
});
};
});
Then you will need inject this service in your controller and call like below -
productApp.controller('UserCtrl',function UserCtrl($scope, API){
//$scope.data=test;
// call service api here
API.callAPI("some name").then(function(response){
$scope.data = response;
}, function(){
// error goes here
});
});
Also, you can change your express js app to send the JSON data as follows -
res.json({...}); // instead of res.render(..);
Inside your express res.json() is, in my opinion, the best option you have since any object passed to it will be converted to JSON other way you can do it like you've done but render is more suited to html where you have to render a nice little view for the client or there is some sort of manipulation involved before sending the JSON on the wire or the json is too big and you don't want to make you router file dirty and rather delegate that to a view file.. else res.json() is a very neat way to do it.
Modify your controller code like:
productApp.controller('UserCtrl',['$scope', '$http' , function($scope, $http){
$http.get('/test').then(
function(response){
$scope.data = test;
},
function(err){
console.error(err);
}); //'/test' <- this is the url;
//$scope.data=test;
}]);
and remove this from your code
<script>
var test=!{JSON.stringify(test)};
</script>
I would recommend doing an $http service call to receive this variable BUT if you truly want this variable/data rendered directly in to the page and available in the controller, you should consider doing the following:
In the rendered/returned HTML:
<head>
...
<script>
angular.module('myAppConfig', [])
.value('MyTestConfig', !{JSON.stringify(test)});
</script>
</head>
<body ng-app="myApp">
...
<div ng-controller='UserCtrl'>{{ data }}</div>
...
</body>
This will setup an injectable configuration value called 'MyTestConfig'. Ideally, this should be part of a bigger object or service so you could do things like Config.apiPath or Config.getStaticResource('my-resource.png')
Your controller will now look like this:
productApp.controller('UserCtrl', function UserCtrl($scope, MyTestConfig){
$scope.data = MyTestConfig;
});
and your original modal definition will look something like this:
angular.module('myApp', ['myAppConfig']);
You may need to shuffle around where the script tag is depending on how you have configured your views. This will also only work before injection has been finalized, aka, this will not work for partials.
I'm new to Angular and also relatively new to the JSONP format. In my code, I set up a factory to read in the JSONP file - and I get back the data variable as the JSONP data properly
$http.get('someJSONFile').success(function(data){
console.log(data);
});
The console log gives me back the following:
states([{"code":"AL","name":"Alabama"},{"code":"AK","name":"Alaska"},{"code":"AZ","name":"Arizona"},{"code":"AR","name":"Arkansas"},{"code":"CA","name":"California"},{"code":"CO","name":"Colorado"},{"code":"CT","name":"Connecticut"},{"code":"DE","name":"Delaware"}])
So - I'm stuck on what to do now. I have a data object that contains a function. I need to parse out the JSON from this function - but not sure how to do it.
I have read in other places that I need to declare a function somewhere in my controller or factory called
function states(results)
{
// what is in results should be the JSON data I crave
}
But even if I do that, I don't think it ever executes - so I am not sure what I should do at that point to get the JSON data into an object that I can use.
The full file I am trying to parse is http://massachusettswebdesigns.com/states.json
Any help is appreciated!
Angular $http service provides a method to consume JSONP endpoints. In your case this should work:
$http.jsonp('someJSONFile').then(function(data) {
console.log(data)
});
Behind the scene, Angular will create a globally accessible function that will receive data, parse and pass further, so you don't need to worry about creating functions yourself.
What looks like your trying to do is standard JSON not JSONP, JSONP will require a callback and is only required if getting data from a different domain, ie a API service
Also the console log output you give is not valid JSON.
//init app
var app = angular.module('MyApp',[]);
//setup a factory for the data handling
app.factory("Data",function($http){
return {
getData:function(type){
return $http.get(type).
then(function(result) {
return result.data;
});
}
}
});
//in a controller 'call' the factory for the data
app.controller('main', function main($scope, Data) {
//other stuff
Data.getData('someJSONFile').then(function (data) {
$scope.jsonData = JSON.parse(data);
});
//other stuff
});
So my error was a stupid one. The JSON file was giving me the name of a custom callback I had to define. Once I did this, all worked. . . . here's the code
angular.module('locationApp')
.controller('MainCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.states = [];
$scope.cities = [];
// Function for the States callback on the JSON files provided
window.states = function (data)
{
$scope.states = data;
};
// Get the State JSON file.
$http.jsonp('http://locationinc-mapping-demo.herokuapp.com/states.json');
}]) // end of MainCtrl
My controller has all the required dependencies injected.
$scope.connect = function(url) {
var defer = $q.defer();
var promise = $http.get(url).then(function (response) {
$timeout(function(){
defer.resolve(response);
},10000);
defer.resolve(response);
$scope.$apply(); //$rootScope.$apply();
});
return defer.promise;
};
$scope.mymethod = function(){
$scope.globalMydata[];
console.log("before the http get");
$scope.connect("MY_URL").then(function(data) {
console.log("called!", data);
console.log("INSIDE the http get");
$scope.mydata = data;
//$scope.globalMydata.push(data);
});
console.log("after the http get ");
//do some processing of the returned data here
var dataHolder = $scope.mydata;
return calculatedValue;//value from procesing
}
When the code is executed "INSIDE the http get" is invoked as the last debug log. I get the results from the get call but since its returned later, I am unable to do any processing with it. This is the exactl reason why we promises right? I need the promised data to do some processing inside the controller.
Any issue in my promise implementation??
I'm not sure whether I get your question, but it looks like you've built a promise interseptor, but from your question it looks like you want just the regular promise behaviour. So I'll try that..
I'm not an angular expert but I do use $http promises a lot and here's how I do it.
I register the $http call as a service, like this:
app.service('ajax',function(host,$http){
this.post = function(api,data,cb){
$http.post(host + api,data).success(cb)
};
this.get = function(api,cb){
$http.get(host + api).success(cb)
}
});
host is a predefined module.value. I inject this service into every controller that needs to call http requests and operate them like this:
ajax.post('users', UserToken, function(data){
console.log('Users points: ' + data.points)
})
As I understand $http has promises built in, so there's no need for q and defere, it's all done at the background. ajax.post calls the service, which sends data to host + 'users', server-side looks for user by his token and return some data with one key by the name of points with a value of the users points. Client-side: upon successful reply from the server it proceeds to the cb function which then console logs the user points.
So I can do whatever modification I need to the promise inside that cb function, since it is not called before a successful reply from the server.
The success and error methods have a few more optional arguments, check them out here.