Call vuex getters from Vue-Router - reactive-programming

Is it possible to call vuex getters from the router?
I need to check the state of a boolean variable from beforeach hook:
router.beforeEach(function ({ to, next }) {
if (to.path !== '/login') {
// return a Promise that resolves to true or false
return the-needed-variable-from-store;
} else {
next()
}
})
How can I get and check the variable derived from the store?
Thanks a lot!

There was a discussion on this here: https://github.com/vuejs/vuex-router-sync/issues/3#issuecomment-200192468
I was able to access the variable in a fairly ridiculous way:
router.beforeEach((transition)=>{
if(transition.to.auth){
if(!transition.to.router.app.$store.state.auth.authorized){
transition.abort()
router.go({path:"/"})
}
}
transition.next()
});
So in your case it might look like to.router.app.$store.state

Related

Axios in Vuex Store returning promise and not data

I'm not sure why I can't get the data I want from this axios.get in my Vuex store.
I've setup this action to commit a change to my mutation like this:
mutations: {
updateShop: (state, payload ) => {
state.shop = payload;
return state.shop;
}
},
actions: {
getShop: ({ commit }) => {
return axios.get("/admin/wine_app/shops").then(response => {
debugger; // I DO have data here??
commit('updateShop', response.data);
});
}
}
But when I stop it with that debugger I DO have the data, but when I use the getShop action in an component I see the promise being returned.
Any idea why?
EDIT:
It MIGHT just not be ready!! I'm seeing this in the console
Promise {<pending>}
__proto__: Promise
[[PromiseStatus]]: "pending"
[[PromiseValue]]: undefined
make the action getShop async
getShop: async ({ commit }) => {
const response = await axios.get("/admin/wine_app/shops");
debugger; // I DO have data here??
commit('updateShop', response.data);
}
await the action where you call it
await this.$store.dispatch('getShop')
Use the shop state prop in your code
this.$store.state.shop
or use mapState if you would like to use several state props.
Also make sure not to return any data from mutations. They must change state and not return its props.
The reason you are seeing a promise is because your action is returning the axios call. Remove the return in both your mutation and action methods.
Your action method uses axios to retrieve the data. This then commits your mutation with the response data. Your mutation method updates the state with that data. At this point your state.shop is updated.
Within your Vue components you can access that data by accessing the state as a computed property.
computed: {
shop() {
return this.$store.state.shop
}
// Or use mapState
...mapState(['shop'])
}
Whenever your state changes this should update in your components due to reactivity.

Get current filename in Babel Plugin?

I'm attempting to write a plugin for babel, and am needing the filename of the current file that is being parsed. I know the lines of the code are passed in, but I haven't managed to find a reference to the filename. Any help??
For instance given this code what could I do
export default function({ types: t }) {
return {
visitor: {
Identifier(path) {
// something here??
}
}
};
}
You can you this or use the 2nd parameter in a visitor (state)
Identifier(path, state) {
console.log(state.file.opts.filename);
}
For any future viewers, you can use this.file.opts.filename in a visitor function

Meteor onRendered function and access to Collections

