I am trying to add a toast to my code as per below, however no toast message appears and I dont get any errors in the console. The code works however and the invite gets sent. I have used it like this in other files and the toast message appears so im uncertain as to why it wouldn't appear now.
Main.js file where I am importing toast and toast service:
import Toast from 'primevue/toast';
import ToastService from 'primevue/toastservice';
const app = createApp(App);
app.component('Toast', Toast);
app.use(ToastService);
In my file using the toast once an invite is sent if successful I want to display the success message:
<template>
<div class="main-container">
<Button #click="sendInvites"/>
</div>
</div>
</template>
<script>
export default {
data() {
return {
};
},
methods: {
createToast() {
get('CreateInvites', { invites: this.invites.filter((invite) => invite.email.length > 0) }).then((data) => {
if (data.length > 0) {
this.$toast.add({
severity: 'error',
summary: 'Unable to send some invites',
detail: data
})
.join('\n'),
life: 9000,
});
}
else {
this.$toast.add({
severity: 'success',
summary: 'Success!',
life: 3000,
});
}
});
},
},
The ideal location of a Toast is the main application template so that
it can be used by any component within the application.
So, you need to use the <Toast> component in your main file (App.vue) like this-
<template>
<Toast />
<template>
It means the Toast component is mounted while App is loaded into the DOM and it is ready to be displayed upon any event's trigger as you did-
this.$toast.add({
severity: 'error',
summary: 'Unable to send some invites',
detail: data
.map((detail) => {
return `${detail.email}: ${detail.error}`
})
.join('\n'),
life: 9000,
})
For more information, read here- https://primefaces.org/primevue/toast
Related
I am settting up an auth middleware which runs just fine, however when I am creating the error I just get to the default error page. I need to reach the custom ~/error.vue to insert a button to click clearError()
Docs says I can just add an error component in the source, which I did.
If ~/error.vue is not reachable from ~/server/middleware then how can I call clearError() in the default error page?
in ~/server/midddleware/auth/auth.ts
export default defineEventHandler(async (event) => {
if(conditionNotMet){
throw createError({
statusCode: 404,
name: 'NotFoundError',
message: 'Todo not found',
statusMessage: "Not Found",
})
}
}
~/error.vue
<template>
<div>{{ props.error }}</div>
</template>
<script setup>
const props = defineProps(['error'])
</script>
This is what I see instead
https://nuxt.com/docs/getting-started/error-handling
In my Vue.js project, I want to display my 404 page, if a route parameter is invalid. For now, I'm using the following code for that:
this.$router.replace({ path: '/404' });
Is there a way to do that without modifying the URL? I want the user to still be able to copy the browser's original URL line. Is there some kind of a silent: true parameter?
With vue-router, the URL is the source of truth. If the URL changes, so does the rendering. You can't "pause" the router. (This is a flaw in vue-router that has been bugging me for ages, but I digress.)
You just have to display the 404 page without modifying the route. Have some display404 data property in your root component that you can set to display the 404 page manually in the template instead of the <router-view>, e.g:
<div>
<my-404-page v-if="display404"/>
<router-view v-else/>
</div>
To display the 404 page from any component:
this.$root.display404 = true
Of course this is just a basic example to demonstrate what I mean, you might want to use Vuex to share the state, or use an event bus, or you can display the 404 page in some other way that works for you, etc.
This was fixed in Vue Router 4 which you can see on the second example in the docs.
Build your NotFound route like this:
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: NotFound
},
Then you can use a beforeEnter navigation guard on your dynamic Vue like so:
// In your router/index.js file...
{
path: 'users/:id',
name: 'User Detail',
component: UserDetail,
beforeEnter(to, from) {
// See if that query exists in your data...
const exists = data.users.find(
user => user.id === parseInt(to.params.id)
)
if (!exists) {
// THE IMPORTANT PART
// Return your not found view...
return {
name: 'NotFound',
// Match the path of your current page and keep the same url...
params: { pathMatch: to.path.split('/').slice(1) },
// ...and the same query and hash.
query: to.query,
hash: to.hash,
}
}
}
}
Haven't tested this in a Component yet, but I'd assume it'd be the same logic in the beforeRouteEnter navigation guard.
Not 100% sure what you are asking, but is either of these any help?
A catch all route:
From Vue.js docs "Catch all route"
Or if you are managing a response form a call (method/fetch/ etc): Use a combination of try/catch and a "loading" data value to change the display or what component is loaded.
Based on Decade Moon's solution, I did the following:
main.js
import Error404 from './views/error/404.vue'
Vue.component('error-404', Error404)
404.vue
<template>
<div>
<h1>Page not found</h1>
<p>Whatever...</p>
</div>
</template>
<script>
export default {
name: 'Page not found'
}
</script>
router --> index.js
const PageNotFound = () => import('#/views/error/404')
function configRoutes() {
return [
{
path: '/',
name: 'Home',
component: TheContainer,
children: [
// ...
{
path: '404',
name: 'Page not found',
component: PageNotFound,
alias: '*'
}
]
}
]
}
My Page which should display the 404 error
<template>
<div class="animated fadeIn" v-if="clientSettings">
...
</div>
<error-404 v-else></error-404>
</template>
<script>
export default {
name: 'Test',
data() {
return {
clientSettings: null
};
},
async created() {
this.setClientConfig();
},
watch: {
'$route.params.id': function (id) { this.setClientConfig(id);}
},
methods: {
setClientConfig(id) {
if (!id) {
id = this.$route.params.id;
// Redirect to the first valid list, if no parameter is proviced
if (!id) {
this.$router.push({ name: 'Test', params: { id: this.$root.clientConfiguration[0].name } });
return;
}
}
// Set client settings
this.clientSettings = this.$root.clientConfiguration.find(cc => cc.name === id);
// This will return null, if no entry was found, therefore the template will jump into the v-else
}
}
}
</script>
I am working with vuejs and vue-router in Rails app. I have a button which calls a nivagate method. When user clicks on this navigate method, it hits an API enpoint via axios module and move to next component using this.$router.push({name: "RouteName"}). Problem is, when user clicks multiple on this button it gives Uncaught (in promise) undefined error in console. My guess is this error occurs because of vue-router.
My question is, how can I catch or handle this error. I am using multiple such buttons in my app so I need a generic solution.
Home.vue - component
<template>
<div>
<button
id="select_button"
#click="onSelectClick"
>
Select
</button>
</div>
</template>
<script>
export default {
onSelectClick() {
this.$`enter code here`axios.get('some-url').then(res => {
//print res on console
}).catch(err => {
// print err on console
})
this.$router.push({ name: 'route-name' }); //route-name != home
}
}
</script>
<style>
</style>
Error I get when I double(or more)-click on button
Uncaught (in promise) undefined
Error Cause: vue-router causes this error when we call this.$router.push({name: 'route-name'}) back to back multiple times without completing the previous call.
Solution: I can handle this error by adding a catch guard on router.push.
this.$router.push({name: 'router-name'}).catch(error => { //handle error here})
I made it generic by adding a method in vue mixin.
import router from '../router'
Vue.mixin({
methods: {
navigate(route) {
router.push(route).catch(err => { //handle error here });
}
}
});
Now I can use this navigate method in my components like this.
<template>
</template>
<script>
export default {
mounted() {
this.navigate({name: 'Home'})
}
}
</script>
<style>
</style>
Hope it helps others.
next({name: 'Login'})
causes Uncaught (in promise)...
I replaced it with
router.push({name: 'Login'})
return
and no error!
I am trying to add a Google Sign-In button to my Vue.js application and I found the vue-google-oauth2 plugin. I installed it and followed exactly the sample.html code to integrate it in my application, this way:
<template>
<div>
<h1>Test</h1>
<button #click="handleClickSignIn" :disabled="!isLoaded">signIn</button>
</div>
</template>
<script>
/**
* You should first need to place these 2 lines of code in your APP ENTRY file, e.g. src/main.js
*
* import GAuth from 'vue-google-oauth2'
* Vue.use(GAuth, {clientId: '4584XXXXXXXX-2gqknkvdjfkdfkvb8uja2k65sldsms7qo9.apps.googleusercontent.com'})
*
*/
export default {
name: 'test',
props: [],
components: {
},
data () {
return {
isLoaded: false
}
},
computed: {
},
methods: {
handleClickSignIn(){
this.$gAuth.signIn(function (user) {
//on success do something
console.log('user', user)
}, function (error) {
//on fail do something
})
}
},
mounted(){
let that = this
let checkGauthLoad = setInterval(function(){
that.isLoaded = that.$gAuth.isLoaded()
console.log('checked', that.isLoaded)
if(that.isLoaded) clearInterval(checkGauthLoad)
}, 1000);
}
}
</script>
The problem is that the isLoaded() method never returns true, with the Google Chrome console telling me every time I press on the button that the google api is not ready, that is the plugin console message printed when the GoogleAuthInstance is false. Could anyone help me?
Use isInit instead of isLoaded as the latter will be/is deprecated.
Add to main.js
import GAuth from 'vue-google-oauth2'
Vue.use(GAuth, {
clientId: '....apps.googleusercontent.com',
scope: 'email',
prompt: 'consent',
fetch_basic_profile: true
})
new Vue({
...
render: (h) => h(App),
}).$mount("#app");
UPDATE:
Can anyone help? I have been pursuing this without luck for the better half of this week. I do notice that the client is generating two POSTs. I have added code for the adapter. Is there anywhere else I should be looking?
I am going through the video tutorial provided below and am unable to resolve two errors when I click the submit button to save data to the database.
No model was found for 'user'
Two POSTs are being generated. This results in an Assertion Failed error, which I suspect is because the ID returned from the server does not match the current ID on the front-end.
I see that the database has two new records. When I click on the submit button again then the application takes me back to the todo-items page where it shows the two records. Can anyone advise what I am doing wrong?
Current versions:
Ember : 3.2.2
Ember Data : 3.2.0
jQuery : 3.3.1
Ember Simple Auth : 1.7.0
Video tutorial (the error occurs at the 11:30 mark): https://www.youtube.com/watch?v=bZ1D_aYGJnU. Note: the author of the video seems to have gotten the duplicate POST issue to go away right at the end of the video, but I do not see how.
Component/forms/todo-item-form/component.js
import Component from '#ember/component';
export default Component.extend({
actions:{
save(){
this.get('submit')();
}
}
});
Component/forms/todo-item-form/template.hbs
<form {{action "save" on="submit"}}>
{{input placeholder="description" value=todoItem.description}}
<br />
{{#if todoItem.validations.isValid}}
<button type="submit">Add</button>
{{else}}
<button type="submit" disabled>Add</button>
{{/if}}
</form>
templates/s/todo-items/add.hbs
{{forms/todo-item-form
todoItem=model
submit=(route-action "submitAction")
}}
{{outlet}}
models/todo-item.js
import DS from 'ember-data';
import { validator, buildValidations } from 'ember-cp-validations';
const { attr, belongsTo } = DS;
const Validations = buildValidations({
description: [
validator('presence', true),
validator('length', {
min: 4
})
]
});
export default DS.Model.extend(Validations, {
description: attr('string'),
owner: belongsTo('person')
});
adapter/Application.js
import DS from 'ember-data';
import ENV from 'todo-list-client/config/environment';
const {computed, inject :{service} } = Ember;
export default DS.JSONAPIAdapter.extend({
session: service(),
namespace: ENV.APP.namespace,
host: ENV.APP.host,
headers: computed('session.data.authenticated.token', function() {
let token = this.get('session.data.authenticated.access_token');
return { Authorization: `Bearer ${token}` };
}),
})
routes/s/todo-items/add.js
import Route from '#ember/routing/route';
export default Route.extend({
model(){
return this.store.createRecord('todo-item');
},
actions: {
submitAction() {
this.get('controller.model')
.save()
.then(() => {
this.transitionTo('s.todo-items');
});
}
},
});
The author adds Ember-Data-Route at about 15m5s for the add.js route as a mixin. This cleans up after the model.
He starts the explanation at that point, adds it in over the next minute or two in the video:
https://youtu.be/bZ1D_aYGJnU?t=15m5s
import Ember from 'ember';
import DataRoute from 'ember-data-route';
export default Ember.Route.extend(DataRoute, {
model() {
return this.store.createRecord('todo-item');
},
actions: {
save() {
this.get('controller.model')
.save()
.then(() => {
this.transitionTo('s.todo-items');
});
}
},
});