How can i pass the value entered into Name and Adres input to the Parent vue?
Parent (App.vue):
<form-group-input-text
:label="'test'"
:labelvalue="'Name'"
:inputplaceholder="'Name'"
:inputname="'Name'"
:inputvalue="''"
:inputclassname="''"
:inputid="'Name'"
:validation="'required|min:3|max:5'">
</form-group-input-text>
<form-group-input-text
:label="'testt'"
:labelvalue="'Adres'"
:inputplaceholder="'adres'"
:inputname="'adres'"
:inputvalue="''"
:inputclassname="''"
:inputid="'adres'"
:validation="'required'">
</form-group-input-text>
Child:
<form-label
:label="inputid"
:labelvalue="labelvalue">
</form-label>
<form-error :inputname="inputname"></form-error>
<form-input-text
v-on:input="handleTitle"
:validation="validation"
:inputplaceholder="inputplaceholder"
:inputname="inputname"
:inputvalue="inputvalue"
:inputclassname="inputclassname"
:inputid="inputid">
</form-input-text>
import Error from '../../form/validation/Error.vue'
import Label from '../../form/Label.vue'
import Input from '../../form/InputText.vue'
export default {
data: function () {
return {
inputvalue: ''
}
},
components: {
'form-label': Label,
'form-input-text': Input,
'form-error': Error
},
props: {
label: String,
labelvalue: String,
inputplaceholder: String,
inputname: String,
inputclassname: String,
inputid: String,
validation: String
},
methods: {
handleTitle: function (evt) {
this.inputvalue = evt.target.value
},
}
}
Child from child:
<input type="text"
v-on:input="updateValue($event)"
v-validate="validation"
:placeholder="inputplaceholder"
:name="inputname"
:value="inputvalue"
:class="{
'form-control':'form-control',
'alert alert-danger': errors.has(inputname),
'alert alert-success': $validator.fields.find({ name: inputname })
&& $validator.fields.find({ name: inputname }).flags.dirty
&& !errors.has(inputname)
}"
:id="inputid"
>
<script>
export default {
inject: ['$validator'],
props: {
inputplaceholder: String,
inputname: String,
inputvalue: String,
inputclassname: String,
inputid: String,
validation: String
},
methods: {
updateValue: function (evt) {
this.$emit('input', evt)
}
}
}
</script>
The common way is to use emit() to dispatch an event to the parent component.
https://v2.vuejs.org/v2/guide/components.html#Emitting-a-Value-With-an-Event
You can use it with v-model, too https://v2.vuejs.org/v2/guide/components.html#Using-v-model-on-Components
Related
How can i use a condition to change the value of these props? In the component i want to set the props value to another one if none are passed. For example, if no title are passed i want to set that to some static string instead. How would i do that?
Component:
<template>
<vue-headful
:title="this.title"
:description="this.description"
:url="this.url"
:image="this.image"
/>
</template>
<script>
import vueHeadful from "vue-headful";
export default {
name: "Meta",
components: { vueHeadful },
props: {
title: String,
description: String,
url: String,
image: String
}
};
Here's how im using it in another file:
<Meta title="test" />
You can set a default value into each prop:
export default {
name: "Meta",
components: { vueHeadful },
props: {
title: {
type: String,
default: ''
},
description: {
type: String,
default: 'foo'
},
url: {
type: String,
default: 'www.example.com'
},
image: {
type: String,
default: '/some/path'
}
}
};
You have a lot of interesting settigs for props in the docs: https://vuejs.org/guide/components/props.html#prop-validation
You can use computed properties:
https://vuejs.org/guide/essentials/computed.html
you can set a default value for title like this:
{
title: {
type: String,
default: 'YOUR DEFAULT TITLE GOES HERE'
}
}
Until now I was using a computed property with a v-if in my component to avoid it to render if basic props was not given, for example :
<template>
<div v-if="basicPropsProvided">
Blabla
</div>
</template>
<script>
export default{
props: {
icon: { type: String, required: true },
title: { type: String, required: true },
url: { type: String, required: true }
},
computed: {
basicPropsProvided(): boolean {
return !!this.title && !!this.icon && !!this.url
}
}
}
</script>
I tried to move this logic to the setup method, without success. Do you think there is a way to do this with the composition api to reuse the logic on other components ?
Define a composable function called useCheckProvidedProps which takes props as parameter and returns the computed property :
<template>
<div v-if="basicPropsProvided">
Blabla
</div>
</template>
<script>
import {computed} from 'vue'
function useCheckProvidedProps (props){
return {
basicPropsProvided:computed(()=>!!props.title && !!props.icon && !!props.url)
}
}
export default{
props: {
icon: { type: String, required: true },
title: { type: String, required: true },
url: { type: String, required: true }
},
setup(props){
const {basicPropsProvided}=useCheckProvidedProps (props)
return {basicPropsProvided}
}
}
</script>
just trying out creating components with the render function, but I am getting a weird warning:
Following component:
import Vue, { CreateElement, VNode } from 'vue'
export default Vue.extend({
name: 'p-form-input',
props: {
type: String,
name: String,
value: {
type: [ String, Number ]
},
placeholder: String,
disabled: Boolean
},
data() {
return {
localValue: ''
}
},
watch: {
value(value) {
this.localValue = value
}
},
mounted() {
this.localValue = this.$props.value
},
methods: {
onInput(e: any) {
this.localValue = e.target.value
this.$emit('input', this.localValue)
},
onChange(e: any) {
this.localValue = e.target.value
this.$emit('change', this.localValue)
}
},
render(h: CreateElement): VNode {
return h('input', {
class: 'form-control',
domProps: {
disabled: this.$props.disabled,
type: this.$props.type,
name: this.$props.name,
placeholder: this.$props.placeholder,
value: this.localValue
},
on: {
input: this.onInput,
change: this.onChange
}
})
}
})
A v-model="inputValue" on the component does trigger a input/change on inputValue but im getting the warning?
Using vue 2.6.11!
Edit:
Don't mind the ts-ignore, it complains about no types found for it, so that's more cosmetic!!!
<template>
<div id="app">
<p-form-input type="text" name="some_input" v-model="inputValue" /> {{ inputValue }}
</div>
</template>
<script lang="ts">
import Vue from 'vue'
// #ts-ignore
import PFormInput from 'vue-components/esm/components/form-input'
export default Vue.extend({
name: 'App',
components: {
PFormInput,
},
data() {
return {
inputValue: 'fdsdsfdsf'
}
}
});
</script>
You have a prop named "value' and then you are using a variable named "value" in your method:
onInput(e: any) {
const value = e.target.value
this.localValue = value
this.$emit('input', value)
},
Don't reuse the name "value". In fact, you don't even need that variable:
onInput(e: any) {
this.localValue = e.target.value
this.$emit('input', this.localValue)
},
Same thing for onChange:
onChange(e: any) {
this.localValue = e.target.value
this.$emit('change', this.localValue)
}
I'm trying to figure out which approach is more appropriate / less resource intense. Both examples below will do the same job, but my understanding is that there might be situations where both events #keyup and #change might be triggered unnecessarily - hence my question, whether watch method would be a better option here?
The reason why I also need to check for a #change event is when someone simply selects saved input value rather than type it.
<template>
<input
type="text"
:name="name"
#keyup="update()"
#change="update()"
v-model="field"
>
</template>
<script>
export default {
props: {
name: {
type: String,
required: true
},
initialValue: {
type: String,
required: false,
default: ''
}
},
data() {
return {
field: this.initialValue
}
},
mounted() {
this.update();
},
methods: {
update() {
this.$emit('input', this.field);
}
}
}
</script>
vs
<template>
<input
type="text"
:name="name"
v-model="field"
>
</template>
<script>
export default {
props: {
name: {
type: String,
required: true
},
initialValue: {
type: String,
required: false,
default: ''
}
},
data() {
return {
field: this.initialValue
}
},
mounted() {
this.update();
},
watch: {
field() {
this.update();
}
},
methods: {
update() {
this.$emit('input', this.field);
}
}
}
</script>
I'm trying to make use of the main component inside another with pre-defined properties.
Here's what I'm trying to achieve, but I'm just getting an empty div as a result.
<template>
<call-dialog-link
:id="id"
:url=url"
message="Are you sure you wish to remove this record?"
label="Remove"
css-classes="alert"
></call-dialog-link>
</template>
<script>
import CallDialogLink from './CallDialogLink.vue';
export default {
props: {
id: {
type: String,
required: true
},
url: {
type: String,
required: true
}
},
components: {
'call-dialog-link': CallDialogLink
}
};
</script>
Here's the CallDialogLink component
<template>
<span class="clickAble" :class="cssClasses" v-text="label" #click="clicked()"></span>
</template>
<script>
export default {
props: {
id: {
type: String,
required: true
},
url: {
type: String,
required: true
},
message: {
type: String,
required: true
},
label: {
type: String,
required: true
},
cssClasses: {
type: String,
required: false
}
},
mounted() {
window.EventHandler.listen('remove-dialog-' + this.id + '-called', (data) => {
window.location.reload(true);
});
},
methods: {
clicked() {
window.EventHandler.fire('top-confirm', {
id: 'remove-dialog-' + this.id,
message: this.message,
url: this.url
});
}
}
};
</script>
Any idea what I'm doing wrong?
I believe there is typo in your code.
<template>
<call-dialog-link
:id="id"
:url="url" // didn't open the double quote here
message="Are you sure you wish to remove this record?"
label="Remove"
css-classes="alert"
></call-dialog-link>
</template>