I'm building a web app that is going to use an API to display cards when you hover over card text on the app.
I'm using unirest to make the call to the API on my node express server as follows -
unirest.get("https://omgvamp-hearthstone-v1.p.mashape.com/cards")
.header("X-Mashape-Key", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
.end(function (result) {
console.log(result.status, result.headers, result.body);
});
The data returns correctly and is displayed in my git bash console as JSON.
How do I use the Angular $get service to make a call against what node has just pulled? I guess my question is , where is this data pulled to once node gets a handle on it?
From what I understand, I would parse this information, but do I have to send this data to use it in my Angular.js file?
I hope I wrote enough information for an answer.
Thank you
If you want to pass the data to your UI, you need to make it accessible through an endpoint, so you could do something like this in your server (I'm using express for simplicity):
app.get('/my-data-endpoint', (req, res) => {
unirest.get("https://omgvamp-hearthstone-v1.p.mashape.com/cards")
.header("X-Mashape-Key", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
.end((result) => {
console.log(result.status, result.headers, result.body);
res.send(result);
});
});
and in your angular controller you can do:
$http.get('/my-data-endpoint')
.then((response) => {
console.log(response);
});
just remember to inject the $http dependency in your controller and you should be able to see the response.
Related
I have a working NodeJS API using Express. I am confused how to properly pass in a parameter from NodeJS to AngularJS in order to retrieve the data for the page.
Note: My question is an extension (not a repeat) of this question:
How do I pass node.js server variables into my angular/html view?
I have set up two routes, one to render the page and one to return the JSON object based on the Book ID (the unique ID of the entity). When the page loads, Angular uses $http to send a GET request to get the data from a JSON endpoint.
This is working, but I have hard-coded an example Book ID in Angular.
Question: How can I pass the Book ID to the Angular controller?
/*EXPRESS ROUTES*/
//Render page
router
.route('/detail/:book_id')
.get(ctrlRequest.detailPage);
//Return JSON data
router
.route('/detail/json/:book_id')
.get(ctrlRequest.detailJSON);
/*NODEJS CONTROLLERS*/
//Render page
module.exports.detailPage = function(req, res) {
res.render('transfer_request_detail.pug', {
title: 'Transfer Request Detail'
});
};
//Return JSON data
module.exports.detailJSON = function(req, res) {
getModel().read(req.params.book_id, (err, entity) => {
if (err) {
console.log('Request Detail JSON unable to return data results. Error message: ', err);
return;
} else {
res.json(entity);
}
});
};
/*ANGULAR WITH HARD-CODED BOOK ID*/
//QUESTION: HOW TO PASS THE BOOK ID IN DYNAMICALLY?
function DetailPageController($http) {
var vm = this;
$http({
url: '/detail/json/5761233819297931', //HARD-CODED ID HOW TO PASS IN DYNAMICALLY?
method: 'GET'
}).then(function (response){
vm.book = response.data;
console.log('API worked', response);
},function (error){
console.log('API error: ', error);
});
}
UPDATE:
"This probably depends on how your application is used. For example, the app might display a list of Books fetched from Express, and the user clicks one to see the detail page. In that case, the frontend fetches the complete list of Book ID's from Express. Can you please outline the behavior of your application?"
Use Case 1:
After the user submits a the New Book form, the Node app will redirect to the URL that renders the detail page. '/detail/:book_id'. I want to use Angular to build a datatable to display the details of the book that was created.
Use Case 2:
Another use case in the future will be to display all books that were created by the logged-in user. In this case, I want to use Angular to display all the books in a datatable. The route will be something like '/mybooks/:username'. Also, the user should also be able to click on a link that brings them to the details page (use case 1) for single book.
UPDATE 2:
I tried using routeParams to extract the ID out of the URL. It appears to be exactly what I need however it isn't working. Note that the routes were created on the server side with Express, not Angular.
$routeParams //Object
$routeParams.book_id //undefined
https://docs.angularjs.org/api/ngRoute/service/$routeParams
UPDATE 3:
I was able to solve this with a bit of a hacky workaround. I'm not super satisfied with this solution since it is quite hacky but at least it works for the time being.
I used this code in the Angular controller to extract the ID from the URL.
var relpath = $location.path().split('/');
var book_id = relpath[3];
UPDATE 4:
So it looks like I am back to square one. This solution broke the express routing. I am now having the same issue as described in this thread because locationProvider HTML mode is enabled to get this solution to work. Pages aren't loading when clicking on menu links, they are only loading when typed in directly.
Angular routing doesn't work when URL is directly visited in browser but works when clicked to?
You can use template literals: in your url string.
function DetailPageController($http, id = 5761233819297931) {
var vm = this;
$http({
url: `/detail/json/${id}`, //HARD-CODED ID HOW TO PASS IN DYNAMICALLY?
method: 'GET'
}).then(function (response){
vm.book = response.data;
console.log('API worked', response);
},function (error){
console.log('API error: ', error);
});
}
I know how to send an http request to a server using angular js. With the promise returned, I know how to listen for a response and manipulate the ui thereafter. But this approach cannot be used for what I have in mind.
However, what I cannot figure out, is how to send a request to a website.
I have a server localhost:800/receiveData which receives a POST request and then manipulate the UI and DoM on the angularjs site
app.get('/', function(req,res){
res.sendFile(__dirname+'/index.html')
})
app.post('/receiveData', function(req,res){
var data = req.body.data
// assume data is a boolean
if(data){
//show a view in index.html using angular js or anything else
}else {
//show a different view in index.html
}
});
Any help will be greatly appreciated. I have a need for angular js. Having a SPA is imperative. I am completely open to adding additional stacks if neccessary.
EDIT:
As pointed out by MarcoS, manipulation of dom should ideally not happen from the server side. I am combining IPFS with node js and angular js to develop a single page application. The swarm of nodes set up using IPFS has an open line of communication with my server (by design). Based on packets of data sent via the comm line to my server, I need to convey messages to the user via the index.html.
I think your approach is wrong: on server-side, you should NOT manipulate the UI and DOM...
You should just do server activity (update a database, send an email, ..., return a static page).
Then you can output a result (JSON/XML/... format) for your client-side calling script to read.
Following OP edit, what I do understand is he wants server push to the client.
To get serve side pushes, you should poll on the client.
In a controller:
function getServerState(changeState) {
return $http.get("/receiveData").then(function(res) {
changeState(res.data); // notify the watcher
}).catch(function(e) {
/* handle errors here */
}).then(function() {
return getServerState(changeState); // poll again when done call
});
}
Consuming it this way:
getServerState(function(status) {
$scope.foo = status; // changes to `foo` $scope variable will reflect instantly on the client
});
And, server side:
app.post('/receiveData', function(req, res) {
var data = req.body.data; // assume data is a boolean
res.end(JSON.stringify(data);
});
I'm running a small Angular application with a Node/Express backend.
In one of my Angular factories (i.e. on the client side) I make a $http request to Github to return user info. However, a Github-generated key (which is meant to be kept secret) is required to do this.
I know I can't use process.env.XYZ on the client side. I'm wondering how I could keep this api key a secret? Do I have to make the request on the back end instead? If so, how do I transfer the returned Github data to the front end?
Sorry if this seems simplistic but I am a relative novice, so any clear responses with code examples would be much appreciated. Thank you
Unfortunately you have to proxy the request on your backend to keep the key secret. (I am assuming that you need some user data that is unavailable via an unauthenticated request like https://api.github.com/users/rsp?callback=foo because otherwise you wouldn't need to use API keys in the first place - but you didn't say specifically what you need to do so it is just my guess).
What you can do is something like this: In your backend you can add a new route for your frontend just for getting the info. It can do whatever you need - using or not any secret API keys, verify the request, process the response before returning to your client etc.
Example:
var app = require('express')();
app.get('/github-user/:user', function (req, res) {
getUser(req.params.user, function (err, data) {
if (err) res.json({error: "Some error"});
else res.json(data);
});
});
function getUser(user, callback) {
// a stub function that should do something more
if (!user) callback("Error");
else callback(null, {user:user, name:"The user "+user});
}
app.listen(3000, function () {
console.log('Listening on port 3000');
});
In this example you can get the user info at:
http://localhost:3000/github-user/abc
The function getUser should make an actual request to GitHub and before you call it you can change if that is really your frontend that is making the request e.g. by cheching the "Referer" header or other things, validate the input etc.
Now, if you only need a public info then you may be able to use a public JSON-P API like this - an example using jQuery to make things simple:
var user = prompt("User name:");
var req = $.getJSON('https://api.github.com/users/'+user);
req.then(function (data) {
console.log(data);
});
See DEMO
I was wondering, since Node is written in JavaScript, and I'm using ES6 to write a little fun app, is there a way to access the object I send to the route without using ajax to get it from the server/api? In other words, can I say something like
import { jsonData } from '../api/server.js';
and then be able to use jsonData as a variable in my client side controller?
In other words... I would have something like this:
var DataController = (req, res) => {
let data_client = new DataClient();
data_client.getData().then(
(data) => {
res.render('index', { jsonData: jsonData });
},
(error) => {
res.send('An error occurred. Please check your connection settings.');
}
);
Is what I'm asking possible?
If not, would I just use an XHR request or fetch?
Just wondering what my options are since I want to use Node (4.x) to its full potential. Sorry if this question was confusing or vague.
I don't think that server side file will be accessible over client side.
If you make your server side file available on client and your server.js file is generic enough to run on client side as well along with correct client side export statement , then yes you can import the jsondata with syntax like
import { jsonData } from '../api/server.js';
and use it else where
Beware that there are limited browsers that support import statement
You can check the list from here
FYI: There is main question on the bottom if you ever feel like my post is too long ;)
Im trying to build my first angularjs app and now Im stuck with collecting data via ajax from nodejs (express) server.
In front-end Im loading templates with angularjs routers and ng-view. In every route i have template and specific controller (this should be pretty basic thing right?).
OK here comes the wall... I was thinking to put $http.get() to load right stuff for the template from the nodejs server in the controller. With GET I could send variables like this.
$http.get('http://.../API', { params: { twitterData : true, needed : "data2" } } )
.success( function(result) {
// pass result to template.
});
And then on the server side get params like this.
router.get('/', function(req, res) {
this.params = req.query;
// here run every function and collect it to one object
// then return it for front-end ajax call.
res.send(JSON.stringify(collectedDataObj));
}
collectedDataObj could look something like this:
{ twitterData :
{ thisIs:twitterObject },
blog : {title: "...", content: "..." }
}
Collecting data would be by nested callbacks like introduced here http://book.mixu.net/node/ch7.html
So is this "collecting all data in back-end" best way to get data or should I send many ajax calls to collect data for one angular view?
Meaning one $http.get() for getting titter object and one for blog content etc.
And of course if you know some pass me links for good tutos/examples.
IMO, whenever possible it's best to get everything you can in one request. Trips back and forth to the server get pretty expensive.