I have two roles in my database. First one is Admin and second one is normal User. I have a page that shows users table to both Admin and normal User. However, for Admin I want to show a button that creates new user with email and password. I do not want to show this button to normal User. I want it to be done on server and I do not want to set isAdmin parameter to vuex states. Because if I set it to vuex state then I can easily change the data using vue devtools... Is there any solution to render conditionally. Not like this:
<template> <div>
<b-table striped hover :items="getUserList"></b-table>
<b-button v-if="isAdmin" variant="primary" size="lg" to="/add_user">+</b-button> </div> </template>
<script> import { mapActions, mapGetters } from "vuex"; import axios from "axios";
export default { middleware: 'authorize-user', methods: {
async getUserList() {
try {
let res = await axios.post("/api/users");
if (res && res.data) {
return res.data.users ? res.data.users : [];
}
} catch (e) {
console.log("user fetch failed");
}
} }, computed: {
...mapGetters(['isAdmin']) } } </script>
Any js code on client can be altered and accessed. So your concern isn`t a valid one. You always should check permission on server. So in that case even if they change isAdmin on client and make button appear - it still wont do anything on click.
Related
I'm trying to access users of different users using my search input where I can type the name of the user and then click on any of the result and navigate to their page. The first user page is displayed but when I search for another user and click on the user name then the route gets updated in the address bar but the view in the window still displays the earlier user. what am I doing wrong in my code?
<template>
<div>
<custom-component :users="users" #input="onClick"></custom-component>
</div>
</template>
<script>
export default {
methods: {
onClick(id) {
this.$router.push(`/user/${id}`);
},
},
watch: {
$route(to, from) {
if (to.params.id !== from.params.id) {
this.$router.push(to.fullPath);
}
},
},
};
You need to change watch and fetch the users list again. No need to push the router again in watch.
watch: {
$route(to, from) {
// react to route changes...
let self = this;
self.getUsers(); // For example
}
},
im searching how to re-mount a child component. Not just re-render it, but totally re-mount (so mounted() function of my child component will be called.
I know there already is a similar question (How to re-mount a component in VueJS?), but the author was searching how to re-rendre (and the solution match this case), when i follow these instructions, my mounted() function is not called.
here is what i have:
I have a page with 2 component:
an upload component
a list component
here is what i want:
I use my upload component to upload a .zip file to my api. Then, the API parse the .zip, and store its information in database.
My list il a table of every .zip, displaying basic informations (name, description...), taking data from the store, and if empty, using axios to fetch from API (everything into the mounted() hook).
the only solution i have to update the list when i upload a new .zip is to fetch the list from my API.
here is the problem: i cant find a way to update my list. Knowing data are fetched when my list component is mounted, the solution would be to re-mount my component, But I can't find how, so I'm asking you guys.
here is my page code:
<template>
<div>
<div class="col-md-4 text-center mr-auto">
<card>
<Upload #upload="upload" ></Upload>
</card>
</div>
<div>
<List :ProjID="selectedProject.id" :key="childKey"/>
</div>
</div>
</template>
<script>
import upload from "./upload.vue";
import API from "./services/API";
import list from "./list.vue";
export default {
name: "ProjectCard",
components: {
Upload,
List,
},
props: {
selectedProject: null
},
data() {
return {
childKey: 0,
};
},
methods: {
upload(file) {
API.postJob(file, this.selectedProject.id)// <-- function calling axios, everything is working here. It also delete stored file in my store, so the list component will fetch from API to get new data
.then(response => {
this.childKey += 1;
console.log("success!")
})
.catch(response => {
console.log("not succes :c")
});
}
}
};
</script>
here is my list mounted() hook:
async mounted() {
const fetch = await API.getAll(); <-- this function fetch from my store, and if nothing comes out, fetch from API.
if (fetch == 401) {
console.log("not logged in");
}
if (fetch == 500) {
console.log("error");
return();
}
this.fetchedFiles = fetch;
this.dataReady = true;
}
I have to re-call the mounted() hook in order to update my list (or any better solution)
My app is unable to detect the state change that occurs when a user logs in without completely refreshing the page. Upon refreshing everything displays correctly. I am using Nuxt and its included auth module documented here - https://auth.nuxtjs.org/.
Here is the v-if statement that is unable to detect the state change:
<template v-if="$auth.$state.loggedIn">
<nuxt-link
to="/profile"
>
Hello, {{ $auth.$state.user.name }}
</nuxt-link>
</template>
<template v-else>
<nuxt-link
to="/logIn"
>
Sign In
</nuxt-link>
</template>
Here is the login method in my login page.
methods: {
async onLogin() {
try{
this.$auth.loginWith("local", {
data: {
email: this.email,
password: this.password
}
});
this.$router.push("/");
}catch(err){
console.log(err);
}
}
}
I tried fetching the state via a computed property but got the same result. I can see the vuex store data change to indicate I am correctly logged in/out in the 'Application' tab in Chrome Dev Tools but the Vue Dev seems to constantly indicate I'm logged in.. Not sure if its just buggy though..
I also encounter the same problem in reverse when logging out. Here's the method:
async onLogout() {
try{
await this.$auth.logout();
}catch(err){
console.log(err);
}
}
I am happy to provide further details.
In store/index.js add this :
export const getters = {
isAuthenticated(state) {
return state.auth.loggedIn
},
loggedInUser(state) {
return state.auth.user
},
};
In the pages you are suppose to be authenticated
use middle ware auth as : middleware: 'auth'
use import { mapGetters } from 'vuex'
in computed add ...mapGetters(['isAuthenticated', 'loggedInUser']),
you can use loggedInUser to get your user details or check if isAuthenticated
and the logout would work as expected as long as your are importing the map getters in the computed
Sometimes Vue's reactivity system falls short and you just need to manually trigger a re-render and the simplest way to do so is by wrapping your function logic in setTimeout()
setTimeout(async () => {
await this.$auth.logout();
}, 0);
I have a section that shows a Login button when there a user is not authenticated(as shown in localStorage), otherwise username and a 'logout botton' will be shown.
The code works when I put the authenticated inside the data block. However, if I put it in the computed field, it always shows login
#template
<router-link v-if="!authenticated" to="login">Log In</router-link>
<template v-else>
Logged in as {{username}}
<button #click="logout">Log out</button>
</template>
#script
data: function() {
return {
// get authenticated() { //this works
// return localStorage.getItem('authenticated');
// },
}
},
computed: function() {
return {
authenticated: function() { //this does not work
return localStorage.getItem('authenticated');
}
}
},
Vue isn't able to observe changes to local storage items, and so the authenticated computed property will forever return the same value because Vue caches the values of computed properties.
In this scenario you would typically use a method:
methods: {
authenticated() {
return localStorage.getItem('authenticated')
}
}
although your getter would work too.
I have my root Vue component setup like this:
<div>
<main-nav></main-nav>
<router-view></router-view>
</div>
So, main-nav is a component outside of the router-view. I'm having trouble with the main-nav updating itself properly when data changes or when navigating from route to route. Here's a simplified version of main-nav:
<template>
<li v-show="loggedIn">
<a #click="logout">Logout</a>
</li>
</template>
<script>
import { isLoggedIn, logout } from '#/tools/Auth'
export default {
computed: {
loggedIn: {
cache: false,
get() {
return isLoggedIn()
}
}
},
methods: {
logout() {
logout().then(() => {
this.$router.push({ name: 'Login' })
// this is necessary or the nav isn't updated after logout
this.$forceUpdate()
})
}
}
}
</script>
First I had to set cache: false on the loggedIn property or it wouldn't update at all after logging out. I also had to add a $forceUpdate() after logout in order for the component to refresh itself. Now I'm having the same problem after login - the component just doesn't refresh. I can see in the vue dev tools that loggedIn is true, but it won't show the logout link until I refresh the page.
It's not a race condition, there's nothing async going on at the moment. I'm just setting and deleting a cookie right now to get this working.
Anyone have an idea why I'm having these issues? I'm fairly familiar with vue-router from other projects and I've read the documentation but maybe I missed something?