Element UI dialog component can open for the first time, but it can't open for the second time - vuejs2

I'm building web app with Vue, Nuxt, and Element UI.
I have a problem with the Element dialog component.
It can open for the first time, but it can't open for the second time.
This is the GIF about my problem.
https://gyazo.com/dfca3db76c75dceddccade632feb808f
This is my code.
index.vue
<template>
<div>
<el-button type="text" #click="handleDialogVisible">click to open the Dialog</el-button>
<modal-first :visible=visible></modal-first>
</div>
</template>
<script>
import ModalFirst from './../components/ModalFirst.vue'
export default {
components: {
'modal-first': ModalFirst
},
data() {
return {
visible: false,
};
},
methods: {
handleDialogVisible() {
this.visible = true;
}
}
}
</script>
ModalFirst.vue
<template>
<el-dialog
title="Tips"
:visible.sync="visible"
width="30%"
>
<span>This is a message</span>
<span slot="footer" class="dialog-footer">
<a>Hello</a>
</span>
</el-dialog>
</template>
<script>
export default {
props: [ 'visible' ]
}
</script>
And I can see a warning message on google chrome console after closing the dialog.
The warning message is below.
webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js:620 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "visible"
found in
---> <ModalFirst> at components/ModalFirst.vue
<Pages/index.vue> at pages/index.vue
<Nuxt>
<Layouts/default.vue> at layouts/default.vue
<Root>
This is the screenshot of the warning message.
https://gyazo.com/83c5f7c5a8e4d6816c35b3116c80db0d

In vue , using directly to prop value is not allowed . Especially when your child component will update that prop value , in my option if prop will be use
for display only using directly is not a problem .
In your code , .sync will update syncronously update data so I recommend to create local data.
ModalFirst.vue
<el-dialog
title="Tips"
:visible.sync="localVisible"
width="30%"
>
<script>
export default {
props: [ 'visible' ],
data: function () {
return {
localVisible: this.visible // create local data using prop value
}
}
}
</script>

If you need the parent visible property to be updated, you can create your component to leverage v-model:
ModalFirst.vue
<el-dialog
title="Tips"
:visible.sync="localVisible"
width="30%"
>
<script>
export default {
props: [ 'value' ],
data() {
return {
localVisible: null
}
},
created() {
this.localVisible = this.value;
this.$watch('localVisible', (value, oldValue) => {
if(value !== oldValue) { // Optional
this.$emit('input', value); // Required
}
});
}
}
</script>
index.vue
<template>
<div>
<el-button type="text" #click="handleDialogVisible">click to open the Dialog</el-button>
<modal-first v-model="visible"></modal-first>
</div>
</template>
<script>
import ModalFirst from './../components/ModalFirst.vue'
export default {
components: {
'modal-first': ModalFirst
},
data() {
return {
visible: false,
};
},
methods: {
handleDialogVisible() {
this.visible = true;
}
}
}
</script>
v-model is basically a shorthand for :value and #input
https://v2.vuejs.org/v2/guide/forms.html#Basic-Usage
Side-note:
You can also import your component like so:
components: { ModalFirst },
as ModalFirst will be interpreted as modal-first as well by Vue.js

Related

how to validate child form from parent component in Vue

