Vue "emit" alternative - vue.js

Vue complain when I use "emit" I'm looking for a same-functioning alternative
It will be a todo list
Code:
<button #click="$emit('delete-todo-event', todo.id)">Button</button>
Warnig in the Browser-Console:
runtime-core.esm-bundler.js?5c40:38 [Vue warn]: Extraneous non-emits event listeners deleteTodoEvent) were passed to component but could not be automatically inherited because component renders fragment or text root nodes. If the listener is intended to be a component custom event listener only, declare it using the "emits" option. at <ToDos todoEntries= (9) [Proxy, Proxy, Proxy, Proxy, Proxy, Proxy, Proxy, Proxy, Proxy] onDeleteTodoEvent=fn<bound deleteToDoItem> > at <App>

You seem to be using Vue 3. The warning tells you that you did not declare your event before using it in your component. Here is an example:
export default {
name: "YourComponent",
emits: ["deleteTodoEvent"], // <--- this is what the warning in hinting to
setup(_,{ emit }) {
...
},
};

Related

(NUXT) How to add component in sweet alert 2

I tried to add a component in swal by the following method.
this.$swal({ html: '<Card :assignment="{}"></Card>' })
But it ends up giving me this error,
error: The "Card" component has been registered but not used vue/no-unused-components
Any leads will be appreciated
The error you're receiving is just a linting error being thrown. It's being thrown because the linter expects you to use the Card component inside the tags.
Try the following:
// inside your Vue component
components: {
// eslint-disable-next-line vue/no-unused-components
Card
}

Vue 3 composition API, how to get context parent property in the setup() function?

I'm running into an issue with Vue 3 (alpha 4):
Inside the setup() function I am trying to read the parent component. As per the documentation on https://vue-composition-api-rfc.netlify.com/api.html#setup it should expose the parent via the context argument, either as a property of context.attrs or directly as parent (see the SetupContext bit under 'typing'). I don't find the documentation to be very clear on whether parent should be accessed directly from SetupContext, or via SetupContext.attrs, so I've tried both ways, but to no avail.
Here's my issue, I can access the SetupContext and SetupContext.attrs (which is a Proxy) just fine when logging them. SetupContext.attrs exposes the usual proxy properties ([[Handler]], [[Target]] and [[IsRevoked]]) and when inspecting [[Target]] it clearly shows the parent property.
When logging the parent though, it just prints out undefined:
export default {
setup(props, context) {
console.log(context);
// Output: {attrs: Proxy, slots: Proxy, emit: ƒ}
console.log(context.attrs);
// Output: Proxy {vnode: {…}, parent: {…}, appContext: {…}, type: {…}, root: {…}, …}
console.log(context.attrs.parent);
// Output: undefined
}
};
Spreading the context yields the same result:
export default {
setup(props, { attrs, parent }) {
console.log(attrs);
// Output: Proxy {vnode: {…}, parent: {…}, appContext: {…}, type: {…}, root: {…}, …}
console.log(attrs.parent);
// Output: undefined
console.log(parent);
// Output: undefined
}
};
I'm a bit new to proxies in JavaScript, but from what I've read on them, and from experimenting with proxies returned by reactive() for example. I should just be able to access the property like I normally would with an object. Any ideas on what I'm doing wrong?
I've created a codesandbox to reproduce the problem
You can use getCurrentInstance. It is undocumented Vue feature.
Usage is as easy as:
import { getCurrentInstance } from "vue";
export default {
setup(props) {
const instance = getCurrentInstance();
console.log("parent:");
console.log(instance.parent);
}
}
Vue considers it an internal api and warns against using it. For your consideration, you can read this github issue and this documentation from wayback machine.
Also, probably worth noting that Vue composition api plugin exposes parent in the same way, but it is referenced as instance.$parent there.
I know this doesn't answer the question directly, but using provide/inject (https://v3.vuejs.org/guide/component-provide-inject.html) has helped me resolve this same issue where I wanted to get a data attribute from the parent node and to pass it to the rendered component, but could not access the parent anymore after upgrading from Vue2 to Vue3. Rather than trying to expose the parent, I passed a prop from its dataset down to the rendered component.
Upon creating the app, I did the following.
main.js
import { createApp } from "vue";
import MyComponent from './components/MyComponent.vue';
const section = document.getElementById('some-element'); // this element contains a data-attribute which I need to use within the app. In my case, I can't get the data from the component created/mounted function as the section with the data attribute is loaded onto the page multiple times with different attributes each time.
const app = createApp(MyComponent);
app.provide('dataset', section.dataset.id); // section.dataset.id contains some kind of id, let's say 'abc123' for the sake of this example
app.use(store); //not relevant for this answer
app.mount(section);
Then, inside the component, I could access the 'dataset' by doing the following.
MyComponent.vue
<template>
<div>Normal template stuff here</div>
</template>
<script>
export default {
name: 'MyComponent',
inject: ['dataset'], // the magic
created() {
console.log(this.dataset); // will log 'abc123'
}
}
</script>
This is very stripped down, but shows my case nicely i guess. In any case, if you're trying to do something similar and want to get data via parent data attribute, you could look into provide/inject.
Hope it helps anyone out there!

