How to get the value of one input field in a "v-for" of multiple inputs - vue.js

I have multiple text inputs generated in v-for directive which i have attached to one v-model variable as show below. I have a button by the respective inputs which prints the value of the current working input. Ultimately I want to extract value of the selected input without affecting the other inputs.
But apparent any change make in one input affect all the input. I super confused as to how I will achieve this. Any help will be much appreciated.
My attempted code is shown below.
<template>
<div id="app">
<div v-for="i in 5" :key="i">
<input v-model="text" type="text" :key="i" />
<button #click="printText">print</button> <span>{{ text }}</span>
</div>
</div>
</template>
<script>
export default {
data() {
return {
text: "",
};
},
methods: {
printText() {
console.log(this.text);
},
},
};
</script>

Take an array instead of simple variable when you use v-model in v-for
And on click pass the index with function call
Try to use
<template>
<div id="app">
<div v-for="i in 5" :key="i">
<input v-model="text[i]" type="text"/>
<button #click="printText(i)">print</button> <span>{{ text[i] }}</span>
</div>
</div>
</template>
<script>
export default {
data() {
return {
text: [],
};
},
methods: {
printText(index) {
console.log(this.text[index]);
},
},
};
</script>

Related

Is it possible to use a prop as a v-model value?

Is it possible to use the value of a prop as the input's v-model?
I normally do the following when creating an input:
<template>
<form>
<input v-model="form.email" type="email"/>
</form>
</template>
<script>
export default {
data() {
return {
form: {
email: '',
}
}
}
}
</script>
But now I'm trying to achieve the following where this.myProp is used within the v-model without being displayed as a string on the input:
<template>
<form>
<input v-model="this.myProp" type="email"/>
</form>
</template>
<script>
export default {
props: ['myProp'] // myProp = form.email for example (to be handled in a parent component)
}
</script>
Yes, but while using it in parent component. In child component you need to extract value and #input instead of using v-model (v-model is shortcut for value="" and #input) Here is an example of input with label, error and hint in Vue 3 composition API.
BaseInput.vue
<template>
<div class="flex flex-col">
<label>{{ label }}</label>
<input v-bind="$attrs" :placeholder="label" :value="modelValue" #input="$emit('update:modelValue', $event.target.value)">
<span v-for="item of errors" class="text-red-400">{{ item.value }}</span>
<span v-if="hint" class="text-sm">{{ hint }}</span>
</div>
</template>
<script setup>
defineProps({ label: String, modelValue: String | Number, errors: Array, hint: String })
defineEmits(['update:modelValue'])
</script>
Using v-bind="$attrs" you target where attributes like type="email" need to be applied in child component. If you don't do it, it will be added to the top level DOM element. In above scenario <div>.
ParentComponent.vue
<BaseInput type="email" v-model="formData.email" :label="Email" :errors="formErrors.email"/>

How do I have a vue component with a ref apply it to a child?

I have a component that contains an input. When I put a ref on the component I want it to point to the input. Is this possible?
Vue.component('input-icon', {
props: ['value', 'icon'],
template: `
<span class="input-icon flex-container">
<span class="icon-container vertical-center" #click="icon_click" :class="{'icon-click': is_icon_click}">
<i class="material-icons">{{icon}}</i>
</span>
<input ref="input" type="text" :value="value" #input="$emit('input', $event.target.value)" class="full-flex text-left" v-bind="$attrs">
<span class="clear" #click="clear"><i class="material-icons">clear</i></span>
</span>
`,
methods: {
icon_click(e) {if (this.is_icon_click) this.$emit('button-click', e)},
clear() {
this.value = '';
this.$refs.input.focus();
}
},
computed: {
is_icon_click() {return !!this._events['button-click']}
}
});
<input-icon ref="search_bar" icon="search" v-model="search" placeholder="Search"></input-icon>
EDIT: I am aware that I can use this.$refs.search_bar.$refs.input but it's ugly. Just hoping for a better way.
If you want to access the input within the input-icon component. Create a method within the input-icon component that returns the input ref.
That is a cleaner way in my opinion

How can I access text inside an input within a template?

My objective is to get text from an input that's in a template. Not sure how to go about retrieving this. I'm using Vue; Note must be available in Vue.js, no external sources
The Template:
<template id="addmodal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
Enter Course Information:
</slot>
</div>
<div class="modal-body">
<slot name="body">
Course Name
<input type="text" ref="coursename" placeholder="Numbers Don't Lie 101">
Course Grade
<input type="text" ref ="coursemark" placeholder="100">
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
<button class="modal-default-button" #click="confirmCourse">
Submit New Course
</button>
<button class="modal-cancel-button" #click="cancelCourse">
Cancel
</button>
</slot>
</div>
</div>
</div>
</div>
</template>
I need to access coursename and coursemark. This can be done fairly easily when not inside a template. As it is right now the code executes stating .value is undefined.
var app = new Vue({
el: "#app",
data: {
courses: [],
confirmModal: false,
confirmAdd: false,
selectedCourse: null
},
methods: {
addCourse2: function addCourse2() {
this.confirmAdd = false;
var course = this.$refs.coursename.value;
var mark = this.$refs.coursemark.value;
if (course) {
this.courses.push(new Course(course, mark));
this.$refs.newcourse.value = "";
this.$refs.newmark.value = "";
}
}
}
});
EDIT:
Forgot to add the component section
Vue.component("add-modal", {
template: "#addmodal",
props: ["open", "course", "mark"],
methods: {
confirmCourse: function confirmCourse() {
alert(this.$refs.coursename.value);
this.$emit("confirm");// GET
},
cancelCourse: function cancelCourse() {
this.$emit("cancel");
}
}
});
Forgive me in advance, I feel this is something rather easy I'm missing as a beginner
use v-model. or if it is in other component. you can use $emit

