Basic REST calls to WordPress V2 API with Angular.js - javascript

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/

Related

Return promise from service for locally stored data in angular

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);
}

Passing data from server to angular

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.

Get tweets using angularjs

I am trying to make an app with material design and angularjs to get the tweets using hashtag search.
getTweets: function(hashtag, since,$http) {
var cfg = {};
var paramSince = since ? '&since_id='+ since : '';
var queryUrl = 'https://api.twitter.com/1.1/search/tweets.json?q=%23'+hashtag+paramSince;
// var queryUrl = '/search?hashtag='+hashtag+paramSince;
var promise = $http.get(queryUrl, cfg).then(function (response) {
return response;
});
return promise;
}
This API returns error 215, Bad Authentication Data
Here is the full application
STEPS TO REPRODUCE:
(i) Click Add Account
(ii)Login
(iii) Click finish
$http is undefined. You injected $http service into your twitterApp.services factory, then you (try) redeclared it inside the returned function getTweets.
In this case there is no "magic", you call getTweets with two arguments, so $http becomes undefined. The solution is removing this parameter from getTweets and use $http as a closure.
UPDATE:
There's no error handling in the process, you have to reject the promise when error occurs. This way you can also see the error comes from the server.
http://plnkr.co/edit/Lbb6EvwsjuecmFn5Vchd?p=preview
As you can see on the console, when trying to get connected, the server returns an origin error:
Error: Origin "http://run.plnkr.co/Of0F9UHpjhrqkjdw/" does not match
any registered domain/url on oauth.io(…)
It's probably about settings in your server (in this case, oauth.io) in terms of CORS.

Parsing a JSONP file in AngularJS

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

angularjs promise not resolving properly

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.

Categories