Problem displaying components that use $route with vue-styleguidist

I have some components that use this.$route internally, for various things. Some simplified examples would be, using this.$route.name to lookup a i18n string for the page:
<h1>New {{ $t($route.name + '.label') }}</h1>
or watching the $route and loading something:
watch: {
$route: {
handler: 'loadItem',
immediate: true
}
}
Whenever these components appear in vue-styleguidist, I get various errors in the browser console and nothing renders for the component example:
index.js?1ef8:1 [Vue warn]: Error in callback for immediate watcher "$route": "TypeError: Cannot read property 'id' of undefined"
found in
---> <MyComponent> at src/components/MyComponent.vue
<Anonymous>
<Root>
I am deliberately not importing vue-router or my routes objects into the styleguide, because this isn't supported - and it causes lots of problems with redirects, route guards, etc... which aren't relevant to the style guide.
What I really want to do, I think, is to mock this.$route inside the components when they appear in the styleguide - but I can't figure out how to do that.
Another option would be to pass the route information into the components as props. This would properly decouple the components from the router and fix the issue, but it will involve changes to every component and route.
So, I ended up refactoring all my components to pass in the route properties that they were using as properties. This properly decouple the components from the router and fix the issue, but it was a lot of work.

How to use events of vue-tel-input?

I've installed vue-tel-input component and included it. I want to use the validate event tha's found in a link! but I can't. How to use it in the compoennt?
The events are regular vue component events.
You can listen for these events as outlined here in the vue docs.
https://v2.vuejs.org/v2/guide/components.html#Listening-to-Child-Components-Events
For example, to use the validate event you would add a listener to the vue-tel-input component.
The listener will automatically pass the arguments to your method.
// In your template
<vue-tel-input
v-model="yourModel"
#validate="yourValidationMethod"
/>
// In your component methods
yourValidationMethod: function ({ number, isValid, country }) {
// Do stuff with the arguments passed by the vue-tel-input component
},
Have your tried with Info from their page ?
In main.js
import Vue from 'vue'
import VueTelInput from 'vue-tel-input'
Vue.use(VueTelInput)
and then use it as component
<template>
<vue-tel-input v-model="phone"></vue-tel-input>
<template>

Vue.js: how to use the afterEnter hook with an async component

I would like to use JS Hook as described here. Specially, I want to use the afterEnter hook with an async component.
This is my async component:
Vue.component('example', function(resolve, reject){
let data = {
text: 'test data',
};
$.post('http://example.com', data, function(r){
r = JSON.parse(r);
if( r.success ) {
resolve({
template: r.data,
afterEnter: function(el, done){
console.log('test');
}
});
}
});
});
This is what the ajax call gets from the server, and it's what is passed to the template in r.data.
<transition v-on:after-enter="afterEnter"></transition>
These are the two errors that I get.
[Vue warn]: Property or method "afterEnter" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
[Vue warn]: Invalid handler for event "after-enter": got undefined
Is it possible to use JS hooks with async components? And if not, how should I approach this? My objective is to run custom JS after Vue (and/or vue-router) inject the component template onto the page, so that I can initiliaze image sliders and whatnot. It is important that my custom JS fires every time the component is navigated to, and not only on the first load.
Thank you.
That warning means that Vue is looking for (but unable to find) a property or method named "afterEnter", which you reference in your template. You have defined afterEnter in your resolve function as if it is a lifecycle hook, but it needs to be one of your Vue instance's methods.
So, your resolve function should look like this:
resolve({
template: r.data,
methods: {
afterEnter: function(el, done) {
console.log('test');
}
}
});