Vuejs: declaring parent component in child component - vue.js

My app has a component:
export default {
name: 'category',
props: {
ref: Object,
asLabel: Boolean
},
components: {
Products
}
}
In Products component, the template has:
<category :asLabel="true" :ref="ref"/>
In component declaration:
components: {category}
This usage throws an error:
custom element: <category> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
So I am trying to use ancestor component inside a child component. Is there anything I am missing?

This is something that's prevented by webpack/browserify. You need to use asynchronous imports to import your parent component in child. Something like:
components: {
category: () => import('./path-to-category/category.vue')
}
Please read the docs here to know why that happens https://v2.vuejs.org/v2/guide/components-edge-cases.html#Circular-References-Between-Components.

Related

Vue Test Utils: how to pass Vuelidate validation rules to child components?

while trying to write a component test by using vue test utils, testing interaction between child components and stuff, I am stuck due to usage of Vuelidate from child components. Below is an example simplified:
// parent component code
<template>
<div>
<childA />
</div>
</template>
//childA code
<template>
<input v-model="value" />
</template>
<script>
...
validations: {
value: {
required
}
}
...
</script>
// parent component test
...
const wrapper = mount(MyParentComponent, {
...,
components: {
childA,
},
validations: {
value: required
},
...
})
I have tried to find a solution out there that I could mount (note here that I WANT to mount also the child components, so shallow-mount is not what I look for) the child component, with it's respective Vuelidate validation rules, but I still haven't found any solution.
Instead, my test gives me errors like:
Cannot read property `value` of undefined
which makes sense, since the test cannot access the child component's $v instance.
Has anyone achieved it so far?
For answering your question and after i've did some test i believe you missed the data part inside your mount
mount: render child components
shallowMount: doesn't render child components
MyParentComponent need to have in the options the structure of you're child component so this is why he is returning the error
And i saw that you're passing the import of your component directly but don't forget that your test folder is outside of your src folder
import ChildA from "#/components/ChildA";
will not work instead i propose to use absolute path directly to import your child component or use a configuration to resolve them
const wrapper = mount(MyParentComponent, {
data() {
return {
value: null
}
},
components: {
ChildA: () => import('../../src/components/ChildA'),
},
validations: {
value: required
},
})

How to get all the props that a parent component has inside a child component In vue js?

How to get all the props like $store, $parent, $root everything that a parent component has inside a child component?
So I'm creating a parent component and a child.
However I don't have anything to render within the child. So I'm creating a renderless child component.
However I'm programatically inserting new html elements via child component
following piece of code is the parent component where I mount the child component.
This is the method I found online.
This is working fine. But I'm not getting the props like this.$store , this.$parent and all (which are automatically available inside the parent component) in the child component.
import { Child } from "./components/child";
export default {
name: "parent",
components: {},
props: [],
data() {
return {};
},
computed: {},
created() {
new Child().$mount();
},
mounted() {},
methods: {},
};
This is the child component.
import Vue from "vue";
const CHILD = {
name: "child",
components: {},
props: [],
data() {
return {};
},
render() {
return;
},
computed: {},
created() {},
mounted() {},
methods: {},
};
export const Child = Vue.extend(CHILD);
So the basic idea is to create child component classes having all the options like $store $el and all (everything vue provides).... but instead of instantiating it inside the template I want to instantiate them in the parent component like this: new Child({...props}).
So is that possible. I'm doing this because my child components are renderless. (But within the child components I'm creating Dom elements..., & the reason I want to extend all the functionalities provided by vue is because in that way I don't want to write my own store, my own event emitter, my own prop binder.... everything will be automatically available...)
KEY TAKEAWAY is that I want to create Child components manually like by calling new Child() rather than registering them as components inside the parent as components: {'app-child': Child} and instantiating them inside the parent template ... Along with that I want every functionalities provided by vue inside the child component.. something like extending vue..
Also How can I listen to events from the child created as above ...
something like this.
// child
created() {
this.$emit('event')
}
//parent
mounted() {
this.child.$on('event', console.log)
}
sources:
https://css-tricks.com/creating-vue-js-component-instances-programmatically/
https://css-tricks.com/building-renderless-vue-components/