When user refresh a certain page, I want to set some initial values from the mongoDB database.
I tried using the onRendered method, which in the documentation states will run when the template that it is run on is inserted into the DOM. However, the database is not available at that instance?
When I try to access the database from the function:
Template.scienceMC.onRendered(function() {
var currentRad = radiationCollection.find().fetch()[0].rad;
}
I get the following error messages:
Exception from Tracker afterFlush function:
TypeError: Cannot read property 'rad' of undefined
However, when I run the line radiationCollection.find().fetch()[0].rad; in the console I can access the value?
How can I make sure that the copy of the mongoDB is available?
The best way for me was to use the waitOn function in the router. Thanks to #David Weldon for the tip.
Router.route('/templateName', {
waitOn: function () {
return Meteor.subscribe('collectionName');
},
action: function () {
// render all templates and regions for this route
this.render();
}
});
You need to setup a proper publication (it seems you did) and subscribe in the route parameters. If you want to make sure that you effectively have your data in the onRendered function, you need to add an extra step.
Here is an example of how to make it in your route definition:
this.templateController = RouteController.extend({
template: "YourTemplate",
action: function() {
if(this.isReady()) { this.render(); } else { this.render("yourTemplate"); this.render("loading");}
/*ACTION_FUNCTION*/
},
isReady: function() {
var subs = [
Meteor.subscribe("yoursubscription1"),
Meteor.subscribe("yoursubscription2")
];
var ready = true;
_.each(subs, function(sub) {
if(!sub.ready())
ready = false;
});
return ready;
},
data: function() {
return {
params: this.params || {}, //if you have params
yourData: radiationCollection.find()
};
}
});
In this example you get,in the onRendered function, your data both using this.data.yourData or radiationCollection.find()
EDIT: as #David Weldon stated in comment, you could also use an easier alternative: waitOn
I can't see your collection, so I can't guarantee that rad is a key in your collection, that said I believe your problem is that you collection isn't available yet. As #David Weldon says, you need to guard or wait on your subscription to be available (remember it has to load).
What I do in ironrouter is this:
data:function(){
var currentRad = radiationCollection.find().fetch()[0].rad;
if (typeof currentRad != 'undefined') {
// if typeof currentRad is not undefined
return currentRad;
}
}

beforeCreate function sailsjs

Before storing data to database I must modify string . Here's my code
beforeCreate:function(value )
{
value.text = value.text.replace(/(\t|\n)/g, '');
}
How to add callback to this function? I know that there must participate callback.
I believe this should do it:
beforeCreate: function(values, callback) {
values.text = values.text.replace(/(\t|\n)/g, '');
return callback();
}
You can refer to the docs for more examples.

How to get Meteor.Call to return value for template?

I've tried to understand this post regarding this concept, however, I'm failing to get it. I have the following simple setup:
/server/test.js
Meteor.methods({
abc: function() {
var result = {};
result.foo = "Hello ";
result.bar = "World!";
return result;
}
});
/client/myapp.js
var q = Meteor.call('abc');
console.log(q);
This structure returns to the console undefined.
If I change the myapp.js file to:
Meteor.call('abc', function(err, data) {
!err ? console.log(data) : console.log(err);
}
I receive the Object in my console.
Ideally this is what I'd like to be able to do, but it doesn't work, stating in the console: Cannot read property 'greeting' of undefined
/client/myapp.js
var q = Meteor.call('abc');
Template.hello.greeting = function() {
return q.foo;
}
Any help in passing the data from the server object into the template would be greatly appreciated. I'm still learning JavaScript & Meteor.
Thanks!
From the Meteor.call documentation:
On the client, if you do not pass a callback and you are not inside a stub, call will return undefined, and you will have no way to get the return value of the method. That is because the client doesn't have fibers, so there is not actually any way it can block on the remote execution of a method.
So, you'll want to do it like this:
Meteor.call('abc', function(err, data) {
if (err)
console.log(err);
Session.set('q', data);
});
Template.hello.greeting = function() {
return Session.get('q').foo;
};
This will reactively update the template once the data is available.
This happens because Npm.require has Async behavior. That's the reason that you have to write a callback for Meteor.call.
But there is a solution, just use install(mrt add npm) and you'll get a function named Meteor.sync(//...) with this you can do both games: sync and async in your Meteor.call().
Reference: http://www.sitepoint.com/create-a-meteor-app-using-npm-module/
You can get the return value of a Meteor method for use in a template by using a reactive variable. Check out the working demonstration on Meteorpad
I went for a ghetto solution. But, it works for me, which is what matters, to me. Below is my code, which, in concept, I think, solves OP's problem.
In the client's main.js:
Meteor.setInterval(function() {
confirmLogin();
}, 5000);
This runs the confirmLogin() function every five seconds.
The confirmLogin function (in the client's main.js):
function confirmLogin() {
Meteor.call('loggedIn', function (error, result) {
Session.set("loggedIn", result);
});
}
The loggedIn method (in the server's main.js):
loggedIn: function () {
var toReturn = false;
var userDetails = Meteor.user();
if (typeof userDetails["services"] !== "undefined") {
if (typeof userDetails["services"]["facebook"] != "undefined") {
toReturn = true;
}
}
return toReturn;
},
The relevant helper:
loggedIn: function () {
return Session.get("loggedIn");
}