How to use $refs in template - vuejs - javascript

I have a input with attribute "ref" and I don't want to use v-model
<div class="form-group m-b-40">
<input type="text" class="form-control" id="name" ref="name" required>
</div>
{{showInput}}
I want to show my input value automatically. I do this
methods: {
showInput: function () {
this.$refs.name.value
},
}
but it isn't updated.

Because the value of a ref isn't an observable object unless it's bound to the component instance:
data() {
return {
name: ''
}
}
Then give your input a :value="name" and now it has an observer attached to it

I can't understand what you want to do,but the way you are doing it seems to be wrong.Anyway,you said i dont want to use v-model.
I am going to show you how to do it without v-model,you can fetch the input value from api(you have to write your own code for this) and set it to input:
<template>
<div>
<div class="form-group m-b-40">
<input type="text" :value="text" #input="updateValue">
<hr>
</div>
The input value is: {{text}}
</div>
</template>
<script>
export default {
data() {
return {
text: ''
}
},
created() {
this.fetchFromApi()
},
methods: {
updateValue(value) {
let newValue = value.target.value
this.text = newValue
},
fetchFromApi() {
//write the code to get from API the input value and then:
this.text = 'input value' //set the input value
}
}
}
</script>
See it in action here

Related

Binding child input :value to the parent prop

I try to bind child input value to the parent value. I pass value searchText from a Parent component to a Child component as prop :valueProp. There I assign it to property value: this.valueProp and bind input:
<input type="text" :value="value" #input="$emit('changeInput', $event.target.value)" />
The problem is that input doesn't work with such setup, nothing displays in input, but parent searchText and valueProp in child update only with the last typed letter; value in child doesn't update at all, though it is set to equal to searchText.
If I remove :value="value" in input, all will work fine, but value in child doesn't get updated along with parent's searchText.
I know that in such cases it's better to use v-model, but I want to figure out the reason behind such behavior in that case.
I can't understand why it works in such way and value in child component doesn't update with parent's searchText. Can you please explain why it behaves in that way?
Link to Sanbox: Sandbox
Parent:
<template>
<div>
<Child :valueProp="searchText" #changeInput="changeInput" />
<p>parent {{ searchText }}</p>
</div>
</template>
<script>
import Child from "./Child.vue";
export default {
name: "Parent",
components: { Child },
data() {
return {
searchText: "",
};
},
methods: {
changeInput(data) {
console.log(data);
this.searchText = data;
},
},
};
</script>
Child:
<template>
<div>
<input type="text" :value="value" #input="$emit('changeInput', $event.target.value)" />
<p>value: {{ value }}</p>
<p>child: {{ valueProp }}</p>
</div>
</template>
<script>
export default {
emits: ["changeInput"],
data() {
return {
value: this.valueProp,
};
},
props: {
valueProp: {
type: String,
required: true,
},
},
};
</script>
You set the value in your Child component only once by instantiating.
In the data() you set the initial value of your data properties:
data() {
return {
value: this.valueProp,
};
},
Since you don't use v-model, the value will never be updated.
You have the following options to fix it:
The best one is to use v-model with value in the Child.vue
<input
type="text"
v-model="value"
update value using watcher
watch: {
valueProp(newValue) {
this.value = newValue;
}
},
use a computed property for value instead of data property
computed: {
value() {return this.valueProp;}
}
Respect for creating the sandbox!
You are overwriting the local value every time the value changes
data() {
return {
value: this.valueProp, // Don't do this
};
},
Bind directly to the prop:
<input ... :value="valueProp" ... />

vuejs: v-on does not trigger function

I have an input component that should call a method getUserSearch when the user types, and update the variable v_on_search with the variable v_model_search value.
I am displaying the content with the variables: v_model_search and v_on_search to test, although only the v-model seems to be working.
<template>
<div>
<input type="text" placeholder="search here" v-model="v_model_search" v-on:oninput="getUserSearch()">
<p>{{v_model_search}}</p>
<p>{{v_on_search}}</p>
</div>
</template>
<script>
export default {
name: 'SearchBox',
data () {
return {
v_model_search: '',
v_on_search: ''
}
},
methods: {
getUserSearch ()
{
this.v_on_search = this.v_model_search
}
}
}
</script>
Try
v-on:input="getUserSearch()"
or shorter
#input="getUserSearch()"
Vue recognizes HTML events but they don't have the "on" prefix

How databind a textarea component text value and update it?

