Can someone help me generate dynamic v-model values?
<div v-for="car in cars">
<div class="row">
<div class="col-md-2">
<p v-model="car.attr_1">{{ car.attr_1 }}</p>
</div>
<div class="col-md-3">
<p v-model="car.attr_2">{{ car.attr_2 }}</p>
</div>
<div class="col-md-2">
<p v-model="car.attr_3">$ {{ car.attr_3 }}</p>
</div>
<div class="col-md-2">
<p><input type="text" class="" placeholder="Quantity" v-on:click="addCar(car)"/></p>
</div>
</div>
</div>
<script>
module.exports = {
data: function () {
return {
cars: ''
}
},
methods: {
getCars: function () {
var self = this;
$.ajax({
type: "GET",
url: '/api/cars',
success: function(data) {
self.cars = data;
}
});
}
}
}
</script>
Sample JSON response - note how all the properties are different..:
cars: [
{
make: 'Audi',
model: 'R8',
color: 'red'
},
{
make: 'Chevy',
tires: 'All Season',
weight: 30
},
{
make: 'Chevy',
tires: 'Summer',
color: 'black'
},
{
make: 'Ford',
weight: 40,
gps: true
}
]
I have an ajax call that returns an array of cars objects. The problem is all the objects returned have variable attributes. Therefore, how can vue.js handle these variable attributes for v-model? I've tried things like v-model="car[ {{attr_1}} ]" but these all return errors.. Can someone help?
Thanks in advance!
You can do it something like:
<div v-for="car in cars">
<div class="row">
<div class="col-md-2" v-if="car.make">
<p v-model="car.make">{{ car.make }}</p>
</div>
<div class="col-md-3" v-if="car.tires">
<p v-model="car.tires">{{ car.tires }}</p>
</div>
<div class="col-md-2" v-if="car.color">
<p v-model="car.color">$ {{ car.color }}</p>
</div>
<div class="col-md-2">
<p><input type="text" class="" placeholder="Quantity" v-on:click="addCar(car)"/></p>
</div>
</div>
</div>
alternatively, You can also write a method, which given car object and attribute, will return corresponding value:
function(car, attr){
return car[attr];
}
Related
I have an array of strings like:
questions: [
"Question 1?",
"Question 2?",
"Question 3?",
"Question 4?",
],
Then I have form fields in my data() like:
legitForm: {
name: '', // this will be equal to question string
answer: '',
description: '',
duration: '',
},
Now, the problem I'm facing is when I fill inputs for any of questions
above the same field for other questions gets same value.
Here is my template code:
<div v-for="(question, index) in questions" :key="index">
<form #submit.prevent="legitStore(question)" method="post">
<div class="row">
<div class="col-md-12">
<p>
<strong>{{question}}</strong>
</p>
</div>
<div class="col-md-6">
<label for="answer">Answer</label>
<select class="mb-1 field" v-model="legitForm.answer" name="answer" id="answer">
<option value="1">Yes</option>
<option value="0">No</option>
</select>
</div>
<div class="col-md-6">
<label for="duration">Duration</label>
<input class="field" v-model="legitForm.duration" type="text">
</div>
<div class="col-md-12">
<label for="description">Description</label>
<textarea style="height: 190px;" type="text" cols="5" rows="10" id="address" class="mb-1 field" v-model="legitForm.description"></textarea>
</div>
</div>
<button type="submit" class="saveButtonExperience float-right btn btn--custom">
<span class="text">Save</span>
</button>
</form>
</div>
And this is my post method that sends data to backend:
legitStore(question) {
this.legitForm.name = question; // set "name" in `legitForm` to value of `question` string
axios.post('/api/auth/userLegitsStore', this.legitForm, {
headers: {
Authorization: localStorage.getItem('access_token')
}
})
.then(res => {
// reset my data after success
this.legitForm = {
name: '',
answer: '',
description: '',
duration: '',
};
})
.catch(error => {
var errors = error.response.data;
let errorsHtml = '<ol>';
$.each(errors.errors,function (k,v) {
errorsHtml += '<li>'+ v + '</li>';
});
errorsHtml += '</ol>';
console.log(errorsHtml);
})
},
Here is issue screenshot:
Note: I've tried to
change legitForm to array like legitForm: [], and legitForm: [{....}]
add index to my inputs v-model
but I've got errors so i wasn't sure what I'm doing wrong, that's why
I'm asking here.
If you think of your questions as questions and answers, you can do something like this:
questions: [
{
question: 'Question 1',
answer: null,
description: null,
duration: null,
},
{
question: 'Question 2',
answer: null,
description: null,
duration: null,
},
]
Then when looping through your form, it would be more like this:
<div v-for="(question, index) in questions" :key="index">
<form #submit.prevent="legitStore(question)" method="post">
...
<select class="mb-1 field" v-model="question.answer" name="answer" id="answer">
<option value="1">Yes</option>
<option value="0">No</option>
</select>
...
</form>
</div>
And in the storing function you could send the data in the question instead of this.legitForm
Like you said you tried here:
change legitForm to array like legitForm: [], and legitForm: [{....}]
add index to my inputs v-model
You are supposed to be doing that.
I would change legitForm to:
//create legitForms equal to the length of questions
const legitForms = [];
for (i in questions) legitForms.push(
{
name: '', // this will be equal to question string
answer: '',
description: '',
duration: '',
}
);
and in template:
<div v-for="(question, index) in questions" :key="index">
<form #submit.prevent="legitStore(question)" method="post">
<div class="row">
<div class="col-md-12">
<p>
<strong>{{question}}</strong>
</p>
</div>
<div class="col-md-6">
<label for="answer">Answer</label>
<select class="mb-1 field" v-model="legitForms[index].answer" name="answer" id="answer">
<option value="1">Yes</option>
<option value="0">No</option>
</select>
</div>
<div class="col-md-6">
<label for="duration">Duration</label>
<input class="field" v-model="legitForms[index].duration" type="text">
</div>
<div class="col-md-12">
<label for="description">Description</label>
<textarea style="height: 190px;" type="text" cols="5" rows="10" id="address" class="mb-1 field" v-model="legitForms[index].description"></textarea>
</div>
</div>
<button type="submit" class="saveButtonExperience float-right btn btn--custom">
<span class="text">Save</span>
</button>
</form>
</div>
<div v-for="(question, index) in questions" :key="index">
In your template you iterate through questions and within this tag render object legitForm it all questions will refer to the same 1 object that's why all question have the same data.
You should have had create an array of question contains it own question's content like
<template>
<div v-for="(question, index) in questions" :key="index">
<form #submit.prevent="legitStore(question)" method="post">
...
<div class="col-md-12">
<p>
<strong>{{question.id}}</strong>
</p>
</div>
...
<select class="mb-1 field" v-model="question.answer" name="answer" id="answer">
<option value="1">Yes</option>
<option value="0">No</option>
</select>
...
</form>
</div>
</template>
<script>
class QuestionForm {
// pass default value if you want
name = ''
answer = ''
description = ''
duration = ''
id = ''
constructor(form) {
Object.assign(this, form)
}
}
function initQuestions(num) {
// can generate a Set object cause question are unique
return Array.from({ length: num }, (v, i) => i).map(_j => new QuestionForm())
}
export default {
data() {
return {
questions: initQuestions(5), // pass number of question you want to generate
}
}
}
</script>
I have dynamic generated form in Vue. Every loop have v-model. Everything work fine. But when I use checkboxes v-model work for all loops not on one like in input type text. Can You help me solved this problem? Below Vue code:
<fieldset>
<div class="form-row mb-2" v-for="input, index in journal" :key="index">
<div class="col-auto">
<label for="date">Data</label>
<Datepicker v-model="input.date" input-class="form-control" :input-attr="{id: 'date', name: 'date'}" style="width: 100%;" />
</div>
<div class="col-md-2">
<label for="timeStart">Od</label>
<Datepicker type="time" v-model="input.timeStart" format="HH:mm" input-class="form-control" :input-attr="{id: 'timeStart', name: 'timeStart'}" style="width: 100%;" />
</div>
<div class="col-md-2">
<label for="timeEnd">Do</label>
<Datepicker type="time" v-model="input.timeEnd" format="HH:mm" input-class="form-control" :input-attr="{id: 'timeEnd', name: 'timeEnd'}" style="width: 100%;" />
</div>
<div class="col-md-2">
<label for="players">Lista obecności</label>
<div class="form-check" v-for="item in input.players">
<input v-model="item.checked" type="checkbox" class="form-check-input" :id="'id-'+item.id+'set'+index">
<label class="form-check-label" :for="'id-'+item.id+'set'+index">{{ item.fullName }}</label>
</div>
</div>
<div class="col-auto">
<label for="description">Opis</label>
<textarea v-model="input.description" class="form-control" rows="7" id="description" placeholder="Opis"></textarea>
</div>
<div class="col-auto" #click="addInput" v-show="index == journal.length-1 && journal.length < 16">
<ButtonVue style="margin-top: 30px;" title="Dodaj" type="button" cancelWidth="true" color="btn-success"><i class="fas fa-plus"></i></ButtonVue>
</div>
<div class="col-auto align-self-start" #click="removeInput(index)" v-show="index || ( !index && journal.length > 1)">
<ButtonVue style="margin-top: 30px;" title="Usuń" type="button" cancelWidth="true" color="btn-danger"><i class="fas fa-minus"></i></ButtonVue>
</div>
</div>
</fieldset>
data() {
return {
contact: [],
journal: [{
date: "",
timeStart: "",
timeEnd: "",
players: "",
description: ""
}],
contacts: [],
}
},
Methods:
Method for creating dynamic form
addInput() {
this.journal.push({
date: "",
timeStart: "",
timeEnd: "",
players: this.contact,
description: ""
});
},
And here is the method which gets players from contacts
getContacts() {
this.pageLoader = true;
this.$http.get('/pkpar/get-contacts')
.then(({
data
}) => {
this.contacts = data.contacts;
for(let i=0; i<this.contacts.length; i++)
{
this.contact.push({'id': this.contacts[i]['id'], 'fullName' :
this.contacts[i]['fullName'], 'checked': true});
}
this.journal[0].players = this.contact;
this.pageLoader = false;
})
.catch(error => {
console.log(error);
});
},
Your addInput method creates and pushes new object into journal array, but each object created this way has a players property which references same array (this.contact)
The Difference Between Values and References in JavaScript
Easiest (but not most optimal) way to handle this is to create a copy of the array and objects inside for each new journal:
addInput() {
this.journal.push({
date: "",
timeStart: "",
timeEnd: "",
players: this.contact.map((player) => ({ ...player })),
description: ""
});
},
I have a list with comments, those comments have a moment field, which is a DateTimeField. In this DateTimeField I have for example this --> 2020-06-03T15:32:01.803027 and I want to delete that T character, or replace with a blank space.
I'm using Django for the backend and Vue.js for the frontend.
I was able to remove the Z character by changing the USE_TZ = True to False option in the settings.py file. But I can't remove the T character, that's all I need. I have tried from the frontend to remove the T character using methods and computed properties, but I can't use the replace("T", " ") method on a DateTimeField, I can only use it on a String
<template lang="html">
<div class="container">
<div class="row">
<div class="col text-left">
<h2>Detalles del partido</h2>
</div>
</div>
<div class="row">
<div class="col">
<div class="card">
<div class="card-body">
<form>
<form #submit="onSubmit">
<div class="form-group row">
<label for="nombreLocal" class="col-sm-2 col-form-label">Local</label>
<div class="col-sm-6">
<input type="text" name="nombreLocal" class="form-control" readonly v-model.trim="form.nombreLocal">
</div>
</div>
<div class="form-group row">
<label for="nombreVisitante" class="col-sm-2 col-form-label">Visitante</label>
<div class="col-sm-6">
<input type="text" name="nombreVisitante" class="form-control" readonly v-model.trim="form.nombreVisitante">
</div>
</div>
<div class="form-group row">
<label for="resultado" class="col-sm-2 col-form-label">Resultado</label>
<div class="col-sm-6">
<input type="text" name="resultado" class="form-control" readonly v-model.trim="form.resultado">
</div>
</div>
<div class="form-group row">
<label for="pronosticoSistema" class="col-sm-2 col-form-label">Pronóstico del sistema</label>
<div class="col-sm-6">
<input type="text" name="pronosticoSistema" class="form-control" readonly v-model.trim="form.pronosticoSistema">
</div>
</div>
<div class="form-group row">
<label for="premio" class="col-sm-2 col-form-label">Premio</label>
<div class="col-sm-6">
<input type="number" name="premio" class="form-control" readonly v-model.trim="form.premio">
</div>
</div>
<div class="form-group row">
<label for="dificultad" class="col-sm-2 col-form-label">Dificultad</label>
<div class="col-sm-6">
<input type="text" name="dificultad" class="form-control" readonly v-model.trim="form.dificultad">
</div>
</div>
<div class="rows">
<div class="col text-left">
<b-button size="sm" variant="primary" :to="{ name:'CreatePronostico', params: {partidoId: this.partidoId} }">
Pronosticar
</b-button>
<b-button size="sm" variant="primary" :to="{ name:'CreateComentario', params: {partidoId: this.partidoId}}">
Comentar
</b-button>
<b-button size="sm" type="submit" class="btn-large-space" :to="{ name: 'PronosticadorUsuario'}">Atrás</b-button>
</div>
</div>
</form>
<br>
<h2>Comentarios</h2>
<br>
<div class="comentarios">
<b-table striped hover
:items="comentarios"
:fields="fields"
:sort-by.sync="sortBy"
:sort-desc.sync="sortDesc">
<template v-slot:cell(action)="data">
<b-button size="sm" variant="primary" :to="{ name:'CreateComentarioRespuesta', params: {comentarioId: data.item.id} }">
Responder
</b-button>
<b-button size="sm" variant="primary" :to="{ name:'DarMeGusta', params: {comentarioId: data.item.id} }">
Me gusta
</b-button>
<b-button size="sm" variant="primary" :to="{ name:'EditComentario', params: {comentarioId: data.item.id} }">
Editar
</b-button>
<b-button size="sm" variant="danger" :to="{ name:'DeleteComentario', params: {comentarioId: data.item.id} }">
Eliminar
</b-button>
</template>
</b-table>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
import swal from 'sweetalert'
import router from "../../router";
export default {
mounted() {
this.checkLoggedIn();
},
data() {
return {
sortBy: 'momento',
sortDesc: false,
partidoId: this.$route.params.partidoId,
form: {
nombreLocal: '',
nombreVisitante: '',
resultado: '',
pronosticoSistema: '',
premio: '',
dificultad: ''
},
fields: [
{ key: 'id', label: 'Número de comentario' },
{ key: 'momento', label: 'Momento', sortable: true},
{ key: 'texto', label: 'Texto' },
{ key: 'meGustas', label: 'Número de "me gustas"', sortable: true},
{ key: 'autor', label: 'Autor' },
{ key: 'comentarioRespuesta', label: 'Responde a' },
{ key: 'action', label: '' }
],
comentarios: []
}
},
methods: {
checkLoggedIn() {
this.$session.start();
if (!this.$session.has("token")) {
router.push("/auth");
}
},
onSubmit(evt){
evt.preventDefault()
const path = `http://localhost:8000/api/v1.0/partidos/${this.partidoId}/`
axios.get(path, this.form).then((response) =>{
this.form.nombreLocal = response.data.nombreLocal
this.form.nombreVisitante = response.data.nombreVisitante
this.form.resultado = response.data.resultado
this.form.pronosticoSistema = response.data.pronosticoSistema
this.form.premio = response.data.premio
this.form.dificultad = response.data.dificultad
})
.catch((error) => {
console.log(error)
})
},
getPartido (){
const path = `http://localhost:8000/api/v1.0/partidos/${this.partidoId}/`
axios.get(path).then((response) =>{
this.form.nombreLocal = response.data.nombreLocal
this.form.nombreVisitante = response.data.nombreVisitante
this.form.resultado = response.data.resultado
this.form.pronosticoSistema = response.data.pronosticoSistema
this.form.premio = response.data.premio
this.form.dificultad = response.data.dificultad
})
.catch((error) => {
console.log(error)
})
},
getComentarios (){
const path = 'http://localhost:8000/api/v1.0/comentarios/'
axios.get(path).then((response) => {
this.comentarios = response.data
})
.catch((error) => {
console.log(error)
})
},
},
computed: {
comentariosFormateados: function (){
var res = [];
for(var i = 0; i < this.comentarios.length; i++){
this.comentarios[i].momento.toISOString().replace('T', '');
res.push(comentarios[i]);
}
return res;
}
},
created() {
this.getPartido(),
this.getComentarios()
}
}
</script>>
<style lang="css" scoped>
</style>
Just return the Django DateTime object formatted however you want, for example:
myDateTime = strftime(MyModel.objects.get(id=id).moment, "%Y-%m-%d %H:%M:%S.%f")
Or:
comment = MyModel.objects.get(id=id)
moment = strftime(comment.moment, "%Y-%m-%d %H:%M:%S.%f")
comment.formatted_moment = moment
...
Then return it to your view in that format (a formatted string).
I've solved with this:
formatMomento(value) { const formattedDate = DateTime.fromISO(value).toLocaleString(DateTime.DATETIME_SHORT); return formattedDate; },
And calling it from the formatter attribute:
fields: [
{ key: 'id', label: 'Número de comentario' },
{ key: 'momento', formatter: "formatMomento", label: 'Momento', sortable: true},
{ key: 'texto', label: 'Texto' },
{ key: 'meGustas', label: 'Número de "me gustas"', sortable: true},
{ key: 'autor', formatter: "nombreDeUsuario", label: 'Autor' },
{ key: 'comentarioRespuesta', label: 'Responde al comentario:' },
{ key: 'action', label: '' }
],
I am attempting to add objects into an array I declared in Vue instance data object. I can set the values in the state's purchase object, but when I push data into the orders queue array, the empty array is not populated. The function is being triggered, but the array does not update.
Here is my form:
<form
v-on:submit.prevent="queuePurchase"
class="form-inline row"
id="order-creation-form"
method="POST"
>
#csrf
<autocomplete-field
sizing="col-xs-12 col-sm-3 col-md-3"
name="customer"
label="Customer"
:data="{{ json_encode($customers) }}"
v-on:setcustomer="setCustomer($event)"
></autocomplete-field>
<div class="col-xs-12 col-sm-3 col-md3 form-group d-flex flex-column align-items-start">
<label for="phone">Product</label>
<select
v-model="purchase.product"
class="form-control w-100"
name="product"
aria-describedby="productHelpBlock"
required
>
#foreach ($products as $product)
<option :value="{{ json_encode($product) }}">
{{ $product->name }}
</option>
#endforeach
</select>
<small id="productHelpBlock" class="form-text text-muted">
Select a product
</small>
</div>
<div class="col-xs-12 col-sm-3 col-md-3 form-group d-flex flex-column align-items-start">
<label for="phone">Quantity</label>
<input
v-model="purchase.quantity"
type="number"
min="1"
name="product"
class="form-control w-100"
aria-describedby="productHelpBlock"
required
>
<small id="productHelpBlock" class="form-text text-muted">
Product quantity
</small>
</div>
<div class="form-group">
<button type="submit" class="btn btn-success icon-button d-flex">
<i class="material-icons">add</i>
<span> Q U E U E</span>
</button>
</div>
</form>
And here is my javascript:
require("./bootstrap");
window.Vue = require("vue");
Vue.component("queue-table", require('./components/QueueTable.vue'));
Vue.component("autocomplete-field", require('./components/AutocompleteField.vue'));
const purchaseApp = new Vue({
el: "#purchase-app",
data() {
return {
queue: [],
purchase: {
product: null,
customer: null,
quantity: null
}
}
},
methods: {
setCustomer: function(customerObj) {
this.purchase.customer = customerObj;
},
queuePurchase: function() {
this.queue.push( this.purchase );
}
}
});
Could someone please explain what & why it is happening?
The push() method ought to add purchase objects to the queue array, but as #FK82 pointed out in his comment, push() is adding multiple references to the same purchase object. This means that if you change the object by increasing the quantity, every purchase's quantity property will be updated.
You can give that a try here:
const exampleComponent = Vue.component("example-component", {
name: "exampleComponent",
template: "#example-component",
data() {
return {
queue: [],
purchase: {
product: null,
customer: null,
quantity: null
}
};
},
methods: {
queuePurchase() {
this.queue.push( this.purchase );
}
}
});
const page = new Vue({
name: "page",
el: ".page",
components: {
"example-component": exampleComponent
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.4/vue.min.js"></script>
<template id="example-component">
<div>
<p>The Queue has {{ this.queue.length }} items.</p>
<input
v-model="purchase.quantity"
type="number"
min="1"
name="product"
placeholder="Quantity"
>
<button #click="queuePurchase">
Add to Queue
</button>
<pre>{{ JSON.stringify(this.queue, null, 2) }}</pre>
</div>
</template>
<div class="page">
<example-component></example-component>
</div>
Instead of push()ing a reference to the same purchase object, try creating a shallow copy with Object.assign({}, this.purchase) or by using the spread operator. Here's an example that uses the spread operator and then push()es the copy onto the queue:
const exampleComponent = Vue.component("example-component", {
name: "exampleComponent",
template: "#example-component",
data() {
return {
queue: [],
purchase: {
product: null,
customer: null,
quantity: null
}
};
},
methods: {
queuePurchase() {
this.queue.push({...this.purchase});
}
}
});
const page = new Vue({
name: "page",
el: ".page",
components: {
"example-component": exampleComponent
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.4/vue.min.js"></script>
<template id="example-component">
<div>
<p>The Queue has {{ this.queue.length }} items.</p>
<input
v-model="purchase.quantity"
type="number"
min="1"
name="product"
placeholder="Quantity"
>
<button #click="queuePurchase">
Add to Queue
</button>
<pre>{{ JSON.stringify(this.queue, null, 2) }}</pre>
</div>
</template>
<div class="page">
<example-component></example-component>
</div>
I am using below code.
HTML code
<form name="profInfoForm" ng-submit="saveInfo(profInfoForm)" novalidate>
<div class="wrapper">
<div class="container">
<section class="main-ctr">
<div class="error-msg" ng-show="showErrorMsg">
<div class="text">Please fix the validation error(s) below and try again.<br />{{serviceErrorMsg}}</div>
</div>
<div ng-include="'views/header.html'"></div>
<main class="sm-main">
<section class="fix-section">
<h1>Professional information</h1>
<div class="lg-form">
<div class="form-group">
<label class="text-label lg-label">Salutation</label>
<div class="select-wrap lg-select">
<select class="form-input select" name="salutation" required ng-init="profInfo.salutation = item[0]"
ng-options="item.name as item.name for item in salutations"
ng-model="profInfo.salutation">
</select>
<div class="error" ng-show="profInfoForm.$submitted || profInfoForm.salutation.$touched">
<span ng-show="profInfoForm.salutation.$error.required">Required Field</span>
</div>
</div>
</div>
</div>
</section>
<div class="clear"></div>
<div class="button-ctr">
<button class="button" ng-class="profInfoForm.$valid ? 'active' : 'disable'">Next</button>
</div>
</main>
</section>
</div>
</div>
<div id="loading" ng-if="showLoader">
<img src="images/loader.gif" id="loading-image">
</div>
</form>
My constant.js
.constant('APP_CONSTANTS', {
SALUTATIONS: [{ id: 0, name: 'Select' }, { id: 1, name: 'Mr.' }, { id: 2, name: 'Mrs.' }, { id: 3, name: 'Miss' }, { id: 4, name: 'Dr.' }, { id: 5, name: 'Ms'}]
})
Controller code is given below
.controller('professionalInfoCtrl', ['$rootScope', '$scope', '$state', 'globalService', 'APP_CONSTANTS', 'dataServices', function ($rootScope, $scope, $state, globalService, APP_CONSTANTS, dataServices) {
$scope.showLoader = false;
$scope.profInfo = userData;
$scope.salutations = APP_CONSTANTS.SALUTATIONS;
}])
I want to set default value of Salutation drop down list.
For this I am using ng-init but this is not working. I did not to find out the problem.
Please consider using ui-select of AngularUI:
<ui-select ng-model="$parent.company">
<!-- using $parent - https://github.com/angular-ui/ui-select/issues/18 -->
<ui-select-match>{{$select.selected.name}}</ui-select-match>
<ui-select-choices repeat="company in companies>{{company.name}}</ui-select-choices>
</ui-select>
I resolved my issue by using below code
<select class="form-input select" ng-model="profInfo.salutation" required
ng-options="item.name as item.name for item in salutations">
<option value="">Select salutation...</option>
</select>
<div class="error" ng-show="profInfoForm.$submitted || profInfoForm.salutation.$touched">
<span ng-show="profInfoForm.salutation.$error.required">Required Field</span>
</div>
As simple I am using
<option value="">Select salutation...</option>
Thanks everyone.