Is there any (simple) way to pass variable from Express to Vue.js?


#1

Ok, so I’m just starting to use Vue.js, and man, it’s so hard to do things that are very simple when just using EJS for example. I’m close to abandon Vue for my current project (Nightlife coordination challenge), since I just don’t know how to pass res.locals.something from Express server to Vue frontend. By the way, it’s Passport.js thing - when authenticated, user should be redirected, but I have to pass the info whether user has logged in or not to Vue (res.locals.isLogged = req.isAuthenticated();), and that seems impossible with my current (close to 0) Vue.js skills… The only solution I found was using ajax (axios was my choice) request on the client side, targeting /login/facebook route on the server, and then I could pass the response from Express to Vue, but it cannot work because of the damned CORS issue. So, I cannot use ajax to retrieve the data from Express, and Express and Vue are not natively connected like Express and EJS or Pug for example.

In short - does anyone know of a simple way to pass Express variable to Vue, not including Vue SSR, Express-vue module etc.?

P.S. I’m not using Webpack or anything similar - just a simple index.html file with Vue loaded from CDN.


#2

Let’s say you have a vue app JS code like this:

myapp = new Vue({
      el: '#screen',
      
      data: {
        myVariable: 'hello',
      }
    });

You can pass/read Vue data variables using this

console.log(myapp.myVariable)   // returns 'hello'
myapp.myVariable = 'goodbye'   // assign new value 

#3

Thanks, but maybe I did not explain the problem properly - I want to pass variable from server (Express) to view (index.html with Vue rendering it). I don’t have a problem with Vue data, the problem is passing data from Express to Vue.

For example, if it was ejs on the frontend, I would just declare a variable in Express (res.locals.isLogged = req.isAuthenticated();) and in ejs file I would access it just by using isLogged. I cannot do that with Vue.

Edit - it seems like I must use .ejs extension, that way I am able to pass variable to ejs script, which seems to work alongside Vue… But I don’t like it. Vue seems like a great idea without some basic stuff incorporated, at least not without too much trouble…


#4

I’ve never used Vue as the front-end to an Express server. Interesting challenge.

EJS is a templating language, no? I’ve always seen Vue as a complete solution.

Off the top of my head, it seems you’d need some for a middleware to make those variables available in the Vue component. How does React get data out of Express? I’d guess it’s a similar to that.

Or you could keep the two separate and use vue-resource to call data routes and access the information. Added benefit of allowing you to use any ‘view’ framework (including native mobile) as required.

Mostly, I’m just blue-sky thinking here. I’ll be watching and hoping someone with more experience in this chimes in.


#5

I can’t use vue-resource, axios or even jQuery ajax - there is a CORS problem preventing me from doing that, otherwise it would be ok.


#6

If you’re requesting from your own express server, you can use the CORS module to send the correct headers when the request comes in. I had to do something similar in a Heroku-hosted API project.

var express = require('express');
var cors = require('cors');

app.get('/your-route', cors(), (req, res) => {
  // res.status(200).send('your data');
}

I’ve left a lot out of that example, but the important parts are the (obviously) required CORS module and the cors() middleware call.


#7

Thanks, but this is not the case - what I tried was using axios on the front end to make an ajax call to Express.js /login/facebook route, then Passport.js would authenticate the user and in my response I would pass variable to axios and Vue, but that is not working. Not only for me - it is not possible in this case.


#8

Making ajax request is the right way to go about it. To resolve cors issue you can install cors npm package and use it in your express application but as far as I can remember it conflicts with passport.
The optimal solution is to make your frontend and backend work on the same server. Make your express router to serve index.html file
`
app.get(’/*’, function(req, res) {
res.sendFile(path.join(__dirname, ‘…/…/dist/index.html’)); // or whenever you html file is placed
});

Make sure to place this code after your other express routes.
`


#9

Any chance to simplify that? Just curious. :grinning:

For the metadata microservice challenge, I used a static public folder that had my html webform. The form POSTed to my /getsize route.

app.use(express.static('public')); 
// public folder in root of project has index.html

#10

Actually, I think Meteor works like this a little. It has the same base code (imports), but manages the front (client) and back (server) ends separately. Separate folders for separate concerns.

Just about to jump back into Meteor (learned it a few months ago, but didn’t have a good project to try it on). I prefer to replace the Blaze templating engine with React (really easy). But this entire paragraph is way off topic. :stuck_out_tongue_closed_eyes:


#11

Yeah you need to configure express.static to serve client files. And it also will serve index.html. The route ‘/*’ is to make sure you always serve index.html since it’s supposed to be a single page app.


#12

That makes sense. :thumbsup:


#13

@prohorova, well, I was using express.static, but not with res.sendFile, now I’ll try that and see if it works.

To resolve cors issue you can install cors npm package and use it in your express application but as far as I can remember it conflicts with passport.

Yeah, it’s not working with Passport, I’ve tried that and bunch of other solutions, but now I’ll try res.sendFile approach…


#14

Ok, so I tried (res.sendFile), and still I get dreaded:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://www.facebook.com/dialog/oauth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2Flogin%2Ffacebook%2Freturn&client_id=**secret**. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

My front-end axios ajax call looks like this:

axios.get('/login/facebook')
.then(function (response) {

console.log(response)
})
.catch(function (error) {
console.log(error);
});

My back-end route receiving the call is like this:

app.get('/login/facebook',
passport.authenticate('facebook'));

app.get('/login/facebook/return',
passport.authenticate('facebook', { failureRedirect: '/failure' }),
cel.ensureLoggedIn(),
function(req, res) {
res.send("test");
});

Any idea? Are you sure that it can be done in this particular case?


#15

That’s not how it should be done. You don’t need an ajax request for that. Just place
<a href='/login/facebook'>
somewhere on your page so your page will make a redirect.


#16

Well, I thought you said that ajax request is the solution, so I tried whole day to do that, although I was convinced previously that’s impossible… My approach was already with a href, but with combination with ejs to get isLogged boolean.
Thanks for help. :slight_smile:


#17

Well I thought you had cors issue between your client and server, not with facebook server. So your passport authentication is working. Then as soon as your vuejs application launches make an ajax request to an express route that returns req.isAuthenticated(). No ejs needed.


#18

Do you know how to do that?

I have tried this call from the client(supposedly mounted() should fire immediately during page load):

    methods: {
    mounted (){

    axios.get('/check')
    .then(function (response) {
    console.log(response);
    })
    .catch(function (error) {
    console.log(error);
    });
    }

On the server I have this route:

app.get('/check', function(req, res) {
res.send(req.isAuthenticated());
});

Nothing is happening, as if no ajax call has been made… Probably I’m doing something stupid, but I don’t get what should I do…

Ok, seems that mounted() function doesn’t work in this case, so I’ll use jQuery document ready function. All in all, Vue really is giving me headaches because integration with backend isn’t that good. I think my next backend project will be all-jQuery. :slight_smile: