How can I get the index of an element and return it from my template in Vue Js? - vue.js

<template>
<select class="form-control" id="sel2" v-model="genre_id">
<option v-for="genre in genres" v-bind:key="genre.id">
{{genre.name}}
</option>
</select
<template/>
<script>
data() {
return {
genre_id: '',
}}
<script>
The code above gets all the genres and once one is picked it returns the genre.name. My question is, instead of returning the genre.name how can I return the genre.id even though I picked the name on my select form?

Add a value attribute:
<select class="form-control" id="sel2" v-model="genre_id">
<option v-for="genre in genres" v-bind:key="genre.id" :value="genre.id">
{{ genre.name }}
</option>
</select>
The value attribute specifies the value to be sent to a server when a form is submitted.
The content between the opening and closing tags is what the browsers will display in a drop-down list. However, the value of the value attribute is what will be sent to the server when a form is submitted.
Note: If the value attribute is not specified, the content will be passed as a value instead.
Reference

Related

How can I add a disabled option when populating a select with Vue.js v-for

I would like to add a disabled option to a select that I have bound with v-for binding. The Vue docs on select suggests adding one but the example is using hard coded options.
I want to create a disabled 'Please select one' with v-for binding to force the user to pick a option rather than defaulting to a particular selection. I currently add a 'Please select one' option to the list I'm binding the select to and it shows up and works fine but I don't want the user to be able to choose it again.
How can I accomplish this when using v-for binding to a select?
//Contrived example of adding the default selection text
data.dashboardDefinitionList.splice(0, 0, { Id: 0, Name:"Select a Dashboard" });
<select id="dashboardSelectNew" v-model="formVariables.dashboardDefIndex" v-on:change="getDashboard">
<option v-for="(dd, index) in dashboardDefinitionList"
:value="dd.Id"
:selected="formVariables.dashboardDefIndex == index">
{{ dd.Name }}
</option>
</select>
Put your disabled option first, then do the v-for.
<select id="dashboardSelectNew" v-model="formVariables.dashboardDefinition" #change="getDashboard">
<option disabled value="">Please select one</option>
<option v-for="dd in dashboardDefinitionList" :key="dd.id" :value="dd">
{{ dd.Name }}
</option>
</select>
Note that I've also attempted to clean up your model / value binding but you may not want or need it.
For the initial value, you would set it to an actual entry from your list instead of a specific index, eg
this.formVariables.dashboardDefinition = this.dashboardDefinitionList[someIndex]
You can use it like this adding disabled selected to appear first and cannot be selected also good practice to put value="0" because you are using id in the value attribute
<select id="dashboardSelectNew" v-model="formVariables.dashboardDefIndex" v-on:change="getDashboard">
<option value="0" disabled selected> Please select one </option>
<option v-for="(dd, index) in dashboardDefinitionList"
:value="dd.Id"
:selected="formVariables.dashboardDefIndex == index">
{{ dd.Name }}
</option>
</select>

vee-validate validation message not working in Laravel 5.6.7

I am using Laravel 5.6.7 with vue.js for form validation. I have successfully installed using npm install vee-validate#next --save
<form role="form">
<select name="Role_ID" v-validate data-vv-rules="required">
<option :value="-1" selected>Please select Role</option>
<option v-for="RoleRecord in RoleRecords" :value="RoleRecord.Role_ID">
{{RoleRecord.Role}}
</option>
</select>
<p v-if="errors.has('Role_ID')">{{ errors.first('Role_ID') }}</p>
<!-- UserName -->
<div>
<label>UserName</label>
<div class="col-md-9">
<input name="User Name" v-validate data-vv-rules="required" type="text"
v-model="createForm.UserName">
<p v-if="errors.has('User Name')">{{ errors.first('User Name') }}</p>
</div>
</div>
<button type="button" #click="validateBeforeSubmit()">
Save Changes
</button>
</form>
<script>
export default {
methods: {
validateBeforeSubmit() {
this.$validator.validateAll();
}
}
}
</script>
My findings
Due to some reasons the option is not being validated.
There is UserName field which is working perfectly.
I am expecting that it should show the error message if the option selected value is less then 0
Am I missing anything? Please let me know if you need more info.
in the vee-validate doc,
The field under validation must have a non-empty value. By default,
all validators pass the validation if they have "empty values" unless
they are required. Those empty values are: empty strings, undefined,
null.
-1 is still considered a valid value for required validation. Use specified empty values instead. (Namely: empty strings, undefined, null)
e.g.
<option :value="null" selected>Please select Role</option>
This should trigger the required validation.
Example: https://codepen.io/jacobgoh101/pen/geaqwr?editors=1011
There's a difference between your naming:
<input name="User Name" v-validate data-vv-rules="required" type="text" v-model="createForm.UserName">
<p v-if="errors.has('User Name')">{{ errors.first('User Name') }}</p>
v-model uses UserName (without spacing). The name-attribute in your input and errors.has + errors.first are using User Name (with spacing). Please make sure you're naming things exactly the same, both in front-end as well as in back-end (and preferably without whitespace).