Dynamic component inside a component that is rendered with render() function

I saw in the docs that you can have a dynamic component inside your VueComponent like this :
<component :is="componentName" v-bind="componentProps" #custom-event="doSomething" />
I am trying to have one of these dynamic components inside a dynamically rendered component (with the render() function, not with an HTML template). Without too much hope, I've tried this :
render(createElement: CreateElement) {
return createElement('component', props: {
'is': 'TestComponent'
});
}
but I got
[Vue warn]: Unknown custom element: <component> - did you register the component correctly?
So again, not hoping too much for a miracle, I tried to import Component and declare it as a component :
#Component({
components: {
Component,
TestComponent
}
})
export default class DynamicThingy extends Vue {
render(createElement: CreateElement): VNode {
return createElement('Component', {
props: {
'is': 'TestComponent'
}
});
}
}
But then I get
[Vue warn]: Do not use built-in or reserved HTML elements as component id: Component
Any idea how that could be possible ?
The first parameter of createElement() must be either
An HTML tag name,
component options,
or async function resolving to one of these.
https://v2.vuejs.org/v2/guide/render-function.html#createElement-Arguments
So in a render function, you can simply create a function* that returns one or another component's options based on your desired criteria, and let that be your first argument. *This function is identical to the function you'd write to determine what goes into the :is prop)
You only need the dynamic component <component /> and :is prop in a template where you don't have the possibility to do it programmatically.
You can use this smart-list component from the vue docs as an example.

vuejs-parent and child components

I am new in vuejs and Iam coding in laravel
I have watched vuejs tutorial but I have got a little confused
about parent and child components because when I started coding in laravel I just used a simple component and use it in blade and
I didn't feel needing parent component I want the usage and when to use
parent component because there were lots of documention for parent and child component I dont know when to use them.
parent component and child component is not the same, child component feeding by the parent as the prop, you can mutate data to child component by parent and emit data from child to parent for changed the prop.
for example:
////parent.vue////
<parent-component>
<child-component :item="items" :profile="profile"></child-component>
</parent-component>
export default {
data(){
items: {
id: 0,
name: 'Negar'
},
data2: {
id: 1,
name: 'Hozhabr^_^'
}
},
profile: {
url: 'http://www.alibaba.com',
company: 'alibaba',
city: 'Tehran'
}
}
//// child.vue /////
<template>
Item: {{items}}
profile: {{profile}}
</template>
export default {
props:['items', 'profile']
}

How to create a reusable component in VueJs?

I would like to create Side Panel as a reusable component in Framework7 with VueJS. Here is my code..
Card.vue
<f7-card>
<f7-card-header>Card header content</f7-card-header>
<f7-card-content><img src="https://wiki.videolan.org/images/Ubuntu-logo.png"></img></f7-card-content>
<f7-card-footer>Card footer content</f7-card-footer>
</f7-card>
Now i registered as a component like below,
import Vue from 'vue'
export default [
{
path: '/card/',
component: require('./Card')
},
]
In later vues i imported as,
import Card from './Card.vue'
and i try to access in another vues like,
Now i'm getting an error like
[Vue warn]: Unknown custom element: - did you register the
component correctly? For recursive components, make sure to provide
the "name" option.
Can anyone help me where have i mistaken?
Thanks,
It's not really clear from your code exactly what you are doing, but the error you are getting happens when you try to use a component as a child of another component without registering it in the parent's components setting like this:
<script>
import Card from './Card.vue'
export default {
data () {
return {
somedata: 'some value'
}
},
components: {Card: Card}, // <- you're missing this
// etc...
}
</script>
You can also register components globally. More here: https://v2.vuejs.org/v2/guide/components.html#Local-Registration
Are you showing us all of Card.vue? For a valid single-file vue component, I would expect to see <template>, <script> and <style> elements. The render function will be generated from whatever you put in the <template> element.
Make sure that the component that you want to reuse is wrapped inside a template tag
As follows
<template>
<div>
<component data/>
<div/>
<template/>
Then register it inside the parent
Like so
export default {
name: "Card",
components: {
Card
},
};