I'm trying to create a custom component in Vue.
This is the simplest component I could come up with and the value prop is ALWAYS undefined.
<template>
<div>
- {{ value }} -
</div>
</template>
<script>
export default {
props: ['value'],
mounted() {
console.log(this.value);
}
}
</script>
Not doing anything special when I call it:
<el-text-group v-model="testVar"></el-text-group>
{{ testVar }}
The variable testVar shows fine, but the custom component shows nothing?
I've followed a bunch of tutorials and the official docs:
https://v2.vuejs.org/v2/guide/components.html#Form-Input-Components-using-Custom-Events
I'm using latest Vue 2.4.2. It seems to work fine with Vue 2.2.x.
I've actually had this issue months ago but thought I would wait to see if something got fixed. But testing again now and the issue is still there. No idea, seems very basic, not sure if there is some change on how to do this?
FILES:
app.js
var component = require('./components/App.vue');
component.router = Vue.router;
new Vue(component).$mount('#app');
App.vue
<template>
<div>
Hello
<hr/>
<test-cpt v-model="testVar"></test-cpt>
</div>
</template>
<script>
export default {
data() {
return {
testVar: 'test'
};
},
components: {
testCpt: require('./TestCpt.vue')
}
}
</script>
TestCpt.vue
<template>
<div>
- {{ value }} -
</div>
</template>
<script>
export default {
props: ['value']
}
</script>
Removing node_modules and reinstalling seemed to fix it.
Related
i want to import #heroicons/vue in Nuxt 3 but my icon not appear in frontend.
my setup:
import { HomeIcon, FilmIcon, PlusIcon } from "#heroicons/vue/solid"
my html:
<template v-for="(profileItem, i) in accountSetFields" :key="i">
<ProfileItems :user="user" :item="profileItem" />
<template v-slot:icon>
<component :is="profileItem.icon"></component>
</template>
</ProfileItems>
</template>
the variable profile.Item.icon has a string value of "HomeIcon"
I have tried to pass the value directly to the child component "ProfileItem.vue" but i receive the same error message.
When i pass the value directly as string ("HomeIcon" instead of profile.Item.icon) than it works because it mentioned the attribute from import { HomeIcon, FilmIcon, PlusIcon } from "#heroicons/vue/solid
<component :is="HomeIcon"></component>
Did anyone know how to load the icons dynamically?
That one works well
<script setup>
import { HomeIcon, FilmIcon, PlusIcon } from "#heroicons/vue/24/solid"
const icons = reactive({
home: HomeIcon,
film: FilmIcon,
plus: PlusIcon,
})
</script>
<template>
<component :is="icons.home"></component>
</template>
as explained here, you need the 24 in your import (for the size).
Not sure but this may also help maybe, didn't have to use that myself: https://github.com/tailwindlabs/heroicons/issues/564
Or you can forget about worrying about various icons configuration and fallback to that one (configured once and for all): https://stackoverflow.com/a/72055404/8816585
You can also use it without <component/> and register the icon as a component. Should also work with the composition api.
<template>
<CheckCircleIcon />
</template>
<script>
import { CheckCircleIcon } from "#heroicons/vue/24/solid";
export default {
components: {
CheckCircleIcon,
}
}
</script>
Problem: I am trying to programmatically register a component to be used in a slot in my Vue/Nuxt site. The component name is included in the data of the parent index.vue file, in this instance the component is named Projects. I am including it in a v-for template as the various objects in the 'modules' data array are iterated over. I had assumed this would be possible/easy from the dynamic component documentation and example however I have not managed to get it working in my case.
What I expect to happen: I expected the component to be registered and 'slotted' into the Module component correctly.
What actually happens: While I can see on the rendered view that the component is 'there', it is not in the correct place (i.e. slotted into the Module component). I also get a vue/no-unused-components error saying: The "Projects" component has been registered but not used.
I have read the documentation about component registration in modular systems but these seem to be for more complex cases than what I am trying to achieve. Any advice would be really helpful as I am totally stuck!
index.vue
<template>
<div>
<template v-for="module in modules">
<Module
:title="module.title"
:to="module.link"
/>
<component v-bind:is="module.slot" />
</Module>
</template>
</div>
</template>
<script>
import Module from '~/components/module/Module.vue'
import Projects from '~/components/module/slots/Projects.vue'
export default {
components: {
Module,
Projects
},
data () {
return {
modules: [
{
title: 'Work',
slot: 'Projects'
},
{
...
}
]
}
}
}
</script>
Edit: As a side note, I get the same error when registering the component with import like so:
components: {
Module,
'Projects': () => import('#/components/module/slots/Projects')
}
Module.vue
<template>
<div>
<h2>
{{ title }}
</h2>
<slot />
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
default: ''
}
}
}
</script>
Projects.vue
<template>
<div>
<h3>Projects</h3>
</div>
</template>
<script>
export default {
name: 'Projects'
}
</script>
You use the self closure tag in your Module component.
This prevents your Projects component to be rendered within the slot.
Just replace:
<Module
:title="module.title"
:to="module.link"
/>
with:
<Module
:title="module.title"
:to="module.link"
>
and it should work.
I want to store input-value from App.vue, and use it in another component. How can I do it? I don't need the show the value in the template, I just need the value inside other components function. In JS I could just use a global var, but how can I achieve it in Vue?
App.vue:
<template>
<div id='app'>
<!-- App.vue has search bar -->
<b-form-input #keydown='search' v-model='input'></b-form-input>
<div>
<!-- Here's my other components -->
<router-view />
</div>
</div>
</template>
<script>
export default {
name: 'App',
data () {
return {
input: '',
value: ''
}
},
methods: {
search () {
this.value = this.input
this.input = ''
}
}
}
</script>
Another component:
<template>
<div>
<p>I'm another component</p>
<p>App.vue input value was: {{value}} </p>
</div>
</template>
<script>
export default {
props: ['value'],
data () {
return {
value: ''
}
}
}
</script>
This is the basic logic I'm trying to achieve. Input value in App.vue --> anotherComponent.vue
If components are not parent and child you can use store for this:
More advanced vuex store that should be your default GO TO - NPM.
Or simple solution with js object.
a. Create store.js file and export object with property in which you will store value.
b. Import store.js object to vue scripts and use it simply like:
import Store from 'store.js'
Store.value
I am having trouble showing my JsonEditor component. This is the code that i am working with:
<template>
<v-app>
<div class="admin">
<v-alert v-if="info.showAlert"
value=true
:type="info.alertType">
{{info.message}}
</v-alert>
<h2>Welcome to scope360 admins area. A place to edit scope360 configurations</h2>
<v-btn class="test" #click="switchEditClicked">{{switchButtonMessage}}</v-btn>
<div class= "editorComponents">
<div v-if="showJsonEditor" class="editor">
<json-editor is-edit="true" v-model="editedConfig" ></json-editor>
<v-btn #click="previewClicked">Preview Changes</v-btn>
</div>
<div v-if="!showJsonEditor" class="jsonDiff">
<vue-json-compare :oldData="originalConfig" :newData="editedConfig"></vue-json-compare>
<v-btn #click="saveClicked">Save</v-btn>
<v-btn #click="cancelPreviewClicked">Cancel</v-btn>
</div>
</div>
</div>
</v-app>
</template>
<script>
import JsonEditor from 'vue-edit-json'
import vueJsonCompare from 'vue-json-compare'
import{getConfig,updateConfig} from "../utils/network";
export default{
components: {
'vue-json-compare' : vueJsonCompare,
'json-editor' : JsonEditor
},
data: function () {
return {
originalConfig: {},
editedConfig: {},
showJsonEditor: true,
switchButtonMessage: "plain text",
info : {
showAlert: false,
alertType: "success",
message: ""
},
}
},
What am i missing? There is no errors when running. I am retrieving information from my backend to display some JSON information.
*The component has worked before, after som changes in design it stopped working
*Yes, i have checked if the data i am retrieving to display is correct and exists
Update
I made it work again but i would still love to know why my first attempt is not working?
This works:
import Vue from 'vue'
Vue.use(JsonEditor)
components: {
'vue-json-compare' : vueJsonCompare
},
//HTML
<JsonEditor is-edit="true" v-model="editedConfig" ></JsonEditor>
Update 2, Link to JsonEditor
https://www.npmjs.com/package/vue-edit-json
To answer your question on why it's not importing the component with your first approach. That's because the author decided to make it a plugin instead of importable component. (See Vue docs on plugin).
Such that when you do import on this component, it may be imported but never rendered since it's written without exporting the default module.
If you need to register this component by the import keyword, you could specify the complete path to the component file itself.
import JsonEditor from "vue-edit-json/src/JsonEditor";
new Vue({
components: {
JsonEditor
}
}
And that should give you the same effect.
BTW, a quick tip for you:
When defining a component with PascalCase, you can use either case when referencing its custom element. That means both <my-component-name> and <MyComponentName> are acceptable.
So in your case, since you seem to want to have the components in kebab-case, you could drop the component "alias" name from the components object.
import VueJsonCompare from 'vue-json-compare';
components: {
VueJsonCompare
}
// ...
<vue-json-compare :oldData="originalConfig" :newData="editedConfig"></vue-json-compare>
In Vue2, I have a string along the lines of the following in my component.
<template>
<div><h1>Hello World</h1>
<div v-html="testString"></div>
</div>
</template>
<script>
export default {
name: "test-component",
props: ['incoming'],
data: function() {
return {
testString: "";
}
},
created() {
this.testString = this.incoming;
}
}
</script>
And then when I do the following (with all the imports done correctly)
<template>
<text-component :incoming="mycontent"></text-component>
</template>
<script>
import 'test-component' from './path/to/test-component.vue'
export default { // etc, just presume this bit is right, it's only psudo code
components: ['test-component'],
data() { return { mycontent: '' }},
created() {
this.mycontent="I just want to <router-link to='/home' v-html='Go Home'></router-link>"
</script>
So now I want the first template with testString to render the <router-link> as if I had put it in myself directly.
I've tried v-html and {{ }} , in my test-component but I think i'm missing something. I'm pretty sure in Vue1 I would use {{{ }}}.
Can anyone help out? Thanks.
From the documentation on v-html:
Note that the contents are inserted as plain HTML - they will not be compiled as Vue templates.
You should be using a slot instead.
Add the slot to your testComponent:
<template>
<div><h1>Hello World</h1>
<slot></slot>
</template>
And then just put the content right in the test-component tag:
<template>
<test-component>
I just want to <router-link to='/home' v-html='Go Home'></router-link>
</test-component>
</template>