I have a child component which includes form:
<el-form :model="abc" ref="ruleForm" :rules="rules">
<el-form-item prop="files">
<abc-card :title="getTranslation('abc.files')">
<file-selector v-model="abc.files" />
</abc-card>
</el-form-item>
</el-form>
And I want to add simple validations to this form:
rules: function () {
return {
files: [
{
type: 'object',
required: true,
trigger: 'change',
message: 'Field required',
},
],
};
},
But my click button is in the parent component:
<files v-model="editableAbc" ref="editableTab" />
<el-button type="primary" #click="submitForm()">Create</el-button>
methods: {
submitForm() {
this.$refs.form.validate((isValid) => {
if (!isValid) {
return;
}
////API CALLS////
});
},
}
So I am trying to achieve that when the button is clicked the navigation should be rendered. How can I do that?
As per your requirement, My suggestion would be to use a ref on child component to access its methods and then on submit click in parent component, trigger the child component method.
In parent component template :
<parent-component>
<child-component ref="childComponentRef" />
<button #click="submitFromParent">Submit</button>
</parent-component>
In parent component script :
methods: {
submitFromParent() {
this.$refs.childComponentRef.submitForm();
}
}
In child component script :
methods: {
submitForm() {
// Perform validations and do make API calls based on validation passed.
// If you want to pass success or failure in parent then you can do that by using $emit from here.
}
}
The "files" component is the form you're talking about?
If so, then ref should be placed exactly when calling the 'files' component, and not inside it. This will allow you to access the component in your parent element.
<files v-model="editableAbc" ref="ruleForm" />
There is a method with the props, which was mentioned in the comments above. I really don't like it, but I can tell you about it.
You need to set a value in the data of the parent component. Next you have to pass it as props to the child component. When you click the button, you must change the value of this key (for example +1). In the child component, you need to monitor the change in the props value via watch and call your validation function.
// Parent
<template>
<div class="test">
<ChildComponent />
</div>
</template>
<script>
export default {
data() {
return {
updateCount: 0,
};
},
methods: {
submitForm() {
// yout submit method
this.updateCount += 1;
},
},
};
</script>
// Child
<script>
export default {
props: {
updateCount: {
type: Number,
default: 0,
},
},
watch: {
updateCount: {
handler() {
this.validate();
},
},
},
methods: {
validate() {
// yout validation method
},
},
};
</script>
And one more solution. It is suitable if you cannot place the button in the child component, but you can pass it through the slot.
You need to pass the validate function in the child component through the prop inside the slot. In this case, in the parent component, you will be able to get this function through the v-slot and bind it to your button.
// Parent
<template>
<div class="test">
<ChildComponent>
<template #button="{ validate }">
<button #click="submitForm(validate)">My button</button>
</template>
</ChildComponent>
</div>
</template>
<script>
import ChildComponent from "./ChildComponent";
export default {
components: {
ChildComponent,
},
methods: {
submitForm(cb) {
const isValid = cb();
// your submit code
},
},
};
</script>
// Child
<template>
<div class="child-component">
<!-- your form -->
<slot name="button" :validate="validate" />
</div>
</template>
<script>
export default {
methods: {
validate() {
// yout validation method
console.log("validate");
},
},
};
</script>

Vue + Nuxt: problem passing (bind) dynamic data from parent to child component

I'm new to Vue and I'm struggling to pass dynamic data from parent to child component through props. My parent component should pass a boolean (isModalVisible) to a children component through the visible prop.
In the parent, the isModalVisible changes (from false to true) when the button is clicked.
But the child component keeps the initial value.
As far as I have understood, the data() is executed when the component is created and when any value that has been bound (visible, in this case) is changed, but this does not occurs.
Anyone can help me to find out what I am missing?
Parent component:
<template>
<div>
{{ isModalVisible }}
<CoursesModal :visible="isModalVisible" />
<button #click="showModal" title="Courses">
Courses
</button>
</div>
</template>
<script>
import CoursesModal from "../components/modals/Courses.vue";
export default {
components: {
CoursesModal
},
data() {
return {
isModalVisible: false
};
},
methods: {
showModal() {
this.isModalVisible = true;
},
closeModal() {
this.isModalVisible = false;
}
},
};
</script>
Child (modal) component:
<template>
<div>
{{ visible }}
</div>
</template>
<script>
export default {
components: {
props: {
visible: {
type: Boolean,
default: true
}
}
},
data: function() {
return {
visible: false,
};
}
};
</script>
I have tried, too, to do
return {
visible: this.visible,
};
but this value is undefined.
My package.json:
"dependencies": {
"core-js": "^3.9.1",
"nuxt": "^2.15.3"
}
I think you make a mistake about the components property. The components property did not have props property and it is used to register the component. You can read further here and here
Here is the correct way to use props:
<template>
<div>
{{ visible }}
</div>
</template>
<script>
export default {
// removed the components and data property
props: {
visible: {
type: Boolean,
default: true
}
}
};
</script>

