Reputation: 53
I'm new in VueJS and I am trying to create a custom form component.
I am using http://element.eleme.io elements. So I created a new Form.vue file
<template>
<el-form :model="data">
<slot></slot>
</el-form>
</template>
<script>
import { FormItem, Input } from 'element-ui';
export default {
name: 'general-form',
components: {
FormItem,
Input
},
props: ['data'],
mounted: function() {
console.log(this.data);
}
}
</script>
Here is my app.js
// Element.io
import { Form, FormItem, Input } from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
// Custom
import GeneralForm from '../../components/presentational-subsystem/form/Form.vue';
Vue.use(Form);
Vue.use(FormItem);
Vue.use(Input);
Vue.config.devtools = true;
var contactsPage = new Vue({
el: '#contacts-page',
components: {
GeneralForm
}
});
And here is my view:
<div id="contacts-page">
<general-form id="contacts-form" :data="{subject: 'abc'}" action="/contacts" method="post">
<el-form-item label="Subject" prop="subject">
<el-input v-model="data.subject"></el-input>
</el-form-item>
</general-form>
</div>
But I get this error in the console:
[Vue warn]: Property or method "formData" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
I know that if I change Vue object to this:
var contactsPage = new Vue({
el: '#contacts-page',
data: { formData: {} }
components: {
GeneralForm
}
});
the error disappears, but then form is not reactive any more. I tried to follow this example:
http://element.eleme.io/#/en-US/component/form
and my markup is actually the same, but when I use Vue dev tools, I can see that my formData variable inside my Form.vue component is different from the shared formData variable in my Vue instance.
My question would be how can I make <el>
elements use formData from my Form component that I created?
Upvotes: 4
Views: 24289
Reputation: 43899
When you use a slot
, its scope -- where its data comes from -- is the parent. The contents of your slot refer to formData
, which you define in the child. You can pass child data to slots using scoped slots
Alternatively, you could fully define formData
in the parent and pass it as a prop
to the child, which passes it on as a prop to el-form
.
This structure:
<el-form :model="formData">
<slot></slot>
</el-form>
has you passing formData
from your Form
component to the el-form
component. It does not pass to the slot. Slots are not children, they are injected code from the parent.
The parent code:
<general-form id="contacts-form" action="/contacts" method="post">
<el-form-item label="Subject" prop="subject">
<el-input v-model="formData.subject"></el-input>
</el-form-item>
</general-form>
is creating an instance of your Form
component and injecting an el-form-item
as slot content. The error you are getting is in referring to formData
in that slot content, because the slot's context is the parent. A slot does not know anything about what it's being injected into (unless you use scoped slots).
In the updated code:
<general-form id="contacts-form" :data="{subject: 'abc'}" action="/contacts" method="post">
<el-form-item label="Subject" prop="subject">
<el-input v-model="data.subject"></el-input>
</el-form-item>
</general-form>
You are passing a data
prop to the Form
child here, but trying to use it in the slot content. the el-input
is looking in the parent for data
. Try this:
var contactsPage = new Vue({
el: '#contacts-page',
data: {
data: { subject: 'abc' }
},
components: {
GeneralForm
}
});
and
<general-form id="contacts-form" :data="data" action="/contacts" method="post">
<el-form-item label="Subject" prop="subject">
<el-input v-model="data.subject"></el-input>
</el-form-item>
</general-form>
Upvotes: 3