I've been working on VueJS just 1 weeks ago for a project.
I've created two components:
* Account.vue (Parent)
<!--It's just a little part of the code-->
<e-textarea
title="Informations complémentaires"
#input="otherInformation" <!--otherInformation is a string variable which contains the text value-->
:value="otherInformation"></e-textarea>
TextArea.vue (Children Component)
<template>
<div class="form-group">
<label for="e-textarea">{{ title }}</label>
<textarea
id="e-textarea"
class="form-control"
row="3"
:value="value"
v-on="listeners"
>
</textarea>
</div>
</template>
<script>
import { FormGroupInput } from "#/components/NowUiKit";
export default {
name: "e-textarea",
components: {
[FormGroupInput.name]: FormGroupInput
},
props: {
title: String,
value: String
},
computed: {
listeners() {
return {
...this.$listeners,
input: this.updateValue
};
}
},
methods: {
updateValue(value) {
this.$emit("input", value);
}
},
mounted() {
console.log(this.components);
}
};
</script>
<style src="#/assets/styles/css/input.css" />
When I write something in my TextArea Custom component from my Account.vue, my text value does not update and my listener function is not passed. Does I need to have something else?
You can easily do this by v-model:
<textarea
id="e-textarea"
class="form-control"
row="3"
v-model="value"
>
</textarea>
it's equals to:
<textarea
id="e-textarea"
class="form-control"
:value="value"
#input="value = $event.target.value"> </textarea>
Bind the value in your custom textarea and the input event:
CustomTextarea.vue
<template>
<div class="form-group">
<label for="e-textarea">{{ title }}</label>
<textarea
id="e-textarea"
class="form-control"
row="3"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
</textarea>
</div>
</template>
<script>
import { FormGroupInput } from "#/components/NowUiKit";
export default {
name: "e-textarea",
components: {
[FormGroupInput.name]: FormGroupInput
},
model: {
prop: "textAreaVue"
},
props: {
title: String,
value: String
},
computed: {
listenerFunction() {
return {
...this.$listener,
input: this.updateValue
};
}
},
methods: {
updateValue(value) {
console.log("function has been passed");
this.$emit("input", value);
}
},
mounted() {
console.log(this.components);
}
};
</script>
<style src="#/assets/styles/css/input.css" />
And use it with v-model :
<custom-textarea
title="Informations complémentaires"
v-model="otherInformation"></custom-textarea>
More explanation here
Hopefully it will save someone some time. In Vue.js 3 they changed this a bit compared the Vue.js 2 and i got it working with this:
<textarea :value="modelValue"
#input="onInput" />
and the onInput method looks like this:
onInput: function (e) {
this.$emit("update:modelValue", e.target.value);
}
of course you have to have the prop 'modelValue' on your 'e-textarea' component instead of value as it was the case in vue 2.
i also added a watcher on this modelValue just in case it fails to update:
props: {
modelValue: {
type: String,
default: null
}
}
watch: {
modelValue: function () {
return this.modelValue;
},
},
and yes, you use the component like so:
<e-textarea v-model="otherInformation" />
of course you can listen to the input event also if you want to, or need to for your specific case
you can also find more about this changes on
here
and here

Automatically update the input field within a form, vue.js

I want to search for elements using an input field within a form. I am passing a value from a component to another and the content changes but only after pressing enter. Is there a way to automatically update the list, after every new letter is typed?
Here is my code:
Parent(App):
<template>
<div id="app">
<Header v-on:phrase-search="passPhrase" />
</div>
</template>
<script>
import Header from ...
export default {
name: "App",
components: {
Header,
},
data() {
return {
posts: [],
searchedPhrase: ""
};
}
computed: {
filteredPosts() {
let temp_text = this.searchedPhrase;
temp_text.trim().toLowerCase();
return this.posts.filter(post => {
return post.name.toLowerCase().match(temp_text);
});
}
},
methods: {
passPhrase(phrase) {
this.searchedPhrase = phrase;
}
}
};
</script>
Child(Header):
<template>
<div class="child">
<p>Search:</p>
<form #submit.prevent="phrasePassed">
<input type="text" v-model="phrase" />
</form>
</div>
</template>
<script>
export default {
name: "search",
data() {
return {
phrase: ""
};
},
methods: {
phrasePassed() {
this.$emit("phrase-search", this.phrase);
}
}
};
</script>
passPhrase() brings the value from the child to the parent and then filteredPosts() find appropriate elements. I suspect that the form might be guilty of this issue but I do not know precisely how to get rid of it and still be able to pass the value to the parent.
Thanks
in the child you use submit event which called on enter. you should use #input on the input itself. and btw you didnt need even to declare pharse in the data because you didnt use it in the child. you just pass it up
you it like so
<template>
<div class="child">
<p>Search:</p>
<form>
<input type="text" #input="phrasePassed">
</form>
</div>
</template>
<script>
export default {
name: "search",
methods: {
phrasePassed(e) {
this.$emit("phrase-search", e.target.value);
}
}
};
</script>

Binding two or more data to a form input in VueJs

I was considering having more than one value in a vue form input binding
Below is a sample of my code.
<template>
<div>
<label for=""> Employee </label>
<input class="form-control-plaintext" v-model="asset.current_status.user.surname" type= "text" readonly name="surname">
</div>
</template>
<script>
data(){
return:{
asset:{},
}
},
methods:{
getAsset(){
axios.get('/api/assets/'+this.id)
.then ( response => {
this.asset = response.data.data[0].data;
this.toFill = this.asset()
this.assetForm.fill(this.toFill)
})
},
},
mounted(){
this.getAsset();
}
</script>
The v-model currently accepts and displays one value of surname, I believe it possible to include another value asset.current_status.user.last_name to the v-model inline but can't currently get things right.
I think you need computed property like this:
computed: {
surname () {
if (this.asset.current_status.user.last_name
&& this.asset.current_status.user.surname) {
return this.asset.current_status.user.last_name
+ this.asset.current_status.user.surname
}
return '' // or whatewer else you need...
}
}
And set v-model="surname".
Read more about computed.
Also if you need to edit that input you will need get() and set().
You can check this example for that.
Good luck!
<template>
<div>
<label for=""> Employee </label>
<input class="form-control-plaintext" :value="showAssignedUser()" type= "text" readonly name="surname">
</div>
</template>
<script>
data(){
return:{
asset:{},
}
},
methods:{
getAsset(){
axios.get('/api/assets/'+this.id)
.then ( response => {
this.asset = response.data.data[0].data;
this.toFill = this.asset()
this.assetForm.fill(this.toFill)
})
},
showAssignedUser(){
return `${this.asset.current_status.user.surname}` + ' '+ `${this.asset.current_status.user.first_name}`
},
},
mounted(){
this.getAsset();
}
</script>

Categories

Resources