I have the following template syntax in a Vue single-file component:
<template>
...
<input v-model="newInput">
...
</template>
In the same component, I have this data:
<script>
...
data: () => {
return {
newInput: "",
}
}
...
</script>
Problem: In Chrome, this input field will not accept any text or numbers. The cursor is blinking in the field, but no text is entering. I opened dev tools, and there is no data change when I type. I checked my keyboard settings, nothing weird there.
Appreciate any guidance on this!
In my case this work perfectly,
Here in template tag I've modified input and in the script tag I've modified 'data()' method which accept any text or number.
Try this:
<template>
<input type="text" v-model="newInput">
</template>
<script>
export default {
data () {
return {
newInput: ''
}
}
}
</script>
Related
Firs of all here is my code:
<input type="text" id="first_name" class="form-control" v-model="user.attributes.first_name"
#keyup.enter="updateProfile" v-model.trim="$v.first_name.$model"
:class="{'is-invalid':$v.first_name.$error, 'is-valid':!$v.first_name.$invalid}">
I am using vuelidate in my form to validate my input field. But at the same time, I am getting the user object as a prop and I want to show the first name of the object as a value of the input field. Since I trim the value of the input field, I think I am not able to use v-model to show my value anymore. Do you have any solution for this?
First, you can't have multiple v-model on the same element.
Then, if you want to use a prop as a v-model, you have to set the #input event yourself.
cf vuelidate documentation
<template>
<input v-model.trim="$v.first_name.$model" #input="updateFirstname">
</template>
<script>
export default {
props: {
user: Object
},
validations: {
first_name: { ... }
},
methods: {
updateFirstName(newFirstName) {
this.user.attributes.first_name = newFirstName
this.$v.first_name.$touch()
}
}
}
</script>
I have a simple Vue component that displays an address, but converts into a form to edit the address if the user clicks a button. The address field is an autocomplete using Google Maps API. Because the field is hidden (actually nonexistent) half the time, I have to re-instantiate the autocomplete each time the field is shown.
<template>
<div>
<div v-if="editing">
<div><input ref="autocomplete" v-model="address"></div>
<button #click="save">Save</button>
</div>
<div v-else>
<p>{{ address }}</p>
<button #click="edit">Edit</button>
</div>
</div>
</template>
<script>
export default {
data() {
editing: false,
address: ""
},
methods: {
edit() {
this.editing = true;
this.initAutocomplete();
},
save() {
this.editing = false;
}
initAutocomplete() {
this.autocomplete = new google.maps.places.Autocomplete(this.$refs.autocomplete, {});
}
},
mounted() {
this.initAutocomplete();
}
}
I was getting errors that the autocomplete reference was not a valid HTMLInputElement, and when I did console.log(this.$refs) it only produced {} even though the input field was clearly present on screen. I then realized it was trying to reference a nonexistent field, so I then tried to confine the autocomplete init to only when the input field should be visible via v-if. Even with this, initAutocomplete() is still giving errors trying to reference a nonexistent field.
How can I ensure that the reference exists first?
Maybe a solution would be to use $nextTick which will wait for your DOM to rerender.
So your code would look like :
edit() {
this.editing = true;
this.$nextTick(() => { this.initAutocomplete(); });
},
Moreover if you try to use your this.initAutocomplete(); during mounting it cannot work since the $refs.autocomplete is not existing yet but I'm not sure you need it since your v-model is already empty.
I think it's because your "refs" is plural
<input refs="autocomplete" v-model="address">
It should be:
<input ref="autocomplete" v-model="address">
I like to know how I can insert a Element that has already been created with the document.createElement method into the template. I am not sure how to proceed here because eventually I would also like to bind the contents of that particular textBox. Here is the (non working) code that I have up till now to illustrate what I like to do:
<template>
<div>
<p id="status">{{ statusMessage }}</p>
<div id="output" v-html="textBox"></div>
</div>
</template>
<script>
export default {
name: 'Result',
data() {
return {
statusMessage: "Status",
textBox: Object,
}
},
mounted() {
this.textBox = this.$someModule.createTextBox()
console.log('textBox should become: '+this.textBox)
// Shows: textbox should become: [object HTMLTextAreaElement]
},
...
}
First of all, v-html is a directive that allow you to use raw html text.
ref: https://v2.vuejs.org/v2/guide/syntax.html#Raw-HTML
Second of all, you can you a ref directive to create a link to you element (ref="someName"):
<div id="output" ref="textBox"></div>
Then:
const el = this.$refs.textBox;
el.appendChild('entity which you want to append');
I'm new to Vue.js
I want to render a script tag inside a variable (data string).
I tried to us a v-html directive to do so, but it doesn't work Nothing is rendered
Any way I can achieve this?
I'd place a v-if directive on the script tag and put the content of it in a variable.
<script v-if="script">
{{script}}
</scrip>
If I understand you correctly, my answer is:
<template>
<div>
{{ strWithScriptTag }}
</div>
</template>
<script>
export default {
name: 'Example',
methods: {
htmlDecode(input) {
const e = document.createElement('div')
e.innerHTML = input
return e.childNodes[0].nodeValue
},
},
computed: {
strWithScriptTag() {
const scriptStr = '<script>https://some.domain.namet</script>'
return this.htmlDecode(scriptStr)
}
},
}
</script>
I think that by safety vue is escaping your <script> automatically and there is no way to avoid this.
Anyway, one thing you can do is eval(this.property) on created() lifecycle hook.
data: {
script: 'alert("this alert will be shown when the component is created")'
},
created() {
eval(this.script)
}
Use it with caution, as stated in vue js docs, this may open XSS attacks in your app
I have a component that takes a main <slot> from a form that is generated elsewhere in my application. I'm trying to use v-model on the form inputs but my vue component just spits out a warning about the properties not being defined, when in fact they are.
I admit it's a weird way of doing things, but it seems to be the easiest way for me to do this since my form is being generated by Symfony.
html:
<my-component>
<input ref="start" v-model="start"/>
</my-component>
my component:
<script>
export default {
data() {
start: null
},
mounted() {
console.log(this.$refs) // === {}; expected {"start":{...}}
}
}
</script>
<template>
<div>
<slot/>
... other stuff here
</div>
</template>
console log:
Property or method "start" is not defined on the instance but referenced during render
I cannot use $refs or v-model in the html. Am I doing something wrong? Or is this just not possible.
If you declare v-model="start" in the parent then it belongs to the parent and needs to be declared there. It looks like instead you declare it in the component instead as null.
If you reorder things it should work as you expect:
Parent:
<parent>
<input v-model="start" :start="start"/>
</parent>
<script>
export default {
data() {
start: null // Important to define start here if it's used in this component's html
}
}
</script>
Component:
<template>
<div>
<slot/>
... other stuff here
</div>
</template>
<script>
export default {
props: ['start'], // Receive the prop from the parent
data() {
},
mounted () {
console.log(this.start) // Should echo the value of the prop from the parent
}
}
</script>