I have a vue component which can be seen on other users's profile but not on logged in user.
when I visit other user's id i can see that component but when I come back to my id it disappears
profile url is /myplace/{username}
vue component :
<template>
<img src="https://cdn0.iconfinder.com/data/icons/basic-ui-elements-colored/700/09_bell-3-512.png" style="height:50px;margin-top: 30px; margin-left:0px!important;">
</template>
<script>
import $ from 'jquery'
import axios from 'axios'
import Notification from './Notification.vue'
export default {
components: { Notification },
props:['username'],
data: () => ({
total: 0,
notifications: []
}),
mounted () {
this.fetch()
if (window.Echo) {
this.listen()
}
this.initDropdown()
},
computed: {
hasUnread () {
return this.total > 0
}
},
methods: {
/**
* Fetch notifications.
*
* #param {Number} limit
*/
fetch (limit = 5) {
axios.get('/notifications', { params: { limit }})
.then(({ data: { total, notifications }}) => {
this.total = total
this.notifications = notifications.map(({ id, data, created }) => {
return {
id: id,
title: data.title,
body: data.body,
created: created,
action_url: data.action_url
}
})
})
},
in blade view:
<notifications-dropdown :username="{{json_encode($user)}}">
</notifications-dropdown></a>
app.js:
import './bootstrap'
import Vue from 'vue'
import NotificationsDemo from './components/NotificationsDemo.vue'
import NotificationsDropdown from './components/NotificationsDropdown.vue'
new Vue({
el: '#app',
components: {
NotificationsDemo,
NotificationsDropdown
}
})
Related
This is the store.js where am consuming the API. I wanted to get the data from the API and display it when loaded. but at the moment am getting two errors
Error in mounted hook (Promise/async): "TypeError: Cannot read properties of undefined (reading 'SET_POST')"
TypeError: Cannot read properties of undefined (reading 'SET_POST')
<template>
<div v-if="!isDataLoaded">
Loading ...Please wait
</div>
<div v-else="isDataLoaded">
</div>
</template>
<script>
import { mapGetters } from 'vuex';
export default{
data: () => ({
isDataLoaded: false,
}),
computed:{
...mapGetters([
"GET_POST",
]),
},
methods: {
post() {
return this.$store.getters.GET_POST;
}
},
async mounted() {
await this.$store.actions.SET_POST
this.isDataLoaded = true
}
}
</script>
store.js file
`
import Vue from "vue";
import Vuex from 'vuex';
import axios from "axios";
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
form: [],
post: [],
twoChunkPost: []
},
getters: {
GET_POST: state => {
return state.post;
}
},
mutations: {
SET_POST(state, post) {
state.post = post;
},
}
actions: {
SET_POST: async ({ commit }) => {
const options = {
headers: {
"Content-Type": "application/json"
}
};
let { data } = await axios.get(
"/api/post",
options
);
if (data.meta.code === 200) {
let postArray = data.data.post;
let chunkSize = 2;
commit("SET_POST", postArray);
let chunkedArray = chunk(postArray, chunkSize);
commit("SET_CHUNKED_POST", chunkedArray);
}
},
}
});
`
I have a problem and it is that when switching between components with router.push the Toast notification is not shown. I have the user edit view and what I want to do is redirect to the user's profile once it has been edited and immediately show the toast notification.
Roughly, I have the following:
Routes.js
import { createRouter, createWebHistory } from 'vue-router';
//Modules
import DashboardIndex from './components/modules/dashboard';
//Users
import UsersIndex from './components/modules/users';
import UsersCreate from './components/modules/users/create';
import UsersEdit from './components/modules/users/edit';
import UsersView from './components/modules/users/view';
export default new createRouter({
history: createWebHistory(),
routes: [
{ path: '/', name: 'dashboard.index', component: DashboardIndex },
{ path: '/users', name: 'users.index', component: UsersIndex},
{ path: '/user/create', name: 'user.create', component: UsersCreate},
{ path: '/user/edit/:id', name: 'user.edit', props: true, component: UsersEdit},
{ path: '/user/:id', name: 'user.view', props: true, component: UsersView},
]
})
Composable/users.js
import axios from 'axios';
import { useRouter } from 'vue-router'
import { useToast } from 'primevue/usetoast';
export default function useUsers() {
const users = ref([])
const user = ref([])
const errors = ref([])
const router = useRouter()
const toast = useToast()
/**
*
* All Users
*
*/
const getUsers = async () => {
const response = await axios.get('/admin/users')
users.value = response.data
}
/**
*
* Create User
*
*/
const storeUser = async (data) => {
try {
let response = await axios.post('/admin/user', data)
await router.push({ name: 'user.view', params: { id: response.data.id } })
} catch (e) {
if (e.response.status === 422) {
errors.value = e.response.data.errors
}
}
}
/**
*
* Create User
*
*/
const updateUser = async (id) => {
try {
//this.showToast = true;
let response = await axios.put(`/admin/user/${id}`, user.value)
router.push({ name: 'user.view', params: { id: response.data.id } })
toast.add({severity:'success', summary: 'Éxito', detail: 'El Usuario ha sido modificado', life: 3000})
} catch (e) {
if (e.response.status === 422) {
errors.value = e.response.data.errors
}
}
}
/**
*
* View User
*
*/
const showUser = async (id) => {
let response = await axios.get(`/admin/user/${id}`)
user.value = response.data
}
/**
*
* Delete User
*
*/
const destroyUser = async (id) => {
await axios.delete(`/admin/user/${id}`)
}
return {errors, users, user, getUsers, storeUser, updateUser, showUser, destroyUser}
}
View.vue
<template>
<div class="container-fluid">
<Toast position="bottom-right"/>
USER PROFILE
</div>
</template>
<script>
import useUsers from '../../../composables/users'
import { onMounted } from 'vue';
export default {
props: {
id: { required: true }
},
setup(props) {
const { user, showUser } = useUsers();
const showUserMounted = async () => {
await showUser(props.id)
}
onMounted(showUserMounted)
return { user }
}
}
</script>
Important fact, I'm using Prime VUE.
And additionally I comment that, when I move to toast.add({severity:'success', summary: 'Success', detail: 'The User has been modified', life: 3000}) inside showUser it is shown well the toast message.
I think what I need is a flag that changes the value in the updateUser method (for example showToast = true) and from the showUser method verify if it is true, if so, execute the toast.add, but I don't know how to do this last.
Thank you very much.
It does not redirect after successfully logged in.
getting a console error TypeError: Cannot read property 'push' of undefine
Here my code.
I'm creating SPA in vue3 with Laravel 8.
import { ref } from "vue";
import { useRoute } from "vue-router";
export default {
setup() {
const form = ref(
{
email: "hudson.vilma#example.net",
password: "password",
isLoading: false,
},
);
const user = ref("");
function login() {
axios.get('/sanctum/csrf-cookie').then(response => {
axios.post('/login', this.form).then(response => {
this.$router.push('/dashboard')
// useRoute.push('/dashboard');
// this.$router.push({ name: "Dashboard" });
}).catch(error => console.log(error)); // credentials didn't match
});
}
return { form, login, user , useRoute};
},
};
</script>
in app.js instant of vue &
require('./bootstrap');
import { createApp } from "vue";
import App from "./view/App.vue";
import router from "./router";
const app = createApp(App);
app.use(router);
app.mount("#app");
Try to use useRouter instead of useRoute and instantiate it like const router =useRouter() in setup function:
import { ref } from "vue";
import { useRouter } from "vue-router";
export default {
setup() {
const router =useRouter()
const form = ref(
{
email: "hudson.vilma#example.net",
password: "password",
isLoading: false,
},
);
const user = ref("");
function login() {
axios.get('/sanctum/csrf-cookie').then(response => {
axios.post('/login', this.form).then(response => {
router.push('/dashboard')
}).catch(error => console.log(error)); // credentials didn't match
});
}
return { form, login, user ,};
},
};
</script>
Note that this couldn't be used in composition API.
You are using this.$router.push('/dashboard') in setup(). This cannot be used in setup(). Instead you can use...
router.push('/dashboard')
I have a project using Laravel and Vue.js. I guess it wasn't the best idea not to separate them, but we learn from our mistakes ;)
Here is how it works:
I have been struggling trying to put global variables, such as "current user". Now, I am calling /currentuser through axios each time I need it, or I put it in props, but it drives my crazy... How can I make it global?
I am wondering if Vuex could work in my project, as everything is called from Laravel, the routes as well...
I have tried several things in app.js (here are 2 of them, mixed):
var curruser=null;
axios.get('/currmember').then(
response => {
curruser=response.data;
}
);
Vue.mixin({
methods: {
},
data: function() {
return {
myvaiable: '', //this doesn't work eather
get currentUser() {
if(curruser==null){
axios.get('/currmember').then(
response => {
curruser=response.data;
return curruser;
}
);
}
return curruser;
}
}
}
});}
in TestComponent.vue
<template>
<div>
{{currentUser}}
{{myvariable}} <!-- none of them display anything -->
</div>
</template>
Here is how things are working (simplify them very much):
app.js
import Vue from 'vue';
window.Vue = require('vue');
var App = Vue.component('app', require('./App.vue').default, {
name: 'app'
});
var shol = Vue.component('test', require('./components/TestComponent.vue').default);
let lang=localStorage.Lang!=null?localStorage.Lang:'fr';// = document.documentElement.lang.substr(0, 2);
init();
function init(){
const app = new Vue({
el: '#app',
i18n,
components:{test
}
});
var curruser=null;
axios.get('/currmember').then(
response => {
curruser=response.data;
}
);
Vue.mixin({
methods: {
},
data: function() {
return {
currentUser: 'blabla',
get currentUser2() {
if(curruser==null){
axios.get('/currmember').then(
response => {
curruser=response.data;
console.log(curruser);
return curruser;
}
);
}
return curruser;
}
}
}
});}
test.blade.php
#extends('template')
#section('pageTitle', 'test' )
#section('contenu')
<div >
<test></test>
</div>
#endsection
web.php
Route::get('/test', function () {
return view('test');
});
You may use vuex to access current authenticated user:
On app.js:
import Vue from 'vue';
import store from './store';
const app = new Vue({
el: '#app',
store,
i18n,
components:{ test },
created() {
store.dispatch('getUser');
}
});
The store.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
user: {},
},
getters: {
user: state => state.user,
},
mutations: {
setUser(state, user) {
state.user = user;
},
},
actions: {
getUser({ commit }) {
return new Promise((resolve, reject) => {
axios.get('/currmember')
.then(result => {
commit('setUser', result.data);
resolve();
})
.catch(error => {
reject(error.response && error.response.data.message || 'Error.');
});
});
},
}
})
The test component:
<template>
<div>
{{ currentUser }}
</div>
</template>
<script>
export default {
computed: {
currentUser() {
return this.$store.state.user;
}
}
};
</script>
I'm creating a laravel SPA and I'm using vue.js as a framework. I'm adding a sweetalert package in my project but whenever i use the toast function it gets me an error. I tried using other functions like swal.fire and it works except for toast.fire. Can someone help me with this? Here are some of my codes.
app.js
require('./bootstrap');
import Vue from 'vue'
import { Form, HasError, AlertError } from 'vform'
import moment from 'moment'
import VueRouter from 'vue-router'
import VueProgressBar from 'vue-progressbar'
import swal from 'sweetalert2'
window.Form = Form;
window.swal = swal;
window.toast = toast;
window.Vue = require('vue');
Vue.use(VueRouter)
Vue.component(HasError.name, HasError)
Vue.component(AlertError.name, AlertError)
const toast = swal.mixin({
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 3000
});
Vue.use(VueProgressBar, {
color: 'rgb(143, 255, 199)',
failedColor: 'red',
height: '2px'
})
const routes = [
{ path: '/dashboard', component: require('./components/Dashboard.vue').default },
{ path: '/profile', component: require('./components/Profile.vue').default},
{ path: '/users', component: require('./components/Users.vue').default}
]
const router = new VueRouter({
mode: 'history',
routes // short for `routes: routes`
})
Vue.filter('upText', function(text){
return text.charAt(0).toUpperCase() + text.slice(1);
});
Vue.filter('myDate', function(created){
return moment(created).format('MMMM Do YYYY');
});
Vue.component('dashboard', require('./components/Dashboard.vue').default);
Vue.component('profile', require('./components/Profile.vue').default);
Vue.component('users', require('./components/Users.vue').default);
const app = new Vue({
el: '#app',
router
});
Users.vue
<template>
//html codes
</template>
<script>
export default {
data(){
return{
users: {},
form: new Form({
name: '',
email: '',
password: '',
type: '',
bio: '',
photo: '',
})
}
},
methods: {
loadUsers(){
axios.get("api/user").then(( {data }) => (this.users = data.data));
},
createUser(){
this.$Progress.start();
this.form.post('api/user');
toast.fire({
type: 'success',
title: 'User Created',
position: 'top-end',
})
this.$Progress.finish();
}
},
created() {
console.log('Component mounted.');
this.loadUsers();
}
}
</script>
At the point this line runs, toast will be undefined:
window.toast = toast;
Note that the line const toast = swal.mixin({ comes later. You would need to write these lines the other way around.
Personally I wouldn't expose these directly on window in the first place. Either import them as required or add them to the Vue prototype:
Vue.prototype.$toast = toast
You'd then use it by calling this.$toast.fire in your components.
You have to call toast.fire in then event of axios.post as below,
createUser(){
this.$Progress.start();
axios.post('api/user', this.form).then(response => {
toast.fire({
type: 'success',
title: 'User Created',
position: 'top-end',
})
this.$Progress.finish();
}).catch(error => {
this.$Progress.finish();
});
You can handle success and failure and show toast messages .then and .catch event respectively.
Hope this helps.