Is it possible to access a element in the view from a router in expressjs. For instance, could I access the view and change the following code from the router in ExpressJS?
<div id="I would like to be accessed from the router">
<p>This is the index page and I am attached to an index router</p>
</div>
router.get('/', function(req, res, next) {
var document.get...("I would like to be accessed from the router");
res.render('NOOOOYOUCANT!!!', { title: 'Why can't I access the view?'});
});
Why can't I access the css in the view from the router?
Why can't I access the css in the view from the router?
You are trying to access client side variables from the server. Unless you have passed this data from the client (View) to the server (Node.js), the server will not be able to access the view's data.
The router does not know about the view.
What you can do is issue an AJAX or Form request from the view to the router.
Related
In my server, I retrieve an object from the database and have it in a variable as follows:
let files = [{"file1": "file1Data"}, {"file2": "file2Data"} ... ];
I want this data to be available in my client side JavaScript.
One way to do this would be to set up an API to call within my JavaScript. My thinking is that this would cause an extra round trip. This is because there is one request to load the initial HTML/JavaScript and then a further request to load the JSON data.
Therefore, it would be faster to send the JavaScript to the client along with the initial request that loaded the page.
How can I send a JSON object directly from the server and have it available in my client side JavaScript?
I would use a templating engine such as EJS or Handlebars.
As an example, using EJS (http://ejs.co/) -
Server side:
// Set EJS as the view engine for Express
app.set('view engine', 'ejs');
// or just create a directory named 'views'
app.set('views', [
path.join(__dirname, 'path/to/views'),
]);
app.get('/index', (req, res)=> {
// 'index' must be in views dir
return res.render('index', {
// Pass in foo as the second argument
// to res.render()
foo: 'bar'
});
})
index.ejs (EJS template):
<script>
const foo = <%- JSON.stringify(foo) %>;
</script>
Before serving the static files, you would need to fetch the object from the database and add the content to the files you're sending. So some kind of server-side processing. The Node app could read index.html from disk, parse it, find a place where to set the json data, and then send the data as response.
I would not do it that way though. You're already making multiple requests, e.g., client asks for index.html. Server sends that file. Client then asks for all the resources like css, JavaScript, images, fonts, etc. Another little request for some json data won't hurt.
As you said, API is the most common method if you retrieve the data from database (since you might do it after the website is loaded). If you retrieve the site when the user is requesting website, my method will be simply render it into the HTML that you serve to user.
I'm gonna show a simple sample here with pure app.write and app.get.
app.get('/', (req, res)=> {
res.write("<h1>Hi</h1>");
res.write("<script>var data="+ObjectYouRetrieve+";</script>");
res.end();
})
So I'm working on a project that incorporates React, Express.js+Passport and Webpack. I understand the concept of pushing everything to a 'master' React component via react-router, then letting it hash out what gets displayed for the given route. That would work great here, I think. To be upfront, I am new to React.
My concerns are:
1) Can I/how can I still use Passport to authenticate my routes? If I understand react-router correctly, I'll have one route in my express app.js file, pointing to, say, a React component named <Application/>. However, Passport needs router.get('/myroute', isAuthenticated, callback) to check the session. Is it still possible to do so with react-router?
2) Furthermore, if this is possible, how do I pass values from the route in Express into my views, in React? I know in a typical view, I could use <%= user %> or {{user}} if I passed that from my route. Is that possible here?
Split a view rendering path from API paths. After all you can set the authentication logic into api calls.
//Auth check middleware
function isAuth(req, res, next) {...}
//API routes
app.post("api/users/login", function() {...});
app.post("api/users/logout", function() {...});
app.get("api/purchases", isAuth, function() {...});
//and so on...
//Wild card view render route
app.use(function(req, res) {
var router = Router.create({
onAbort: function(options) {...},
onError: function(error) {...},
routes: //your react routes
location: req.url
});
router.run(function(Handler) {
res.set("Content-Type", "text/html");
res.send(React.renderToString(<Handler/>));
});
});
So you have to solve how you're going to pass server side rendered data in views to a client side (choose your isomorphic data transferring technique).
You can also create views and the redirection logic on a client side only and firstly render react components in an "awaiting" state that will be resolved on a client after a component will be mounted (check auth state via an API call).
I've set up a meteor app using iron-router and I want the app to listen to a webhook from another service (basically I'm building an API for other services to use)
So for example, when an external website calls myapp.meteor.com/webhook I want to catch that specific link and parameters and do stuff with the data.
Update: Thanks to a comment I found this: https://github.com/iron-meteor/iron-router/blob/devel/Guide.md#server-routing
Router.route('/webhooks', { where: 'server' })
.post(function () {
console.log(this);
this.response.end('Caught you\n');
//this.response.status(200).json({text:"Todo added"});
});
I added the above in the /server folder as there is no need to for the front-end server to worry about this like mentioned in the comment. But when I load this using postman POST request, it just returns my HTML for not found. Any ideas?
Thanks in advance for your help.
UPDATE
I tried what #David said and still I get the template loaded and nothing in the console. Any idea what I'm doing wrong?
Your server route will only run if no client routes also match. I suspect you have a catch-all route which is executing on the client and preventing the server route from running. One solution is to define all of the routes in a common folder like /lib so that you can properly order them. Your routes file could look something like:
client route 1
client route 2
server route 1
server route 2
catch-all (not found) route
I have a meteor application and am using Iron Router for the routing.
I've got one route called /process which is run server side. In the URL parameters i have a parameter named route. What i want to do is for the handler for the route handler to return the HTML that was generated from the route specified in the parameter using this.res.end(- the rendered HTML from the route parameter's route-)
This is bound to be possible but my meteor skills are lacking.
i'm currently trying to display the name of the logged-in user in my MEAN app. I'm using the EJS templating engine and I'm able to get the username showing by putting <%- user.username %> in my markup. The problem with this is that I don't really want to my mixing angular and embedded scripts in the same files, I'd like to pass the server-side data into Angular. I've tried ng-init but I'm not having any success at all with it.
I will assume you are using ExpressJS 4 it will be a little different in version 3, however the approach will be the same for both versions:
Node/Sever side
var express = require('express');
var bodyParser = require('body-parser');
var schema = require("./schemas");
var app = express();
var router = express.Router();
router.get('api/account', function(req, res){
res.json({ "login": req.session.user.login }); /*access the session account not sure if this matches your login location you will adapt it to your own*/
});
Angular/Client Side
You then invoke from your controller or service the url api/account with a GET request to receive the JSON like:
$http.get("/api/account").then(function(data){ console.log(data); });
then you could do something like:
$scope.login = data.login;
and in the html
{{login}}
From what I understand of Angular, it discourages server-side setting of templated values in HTML code. Consider setting up a JSON service that provides the data, and fetching the data over JSON. There is an example at the end of the Angular Tutorial that may make this clearer.
I do the exact same thing and mix EJS to embed things like my server info (to initiate a socket connection from the client). If you wanted to keep this purely client-side, you would need to have AngularJS fetch the server-side data using a service / factory - and then affect any views you have depending on said data.
ng-init only applies to things which live inside the "Angular" scope.