I just coded sample files.
my ejs file display some data after receiving the data from API call.
my code is shown as below and the pattern of my code follows
node(router) --> call api(axios) --> display data on the ejs file.
//index.js
...
...
router.get('/dashboard', function(req,res,next){
try {
let result = await axios({ //Call API
method: 'get',
url: 'http://localhost:3001/user',
data: {
id: '1129',
lastName: 'Test'
}
});
res.render('dashboard', {data: result.data}); //display the received data
} catch (error) {
next(error)
}
})
module.exports = router;
//dashboard.ejs
...
...
<div>
<p>js data : <%=data%></p> //displays the data I jsut received from Axios
</div>
...
...
But what if some client types input value and I want to execute API call(post or put) with the client input value?
likes..
get client value from ejs --> send the value to node(router) --> call api(axios)
is there any way to do that?(without ajax, because I am trying not to use ajax).
You have three layers here. EJS is the least relevant one of these.
The controller (the function you pass to router.get) which runs on the server and handles the business logic.
The view (the EJS template) which runs on the server and handles the display logic (converting the data into HTML).
Client-side JS (<script> elements) which run on the client
But what if some client types input value and I want to execute API call(post or put) with the client input value?
Then you have two options:
Submit a <form> to a URL that is handled by a controller (which then uses axios server side, gets some data, populates an EJS view and returns a new page to the client).
Read the data with client-side JS, use Ajax to send it to a URL (which could be a URL you provide which is handled by a controller), have that controller return data (which could be HTML generated by EJS or plain JSON) and then use client-side JS to insert it into the page.
If you don't want to use Ajax, then you have to use a form submission and load a new page.
While it might be possible to call Axios from EJS (I have a feeling the asynchronous nature of it would break things) that is effectively the same as the form submission option, but it puts business logic in the view layer, which is confusing at best.
Related: What is the difference between client-side and server-side programming?
Related
I'm trying to pass data (array) from node.js backend to frontend JS to process it there. I don't want to pass data directly to backend-served html file because I'd like to keep it clean and don't want to do any loops there etc.
My backend part looks like this:
app.get("/search-db", function (req, res) {
const term = req.query.term;
findInDb(term);
res.redirect('/search', {
searchResults: searchResults,
});
})
async function findInDb(query) {
const collection = await getDbCollection();
await collection.find().forEach((item) => {
console.log(item.artist);
if (item.artist.includes(query) || item.name.includes(query)) {
searchResults.push(item);
}
})
}
Is this possible or do I have to clutter my html and use loop there to process passed results?
Your web page can use AJAX via fetch to make the /search-db API request to your server. Your server route handler should fetch the results from the DB, then invoke res.send() to send a JSON response back to the client, rather than res.redirect() to redirect the client to a new page.
Example: How to create a REST API with Express.js in Node.js
Also, unrelated, your findInDb function should return the search results instead of placing them in a global variable (searchResults).
I'm trying to make an application using nodejs, express and ejs. What I'm aiming to do is submitting a form to the server, trigger a server function which processes the data to get some result, and getting my page to display the result without reloading the whole page.
Currently this is what I have:
ejs
<form method = "GET" action = "/sendinput"
...something here
</form>
app.js
app.get('/sendinput', function (req, res) {
result = processData(req.query);
});
I manage to get the function to run when the form is submitted, but after that the page keeps loading even after the function finishes running. I'm also not sure how to fetch the result and let the form segment of the html displays it without reloading the whole page.
To stop the page from loading, use res.end();
it will signal the server that your function is done.
app.get('/sendinput', function (req, res) {
result = processData(req.query);
res.end();
});
So in the end I solve it by using Ajax, which doesn't prompt the page for a reload and manage to get what I want.
I currently have an app which uses Express with Jade templates.
I'm building a new version of the app using Angular with client-side HTML.
I need access to certain request parameters in order to determine user permissions in my Angular code. My problem is that I don't know how to get ahold of these parameters in my Angular controllers/services.
Below is what currently occurs in Express with the Jade structure:
routes.js:
router.get('/player/:id',
playerRoute.show
);
player.js:
var show = function(req, res) {
res.render('player', {user: req.user});
};
...and now my new version's handler:
var player = function(req, res) {
//res.sendFile(path.join(__dirname, '../v2', 'index.html'));
res.json({user: req.user});
};
The correct user JSON is sent back to my client-side with the code above. When res.json is commented out and res.sendFile uncommented the correct HTML is rendered. My dilemma is how to both render this HTML AND provide my client-side Angular code with the user JSON object?
After all that, your question just boils down to:
MY dilemma is how to both render this HTML AND provide my client-side Angular code with the user JSON object?
You don't. The usual case is to just render the HTML along with the assets needed to render the initial app (hide everything, show a splash screen whatever). Further data (like getting your user) is handled by API calls to your server via Angular's HTTP facilities. That means they are separate. After that API call, your app determines what to render.
Otherwise, you could just render the data in the HTML as some global variable and have Angular pick it up from there. This is messy IMO, but doesn't require a separate API call to get the data.
copied from my own answer to a similar question
To get a variable from server to client javascript try templating a json string into the html and loading it from the javascript. EJS handles quote escaping and I think Jade does too. For reference content!= safeString tells Jade to skip escaping, so does content !{safeString}.
- var user={id:1, displayName:'foo'}
#example
meta(data-userJSON=JSON.stringify(user))
script(src="//code.jquery.com/jquery-1.11.3.min.js")
script.
var user = JSON.parse(
$('#example meta').attr('data-userJSON')
)
console.log(user);
span #{user.id}
span #{user.displayName}
Here's how I ended up handling this situation. I simply created a new API endpoint which I can easily hit with an Angular service. Here's the Node setup:
routes.js:
router.get('/currentUser',
apiController.currentUser.index
);
currentUser.js:
var index = function(req, res) {
res.json({user: req.user});
};
module.exports = {
index: index
};
Still seems odd to me to make an API call to get the request parameters, but it works. Feedback appreciated.
Please help, I'm unflushed in programming . I created a route router.get('/statistics', routesCtrl.statistics) for a page where I want to display some statistics in some charts, using Angular.
I realized that I need to send some query results like, how many registrations are in db, how many of them have "this property", how many of them have “those properties” and so on, being something new for me. Until now in responses of the routes I sent only one statistic from the above list.
How should I send this info to Angular, should I create a literal object containing those statistics, packing them in the response and send it to the Angular? Or to send the entire json from db and parse it in Angular, but it seems to be a wrong idea also because I can't use then mongoose queries from Angular if it's true :) .
I don’t have any other idea and there probably are more professional ways. Thank you!
It is very simple, whenever you need data from server side, which is node.js in your case or anything it may be like PHP, asp.nrt etc you have to send http requests to server using angular $http (GET/POST) and along with required parameters as a json object or query string. At server end write some rest service type stuff to handle this and make use of send parmeters at server to query mongo and than pass collected data as a json object back to angular end. At angular you can parse this JSON, and angular have also scope to use JSON/Array directly in view using attribute ng-repeat and so on depends on your exact requirement.
Request in angular.js
var sendConfig = {
method : "POST",
url: "YOUR_URL",
data: {action : 'Test_Service'},
headers : {}
};
$http(sendConfig).success(function(response) {
console.log(response);
}).error(function(error) {
console.log(error);
});
Response In node.js
var server = http.createServer(function(req,res){
var webservice_actions_instance = new webservice_actions(req, res);
var service_response = {data : 'RESPONSE_HERE_AFTER_CERTAIN_ALGOS'};
res.writeHead(200, {'Content-Type': 'text/html',"Access-Control-Allow-Origin": "*","Access-Control-Allow-Headers":" X-Requested-With"});
res.write('Response Data '+ service_response);
res.end();
}).listen( 8080 );
I'm developing an Angular application with the MEAN stack, so suppose you got an express route that make a query to the databse, the results are sent in the response:
app.get('/api', function(req, res){
Todo.find({}, "", function(err,todos){
if (err)
res.send(err);
res.json(todos);
});
});
In the client-side:
Controller :
...
Todo.get().success(function(data){ //i got the service with the $http call
$scope.todos = data;
});
When I go to localhost:8080/#/api, I can see my partial and the data I requested.
The problem that I'm having is that if I omit the hashtag, i don't see the partial, I only see the response data in JSON format.
I also tried to use html5 mode, but if I reload I got the same behavior.
Any ideas on how can I avoid this behavior??
Anything after the # isn't sent to the server. So when you go to localhost:8080/#/api, expressjs just sees a request to / and returns the AngularJS template. AngularJS then routes the browser page using the /#/api, which called the Todo.get() and (I assume) makes a call to localhost:8080/api, returning the data from the DB.
That's why you only get the data when you omit the hash and when you use html5 mode.
I would suggest changing your API call to:
/api/todos - return data from the db
And change your AngularJS route to just use:
/todos - show the partial and data requested