Update component data from the template

Not too sure what is wrong here, it seems fine to me! I'm simply trying to update the data property display to true when I click the input within my component.
I have passed the data to the slot scope, so can't see that being the issue. It just simply won't update, using a function to toggle it works, however not what I really want to do, seems pointless.
<time-select>
<div slot-scope="{ time }" class="is-inline-block">
<label for="businessHoursTimeFrom"><i class="fas fa-clock"></i> From</label>
<input type="text" name="businessHoursTimeFrom[]" v-model="time" v-on:click="display = true">
</div>
</time-select>
The code behind:
<template>
<div>
<p>{{ display }}</p>
<slot :time="time" :display="display"></slot>
<div class="picker" v-if="display">
<p>Test</p>
</div>
</div>
</template>
<script>
export default {
props: [],
data: function () {
return {
time: '',
display: false
}
},
mounted() {
},
methods: {
}
}
</script>

How can I get value in datetimepicker bootstrap on vue component?

My view blade, you can see this below :
...
<div class="panel-body">
<order-view v-cloak>
<input slot="from-date" data-date-format="DD-MM-YYYY" title="DD-MM-YYYY" type="text" class="form-control" placeholder="Date" name="from_date" id="datetimepicker" required>
<input slot="to-date" data-date-format="DD-MM-YYYY" title="DD-MM-YYYY" type="text" class="form-control" placeholder="Date" name="to_date" id="datetimepicker" required>
</order-view>
</div>
...
My order-view component, you can see this below :
<template>
<div>
<div class="col-sm-2">
<div class="form-group">
<slot name="from-date" required v-model="fromDate"></slot>
</div>
</div>
<div class="col-sm-1">
<div class="form-group" style="text-align: center">
-
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<slot name="to-date" required v-model="toDate"></slot>
</div>
</div>
<div class="col-sm-4">
<button v-on:click="filter()" class="btn btn-default" type="button">
<span class="glyphicon glyphicon-search"></span>
</button>
</div>
</div>
</template>
<script>
export default {
data() {
return{
fromDate: '',
toDate: ''
}
},
methods: {
filter: function() {
console.log(this.fromDate)
console.log(this.toDate)
}
}
}
</script>
I using v-model like above code
But, when I click the button, the result of
console.log(this.fromDate)
console.log(this.toDate)
is empty
It display empty
Why it does not work?
How can I solve it?
You cannot bind a slot using v-model and expect that Vue will attach that automatically to your slot input, but I can't see any reason why you need to use a slot here anyway. It looks like you just want an input that you can attach custom attributes to and you can do that by passing the attributes as a prop and use v-bind to bind them:
<template>
<div>
<input v-bind="attrs" v-model="fromDate" />
<button #click="filter">filter</button>
</div>
</template>
export default{
props: ['attrs'],
methods: {
filter() {
console.log(this.fromDate)
}
},
data() {
return {
fromDate: ""
}
}
}
new Vue({
el: "#app",
data: {
fromDateAttrs: {
'data-date-format': "DD-MM-YYYY",
title: "DD-MM-YYYY",
type: "text",
class: "form-control",
placeholder: "Date",
name: "from_date",
id: "datetimepicker",
}
}
});
Now you can just pass your attrs as a prop in the parent:
<my-comp :attrs="fromDateAttrs"></my-comp>
Here's the JSFiddle: https://jsfiddle.net/rvederzc/
EDIT
In reference as to how to create a date picker component, here's how I would implement a jQuery datepicker using Vue.js:
<template id="date-picker">
<div>
<input v-bind="attrs" v-model="date" #input="$emit('input', $event.target.value)" v-date-picker/>
</div>
</template>
<script type="text/javascript">
export default {
props: ['attrs'],
directives: {
datePicker: {
bind(el, binding, vnode) {
$(el).datepicker({
onSelect: function(val) {
// directive talk for 'this.$emit'
vnode.context.$emit('input', val);
}
});
}
}
}
}
</script>
You can then bind that with v-model in the parent:
<date-picker v-model="myDate"></date-picker>
Here's the JSFiddle: https://jsfiddle.net/g64drpg6/
Cant expect any javascript technology to be complete before it becomes famous. Going by that, I tried all the recommendations from using moment to vue-datapicker. All recommendations heavily broke design and needed hardcode of the div id's in the vue initialisation under mounted. Cant introduce hacks into my project this way. Messes up design and implementation neatness.
I fixed it using plain old jsp. On Save, I just did this
vuedata.dateOfBirthMilliSecs = $("#dateOfBirth").val() ;
I'll figure out conversion of date format to milliseconds in my java controller.