error Unexpected mutation of "todo" prop in vue.js (I'm using vue3)

I'm making a todo app in vue.js which has a component TodoItem
<template>
<div class="todo-item" v-bind:class="{'is-completed':todo.completed}">
<p>
<input type="checkbox" #change="markCompleted" />
{{todo.task}}
<button class="del">x</button>
</p>
</div>
</template>
<script>
export default {
name: "TodoItem",
props: ["todo"],
methods: {
markCompleted() {
this.todo.completed = true
},
},
};
</script>
todo prop that I'm passing:
{
id:1,
task:'todo 1',
completed:false
}
but it is throwing an error error Unexpected mutation of "todo" prop
Method 1 (Vue 2.3.0+) - From your parent component, you can pass prop with sync modifier
Parent Component
<TodoItem v-for="todo in todoList" :key="todo.id" todo_prop.sync="todo">
Child Component
<template>
<div class="todo-item" v-bind:class="{'is-completed':todo.completed}">
<p>
<input type="checkbox" #change="markCompleted" />
{{todo.task}}
<button class="del">x</button>
</p>
</div>
</template>
<script>
export default {
name: "TodoItem",
props: ["todo_prop"],
data() {
return {
todo: this.todo_prop
}
},
methods: {
markCompleted() {
this.todo.completed = true
},
},
};
</script>
Method 2 - Pass props from parent component without sync modifier and emit an event when the value changed. For this method, everything else is similar as well. Just need to emit an event when the todo item changed to completed.
The code is untested. Apologies if anything does not work.
What happen ? : Mutating a prop locally is now considered an anti-pattern, e.g. declaring a prop and then setting this.myProp = 'someOtherValue' in the component. Due to the new rendering mechanism, whenever the parent component re-renders, the child component’s local changes will be overwritten.
Solution : You can storage it as local data.
export default {
name: "TodoItem",
props: ["todo"],
data() {
return {
todoLocal: this.todo,
};
},
methods: {
markComplete() {
this.todoLocal.completed = !this.todoLocal.completed;
},
},
};
For me to fix this problem I store props in todos data im watching brad vue tutorials and i get this error this is my actual codes and its working.
<template>
<div class="todo-item" v-bind:class="{ 'is-complete': todo.completed }">
<p>
<input
type="checkbox"
v-on:change="markComplete(todo.completed)"
v-bind:checked="todo.completed"
/>
{{ todo.title }}
<!-- <button #click="$emit('del-todo', todo.id)" class="del">x</button> -->
</p>
</div>
</template>
<script>
export default {
name: 'TodoItem',
props: ['todo'],
data() {
return {
todos: this.todo,
}
},
methods: {
markComplete(isComplete) {
this.todos.completed = !isComplete
},
},
}
</script>
<style scoped>
.todo-item {
background: #f4f4f4;
padding: 10px;
border-bottom: 1px #ccc dotted;
}
.is-complete {
text-decoration: line-through;
}
.del {
background: #ff0000;
color: #fff;
border: none;
padding: 5px 9px;
border-radius: 50%;
cursor: pointer;
float: right;
}
</style>
One of the core principles of VueJS is that child components never mutate a prop.
All props form a one-way-down binding between the child property and the parent one: when the parent property updates, it will flow down to the child, but not the other way around.
If you wish to have the child component update todo.completed, you have two choices:
Use .sync modifier (Recommended)
This approach will require a bit of change to your props. You can read more about it here.
Parent component
<template>
<div>
...
<todo-item :task="nextTodo.task" :completed.sync="nextTodo.completed"/>
</div>
</template>
Child component
<template>
<div class="todo-item" v-bind:class="{'is-completed':completed}">
<p>
<input type="checkbox" #change="markCompleted" />
{{task}}
<button class="del">x</button>
</p>
</div>
</template>
<script>
export default {
name: "TodoItem",
props: ["task", "completed"],
methods: {
markCompleted() {
this.$emit('update:completed', true)
},
},
};
</script>
Use a custom event
Vue allows you set up listeners in your parent for events that the child will emit. Your child component can use this mechanism to ask the parent to change things. In fact, the above .sync modifier is doing exactly this behind the scenes.
Parent component
<template>
<div>
...
<todo-item :todo="nextTodo" #set-completed="$value => { nextTodo.completed = $value }/>
</div>
</template>
Child component
<template>
<div class="todo-item" v-bind:class="{'is-completed':todo.completed}">
<p>
<input type="checkbox" #change="markCompleted" />
{{todo.task}}
<button class="del">x</button>
</p>
</div>
</template>
<script>
export default {
name: "TodoItem",
props: ["todo"],
methods: {
markCompleted() {
this.$emit('set-completed', true)
},
},
};
</script>
You can't change a prop from inside a component - they are meant to be set by the parent only. It's a one-directional communication path.
You can try one of two things - either move your logic for detecting a todo has been completed to the parent, or feed the prop into a new variable in the data() lifecycle hook (this will only happen when the component is loaded for the first time, so you won't be able to update from outside the component, if that's important for your use case).
The canonical way to achieve n-deep prop binding in Vue 3 is to wrap your prop with a simple computed property. This is an example of a component that will communicate changes to it's selected property to it's parent--who is ultimately responsible for storing the state.
<template>
<!-- In this example my-child-component also has a "selected" prop -->
<my-child-component v-model:selected="syncSelectedId" />
</template>
<script lang="ts">
export default defineComponent({
components: { MyChildComponent },
props: {
selected: {
type: String,
required: true,
}
},
emits: ['update:selected'],
setup(props, context) {
const syncSelectedId = computed<string>({
get() {
return props.selected;
},
set(newVal: string) {
context.emit('update:selected', newVal);
},
});
return {
syncSelectedId,
}
}
});
So to re-iterate: With this strategy the highest level parent is the holder of the state. The code above assumes that there is a parent component in the hierarchy (so this component is just a "middle-man").
Then my-child-component can simply emit its own update:selected event to cause the state to change. That child will be updated appropriately through it's prop after the emit event causes the parent chain to propagate that change up (through emits) and then back down the component hierarchy (through props).
If you wanted to you could modify the code above to make it the "owner" of the state:
<template>
<my-child-component v-model:selected="selected" />
</template>
<script lang="ts">
export default defineComponent({
components: { MyChildComponent },
setup(props, context) {
const selected = ref('');
return {
selected,
}
}
});
And now of course you won't run into the "Unexpected mutation of X prop" error.
Another option is to have a prop that serves as a "default value" for a given state:
<template>
<my-child-component v-model:selected="selected" />
</template>
<script lang="ts">
export default defineComponent({
components: { MyChildComponent },
props: {
defaultSelected: {
type: String,
required: false,
default: ''
}
},
setup(props, context) {
const selected = ref(props.defaultSelected);
return {
selected,
}
}
});
And in this code above keep in mind that selected will NOT change if defaultSelected changes after the component has been initialized.
And lastly it's worth noting that you could write more sophisticated code to detect if a property is supplied--and if not use an internal state variable to store the value. I use this pattern for re-usable components that could be embedded in places where the parent wants to control the state OR in places where the parent is happy to delegate the storage of the state to the child:
<template>
<!-- In this example my-child-component also has a "selected" prop -->
<my-child-component v-model:selected="syncSelectedId" />
</template>
<script lang="ts">
export default defineComponent({
components: { MyChildComponent },
props: {
selected: {
type: String,
required: false,
default: null // Important: parent MUST pass non-null value if it wants to control state
}
},
emits: ['update:selected'],
setup(props, context) {
// This is state storage used if prop.selected is not provided
const _selected = ref('');
const syncSelectedId = computed<string>({
get() {
return props.selected === null ? _selected.value : props.selected;
},
set(newVal: string) {
if (props.selected !== null) {
// Using prop.selected as the driving model...
if (newVal !== props.selected) {
// We need to set to empty string (never null)
context.emit('update:selectedId', (newVal == null ? '' : newVal));
}
} else { // Storing selection state with _selectedId
if (newVal !== _selected.value) {
_selected.value = newVal == null ? '' : newVal;
context.emit('update:selected', _selected);
}
}
},
});
return {
syncSelectedId,
}
}
});
This last example is tricky... it gives special meaning to null and requires that you be very mindful of potential values of your state. In my example empty string is my representation for "no selection" and null is used as a flag for "no parent model of this state".
Mainly, property mutation is now deprecated and parent properties are overwritten when the parent component renders its DOM.
Here's the official documentation about it. We can still achieve this in multiple possible ways. Through a data property, a computed property, and component events.
When we want to pass this value back to the parent component as well as the nested child component of the current child component, using a data property would be useful as shown in the following example.
Example:
Calling your child component from the parent component like this.
Parent component:
<template>
<TodoItem :todoParent="todo" />
</template>
<script>
export default {
data() {
return {
todo: {
id:1,
task:'todo 1',
completed:false
}
};
}
}
</script>
Child component:
<template>
<div class="todo-item" v-bind:class="{'is-completed':todo.completed}">
<p>
<input type="checkbox" #change="markCompleted" />
{{todo.task}}
<button class="del">x</button>
</p>
</div>
</template>
<script>
export default {
name: "TodoItem",
props: ["todoParent"],
data() {
return {
todo: this.todoParent,
};
},
methods: {
markCompleted() {
this.todo.completed = true
},
},
};
</script>
Even you can pass this property to the nested child component and it won't give this error/warning.
Other use cases when you only need this property sync between parent and child component. It can be achieved using the sync modifier from Vue. v-model can also be useful. Many other examples are available in this question thread.
Example2: using component events.
We can emit the event from the child component as below.
Parent component:
<template>
<TodoItem :todo="todo" #markCompletedParent="markCompleted" />
</template>
<script>
export default {
data() {
return {
todo: {
id:1,
task:'todo 1',
completed:false
}
};
},
methods: {
markCompleted() {
this.todo.completed = true
},
}
}
</script>
Child component:
<template>
<div class="todo-item" v-bind:class="{'is-completed':todo.completed}">
<p>
<input type="checkbox" #change="markCompleted" />
{{todo.task}}
<button class="del">x</button>
</p>
</div>
</template>
<script>
export default {
name: "TodoItem",
props: ["todo"],
methods: {
markCompleted() {
this.$emit('markCompletedParent', true)
},
}
};
</script>
While you can still custom-bind events to handle this, .sync property extensions are considered deprecated. In Vue3 (at least) you can and usually should use the v-model:property declaration, similar to how you bind the property to the actual input. You just need to bind the inner input with :value and have it emit a matching update:property
<!-- CustomInput.vue -->
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>
<template>
<input
:value="modelValue"
#input="$emit('update:modelValue', $event.target.value)"
/>
</template>
And use thusly:
<CustomInput v-model="searchText" />

vue reload child component

I'm using vue, version 2.5.8
I want to reload child component's, or reload parent and then force children components to reload.
I was trying to use this.$forceUpdate() but this is not working.
Do You have any idea how to do this?
Use a :key for the component and reset the key.
See https://michaelnthiessen.com/force-re-render/
Add key to child component, then update the key in parent. Child component will be re-created.
<childComponent :key="childKey"/>
If the children are dynamically created by a v-for or something, you could clear the array and re-assign it, and the children would all be re-created.
To simply have existing components respond to a signal, you want to pass an event bus as a prop, then emit an event to which they will respond. The normal direction of events is up, but it is sometimes appropriate to have them go down.
new Vue({
el: '#app',
data: {
bus: new Vue()
},
components: {
child: {
template: '#child-template',
props: ['bus'],
data() {
return {
value: 0
};
},
methods: {
increment() {
this.value += 1;
},
reset() {
this.value = 0;
}
},
created() {
this.bus.$on('reset', this.reset);
}
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
<child :bus="bus">
</child>
<child :bus="bus">
</child>
<child :bus="bus">
</child>
<button #click="() => bus.$emit('reset')">Reset</button>
</div>
<template id="child-template">
<div>
{{value}} <button #click="increment">More!</button>
</div>
</template>
I'm using directive v-if which is responsible for conditional rendering. It only affects reloading HTML <template> part. Sections created(), computed are not reloaded. As I understand after framework load components reloading it is not possible. We can only re render a <template>.
Rerender example.
I have a Child.vue component code:
<template>
<div v-if="show">
Child content to render
{{ callDuringReRender() }}
</div>
</template>
<script>
export default {
data() {
return {
show: true
}
}
,
methods: {
showComponent() {
this.show = true
},
hideComponent() {
this.show = false
},
callDuringReRender() {
console.log("function recall during rendering")
}
}
}
</script>
In my Parent.vue component I can call child methods and using it's v-if to force the child rerender
<template>
<div>
<input type="button"
value="ReRender the child"
#click="reRenderChildComponent"/>
<child ref="childComponent"></child>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
methods: {
reRenderChildComponent(){
this.$refs.childComponent.hideComponent();
this.$refs.childComponent.showComponent()
}
},
components: {
Child
}
}
</script>
After clicking a button in console You will notice message "function recall during rendering" informing You that component was rerendered.
This example is from the link that #sureshvv shared
import Vue from 'vue';
Vue.forceUpdate();
// Using the component instance
export default {
methods: {
methodThatForcesUpdate() {
// ...
this.$forceUpdate(); // Notice we have to use a $ here
// ...
}
}
}
I've found that when you want the child component to refresh you either need the passed property to be output in the template somewhere or be accessed by a computed property.
<!-- ParentComponent -->
<template>
<child-component :user="userFromParent"></child-component>
</template>
<!-- ChildComponent -->
<template>
<!-- 'updated' fires if property 'user' is used in the child template -->
<p>user: {{ user.name }}
</template>
<script>
export default {
props: {'user'},
data() { return {}; }
computed: {
// Or use a computed property if only accessing it in the script
getUser() {
return this.user;
}
}
}
</script>

Using v-model with a prop on VUE.JS

I'm trying to use a data coming from a prop with v-model, the following code works, but with a warning.
<template>
<div>
<b-form-input v-model="value" #change="postPost()"></b-form-input>
</div>
</template>
<script>
import axios from 'axios';
export default {
props: {
value: String
},
methods: {
postPost() {
axios.put('/trajectory/inclination', {
body: this.value
})
.then(response => {
})
.catch(e => {
this.errors.push(e)
})
}
}
}
</script>
The warning says:
"Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "value"
So I changed and now I'm using a data as the warning says.
<template>
<div>
<b-form-input v-model="_value" #change="postPost()"></b-form-input>
</div>
</template>
<script>
import axios from 'axios';
export default {
props: {
value: String
},
data() {
return {
_value: this.value
}
},
methods: {
postPost() {
axios.put('/trajectory/inclination', {
body: this._value
})
.then(response => {
})
.catch(e => {
this.errors.push(e)
})
}
}
}
So now the code it's not working and the warning says:
"Property or method "_value" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option"
Any idea how to fix the first code to suppress the warning? (or some idea on how to fix the second code?)
Obs.: b-form-input it's not my componente, this is the Textual Input from Boostrap-Vue (Doc for b-form-input)
Answer is from https://github.com/vuejs/vue/issues/7434
Props are read-only, but you are trying to change its value with v-model. In this case, if you change the input value, the prop is not modified and the value is restored on the next update.
Use a data property or a computed setter instead:
computed: {
propModel: {
get () { return this.prop },
set (value) { this.$emit('update:prop', value) },
},
},
https://v2.vuejs.org/v2/guide/computed.html#Computed-Setter
Bert addresses your direct issue, but I think you should also know that your approach is a bit off. Since ultimately you are sending the new value to postPost, you don't really need to modify your local copy. Use the event object that is sent to the change handler to get the current value from the input.
Instead of v-model, just use :value, and don't include the invocation parentheses when specifying the change handler.
<template>
<div>
<b-form-input :value="value" #change="postPost"></b-form-input>
</div>
</template>
<script>
import axios from 'axios';
export default {
props: {
value: String
},
methods: {
postPost(event) {
axios.put('/trajectory/inclination', {
body: event.target.value
})
.then(response => {
})
.catch(e => {
this.errors.push(e)
})
}
}
}
</script>
_ prefixed properties are reserved for Vue's internal properties.
Properties that start with _ or $ will not be proxied on the Vue
instance because they may conflict with Vue’s internal properties and
API methods.
Try changing _value to something that doesn't start with an underscore.
One general workaround is to introduce a data-variable and watch the props to update-variable. This is quite subtle and so easy to get wrong so here's an example with a Vuetify modal using v-model (the same technique, in theory, should work with <input> and others):
<template>
<v-dialog v-model="isVisible" max-width="500px" persistent>
</v-dialog>
</template>
<script>
export default {
name: 'Blablabla',
props: {
visible: { type: Boolean, required: true }
},
data() {
isVisible: false
},
watch: {
// `visible(value) => this.isVisible = value` could work too
visible() {
this.isVisible = this.$props.visible
}
}
}
</script>
The official Vue docs shows how to use v-model on a custom component: https://v2.vuejs.org/v2/guide/components.html#Using-v-model-on-Components
TL;DR:
You simply need to have a specifically named value prop, and emit an input event which the v-model when you instantiate the component maps for you.
More info on how this works on the link above.
<template>
<input
type="text"
:value="value"
#input="$emit('input', $event.target.value)"
/>
</template>
<script>
export default {
name: "Input",
props: {
value: String,
},
};
</script>
<Input v-model="searchText"></Input>
Point your input v-model directive to a data property named value_ (or any other name not starting with prefixes _ or $ which are reserved by Vue). Set the data property's default value to null. Then, add a method getValue() which will set property value_ based on your value prop's value. Finally, call getValue() in Vue's created() lifecycle hook. Like so:
<template>
<div>
<b-form-input v-model="value_" #change="postPost()">
</b-form-input>
</div>
</template>
<script>
import axios from 'axios';
export default {
data: () => ({
value_: null
}),
props: {
value: String
},
methods: {
postPost() {
axios.put('/trajectory/inclination', {
body: this.value_
})
.then(response => {
})
.catch(e => {
this.errors.push(e)
})
},
getValue() {
this.value_ = this.value;
}
},
created() {
this.getValue()
}
}
</script>
You can use a data like below.
<template>
<input type="text" v-bind:value="value" v-on:input="dValue= $event.target.value" />
</template>
<script>
export default {
props: ["value"],
data: function () {
return {
dValue: this.value,
};
},
methods: {
alertValue() {
alert("Current Value" + this.dValue);
},
},
};
</script>