How to bind a value from a select?

How can I bind a value selected with aurelia?
I have this select bellow:
<select id="user" class="form-control" value.bind="filters[0].value" change.delegate="userDropdownChanged(filters[0].value)">
<option repeat.for="user of users" model.bind="user.uuid">${user.name}</option>
</select>
I tried bind the value, but it is showing the whole list of the select, it is a way to show just the user selected in my h1?
<h1 repeat.for="user of users" model.bind="user.uuid">${user.name} </h1>
If you do the following:
<select value.bind="selectedUser">
<option repeat.for="user of users" model.bind="user.uuid">${user.name}</option>
</select>
The value selected in your <select> will be bound to a variable in your viewmodel called selectedUser.
You can then bind that to your <h1> like so:
<h1>${selectedUser.name}</h1>

VueJS bind select to object but still POST string

What is the correct way to bind a select element to an object (rather than a string value) but still have the HTML element submit a string value?
I've managed to get this working, but it almost seems like I'm exploiting a bug:
<select v-model="selected" v-on:change="price=selected.price">
<option v-for="item in items" v-bind:value="item" value="{{ item.id }}">{{ item.name }}</option>
</select>
This works as intended: the "selected" property is attached to the "item" object, but the form POSTs just the item's ID. However, if I reverse the order of the HTML attributes, so that value={{ item.id }} comes before v-bind:value="item", then the form POSTs "[Object]" rather than, e.g., "3".
The fact that it's so fragile makes me think I'm doing something wrong.
So what's the right way to handle this?
I had a similar situation in which I built several vue components that could be used both within a vue component or within a standard form.
<select v-model="selected" v-on:change="price=selected.price">
<option v-for="item in items" :value="JSON.stringify(item)">{{ item.name }}</option>
</select>
Appears to be what you are after. I also had success using a computed property or filter but I decided that stringify was most readable.
I fixed it by using this approach:
<select v-model="product">
<option v-for="obj in choices" :value="obj">{{ obj.name }}</option>
</select>
<input type="hidden" name="product" :value="choice.id">
In summary: don't give your select a name but give that name to your hidden input and provide the ID as value on that element instead.
I see in both the cases, HTML being rendered as following:
<select>
<option value="[object Object]">name1</option>
<option value="[object Object]">name2</option>
<option value="[object Object]">name3</option>
<option value="[object Object]">name4</option>
</select>
Case 1 : v-bind:value="item" value="{{ item.id }}" : fiddle
Case 2 : value="{{ item.id }}" v-bind:value="item" : fiddle
So both the cases are equivalent as far as HTML being rendered. Ideal way to do it without confusion will be just using v-bind:value="item" like following:
<select v-model="selected" v-on:change="price=selected.price">
<option v-for="item in items" v-bind:value="item">{{ item.name }}</option>
</select>
You should v-bind to item or item.id depending on what you want to assign to selected variable.

How to prevent duplicated ID in partial views and still reference them in the Javascript code?

I have a shared view that is going to be called for each item in a collection. In this view I want to have a dropdown list that will contain the Id, Text and image url of the information selected item. When an Item is selected I want to show the image in an image tag.
I got to this code
<select id="themes" onchange="javascript:document.getElementById('themePlaceHolder').src=this.options[this.selectedIndex].getAttribute('data-url')">
<option value="" data-Url="" >Select a theme</option>
#foreach(Theme theme in Model.Themes) {
<option value="#theme.Id" data-url="#theme.Url" >#theme.Name</option>
}
</select>
<img id="themePlaceHolder" src="" />
This works perfectly when my collection has only one element, but if it has 2 or more, I have issues with the ID used to identify the image tag because it is duplicated.
Is there anyway to generate the ID so it isn't duplicated but still reference it on my onchange element?
Try with jQuery:
Pseudo code:
<select class="themes">
<option value="" data-Url="" >Select a theme</option>
#foreach(Theme theme in Model.Themes) {
<option value="#theme.Id" data-url="#theme.Url" >#theme.Name</option>
}
</select>
<img id="themePlaceHolder" src="" />
$(".themes").change(function(){
// to get selected text
$(this + " option:selected").text();
// to get selected value
$(this).val();
// Now do what ever you want using this value
});