Select Option Change To Trigger Additional Code - onchange

Ok so I am trying to write a script that will show and hide items based on a users selection. I was able to figure out how to do this with a radio group but when it comes to a select item I just cant figure it out. Anyone have an idea what I'm doing wrong here?
my jQuery
$('select#contact').change(function() {
var isPhone = $('#phone').is(':selected');
var isEmail = $('#email').is(':selected');
$('#cell').toggleClass('req', isPhone);
if ( isPhone === true ) {
$('#phoneNum').animate({'height':'show'}, 500);
} else if ( isPhone === false ){
$('#phoneNum').animate({'height':'hide'}, 200);
}
$('#Remail').toggleClass('req', isEmail);
if ( isEmail === true ) {
$('#emailAdd').animate({'height':'show'}, 500);
} else if ( isEmail === false ){
$('#emailAdd').animate({'height':'hide'}, 200);
}
});
my HTML
<p>
<label for="contact">How Would You Like Us To Contact You?</label>
<select id="contact" name="contact" class="req">
<option></option>
<option id="phone">By Phone</option>
<option id="email">By Email</option>
</select>
</p>
<p id="phoneNum">
<label for="cell">Best Phone Number</label>
<input id="cell" name="cell" type="tel" placeholder="e.g. 555-555-5555" class=""/>
</p>
<p id="emailAdd">
<label for="Remail">Email</label>
<input id="Remail" name="Remail" placeholder="something#something.com" type="email" class=""/>
</p>

Figured it out:
$('select#contact').change(function() {
var isPhone = $(this).find("option:selected").is('#phone');
var isEmail = $(this).find("option:selected").is('#email');
$('#cell').toggleClass('req', isPhone);
if ( isPhone === true ) {
$('#phoneNum').animate({'height':'show'}, 500);
} else if ( isPhone === false ){
$('#phoneNum').animate({'height':'hide'}, 200);
}
$('#Remail').toggleClass('req', isEmail);
if ( isEmail === true ) {
$('#emailAdd').animate({'height':'show'}, 500);
} else if ( isEmail === false ){
$('#emailAdd').animate({'height':'hide'}, 200);
}
});

Related

Dynamic Rendering with V-If

I am creating a form and I want to show certain fields only when a certain button is pressed, but take those fields away and show other fields when another button is pressed.
I am new to vue (and coding), but I think I'm wanting to use v-if, but I can't seem to return the values back to the v-if field.
If the type MAGAZINE is selected, then a method sets the typeIsMagazine to TRUE and the other typeselectors to FALSE. I would expect that once typeIsMagazine is set to true, then the v-if would be triggered and the form fields will be shown.
The method is being triggered, and I am testing it with console.log so I know the if functions are working. I just don't think it's being returned to v-if.
<template>
<form #submit.prevent="handleSubmit">
<label class="main">Type:</label>
<div class="type-row">
<div class="sub-column">
<div
class="sub"
#click="updateType('auto_stories')"
:class="{ selected: type === 'auto_stories' }"
>
Book
</div>
</div>
<div class="sub-column">
<div
class="sub"
#click="updateType('article')"
:class="{ selected: type === 'article' }"
>
Article
</div>
</div>
<div class="sub-column">
<div
class="sub"
#click="updateType('website')"
:class="{ selected: type === 'website' }"
>
Website
</div>
</div>
</div>
<template v-if="typeIsWebsite">
<label class="main">Website:</label>
<input type="text" class="text" v-model="url" required />
</template>
<template v-if="typeIsArticle">
<label class="main">Magazine:</label>
<input type="text" class="text" v-model="magazine" required />
</template>
<button class="form">Add Entry</button>
</form>
</template>
<script>
export default {
data() {
return {
typeIsWebsite: false,
typeIsArticle: false,
typeIsBook: false,
};
},
methods: {
updateType(typeSelect) {
this.type = typeSelect;
let typeIsWebsite = false;
let typeIsBook = false;
let typeIsArticle = false;
if (typeSelect === "website") {
typeIsWebsite = true;
typeIsArticle = false;
typeIsBook = false;
} else if (typeSelect === "article") {
typeIsWebsite = false;
typeIsArticle = true;
typeIsBook = false;
} else if (typeSelect === "auto_stories") {
typeIsWebsite = false;
typeIsArticle = false;
typeIsBook = true;
}
return typeIsWebsite, typeIsArticle, typeIsBook;
},
In updateType, your variables typeIsWebsite, typeIsBook, etc are declared as local variables using let. Thus, when you do the if, you are updating local variables, not your component's instance variables.
To fix, remove the typeIsX variable declarations in updateType, and use this.typeIsX to refer to each variable.
Like so:
updateType(typeSelect) {
this.type = typeSelect;
if (typeSelect === "website") {
this.typeIsWebsite = true;
this.typeIsArticle = false;
this.typeIsBook = false;
} else if (typeSelect === "article") {
this.typeIsWebsite = false;
this.typeIsArticle = true;
this.typeIsBook = false;
} else if (typeSelect === "auto_stories") {
this.typeIsWebsite = false;
this.typeIsArticle = false;
this.typeIsBook = true;
}
}
Finally, the function doesn't need to return anything.
As an extra advice, note that this is really verbose code and at least in your use case you don't need all the flags. Just keeping the current type as a string and then comparing against that would be enough. For example:
this.typeIsWebsite is equivalent to this.type === 'website'.
Remember: less code means less errors!

Error mesage quickly displaying then hiding as expected in VUE

I have a page which I validate the email add input #blur. This works perfectly and displays the error message if it fails validation rules set but the issue I have is that due to the #blur, when I click my reset button the error quickly displays then hides and this is poor UI and I want to stop it but can't figure out how to.
HTML
<div class="card" v-on:click="select($event)">
<div class="card-body">
<div class="form-group row">
<label class="col-sm-3 col-form-label pr-0" for="emailAddField">Email <span class="text-danger">*</span></label>
<div class="col-sm-9">
<div class="input-group">
<input id="emailAddField" ref="pdEmailAdd" class="form-control" type="search" :value="pdEmailAdd" #input="pdEmailAddInput" #blur="emailInputValChecker($event)" placeholder="Enter an email address">
<div class="input-group-append" :class="emailButtonValidation">
<a class="btn input-group-text primaryBtn" :class="emailButtonValidation" type="button" :href="'mailto:' + pdEmailAdd">
<i class="far fa-envelope"></i>
</a>
</div>
</div>
<div v-if="emailFormatErrorMsg" class="text-danger">Incorrect email address format</div>
</div>
<div class="card-footer">
<button id="resetButton" ref="resetButton" class="btn btn-warning col-4" #click="pdInitPageStates($event)" :disabled="resetDetails">
Reset details
</button>
</div>
</div>
I have 'hacked' at the card trying to use #click on the card to get the id but this didn't work so I set the id in my `data but not happy about it and sure there is a lot better way but I just can't figure it out
Code
data() {
return {
pdEmailAdd: '',
reg: /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,24}))$/,
detailsChanged: false,
emailIncorrectFormat: false,
targetId: 'resetButton', // HACK
targetId2: '', // HACK
}
},
computed: {
emailButtonValidation() {
if (!this.pdEmailAdd || !this.reg.test(this.pdEmailAdd)) {
if (this.pdEmailAdd === '') {
this.emailIncorrectFormat = false;
} else {
this.emailIncorrectFormat = true;
}
return 'disabled'
} else {
this.emailIncorrectFormat = false;
return ''
}
},
resetDetails() {
this.detailsChanged = false;
if (this.pdName != this.$store.state.account.firstname + ' ' + this.$store.state.account.lastname) {
this.detailsChanged = true;
}
if (this.telNoType === 'ddi' && this.pdTelNo != this.$store.state.account.ddi) {
this.detailsChanged = true;
} else if (this.telNoType === 'mobile' && this.pdTelNo != this.$store.state.account.mobile) {
this.detailsChanged = true;
} else if (this.telNoType === 'na' && this.pdTelNo != '') {
this.detailsChanged = true;
}
if (this.pdExtNo != this.$store.state.account.extension) {
this.detailsChanged = true;
}
if (this.pdEmailAdd != this.$store.state.user.adminemail) {
this.detailsChanged = true;
}
return !this.detailsChanged;
}
}
// Another hack to try set it soon as page loads
mounted() {
this.$refs.resetButton.click();
},
methods: {
emailInputValChecker(event) {
this.emailFormatErrorMsg = false;
if (!this.pdEmailAdd || !this.reg.test(this.pdEmailAdd)) {
if (this.pdEmailAdd === '') {
this.emailFormatErrorMsg = false;
} else {
this.select(event)
// Uses the 'dirty hacks'
if (this.targetId !== '' && this.targetId !== 'resetButton' && this.targetId2 !== 'resetButton') {
this.emailFormatErrorMsg = true;
};
}
}
},
select(event) {
this.targetId = event.target.id;
if (this.targetId === 'resetButton') {
this.targetId2 === 'resetButton';
} else if (this.targetId === '') {
this.targetId === 'resetButton';
}
}
}
Basically all I want is the input to check it passes validation when input is left unless the reset button is clicked then ignore it but think I've gone code blind and can't think of a way to do this.
The mousedown event on your reset button is what causes blur on the input to fire. Adding #mousedown.prevent to the reset button will stop that from happening specifically when the reset button is clicked.
This snippet ought to illustrate the solution. Remove #mousedown.prevent from the reset button and you'll see similar behavior to your issue, with the error briefly flashing.
new Vue({
el: '#app',
data: {
email: '',
error: null
},
methods: {
onBlur () {
if (this.email === 'bad') {
this.error = 'bad email!'
} else {
this.error = null
}
},
onReset () {
this.error = null
this.email = ''
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="onReset" #mousedown.prevent>Reset</button>
<p>
Type in "bad" and leave input to trigger validation error<br>
<input type="text" v-model="email" #blur="onBlur"/>
</p>
<p>{{ email }}</p>
<p v-if="error">error!</p>
</div>

vee-validate in steps form

I have a problem I'm trying to learn vee-validate
to a form that has steps but the problem is like as far
as the first drop I validate correctly a field from the second step is no longer works properly or someone could help this is all component and methods i think this is scope problem but i don't now?
<template>
<div>
<div v-if="step === 1">
<input
class="form-control loginForm__input"
type="text"
:class="{'input': true, 'is-invalid': errors.has('email') }"
name="email"
v-validate="'required|email'"
placeholder="Email adress"
v-model="registration.email"
/>
</div>
<div v-if="step === 2">
<input
class="form-control loginForm__input"
:class="{'input': true, 'is-invalid': errors.has('nameFirst') }"
v-validate="'required'"
name="nameFirst"
type="text"
placeholder="name"
v-model="registration.nameFirst"
/>
<div class="LoginButton">
<button
type="button"
class="btn button__blue"
#click="nextStep();progressbarNext();"
>Continue</button>
</div>
</div>
</template>
<script>
export default {
name: "Register",
components: {
},
data: function() {
return {
step: 1,
registration: {
email: null,
nameFirst: null,
}
};
},
computed: {},
methods: {
goBack() {
if (this.step === 1) {
this.$router.push("/");
return;
}
this.step--;
},
nextStep() {
this.$validator.validateAll().then(result => {
console.log(result);
if (result) {
if (this.step === 3) {
this.showModal = true;
(this.stepBannerThree = true), (this.step = 3);
return;
}
this.step++;
if (this.step == 2) {
return (this.stepBannerOne = true);
}
if (this.step == 3) {
return (this.stepBannerTwo = true);
}
return;
}
});
},
}
};
</script> ```

Filtering with Vuejs w/ axios

Hoping someone can point me in the right direction - I'm fairly new to Vuejs and have taken over someone else's code, although I've managed to do a fair bit without any issues, i'm struggling to get the filtering to work.
Here is the majority of the code:
<template>
<div v-if="showProperties">
<div v-if="properties.length > 0">
<div class="row">
<div class="col-2 listings--filter">
<select v-model="filter" class="form-control listings--filter_select">
<option value="" disabled hidden>Filter</option>
<option value="price-lowest">Lowest Price First</option>
<option value="price-highest">Highest Price First</option>
<option value="listing-new">Newest Listing First</option>
<option value="listing-old">Oldest Listing First</option>
</select>
</div>
<div class="col-2 listings--filtersstc">
<toggle-button v-model="sstcBtn"
:value="true"
:labels="{checked: 'Show SSTC', unchecked: 'Hide SSTC'}"
:width="120"
:height="40"/>
</div>
</div>
<div class="row margin-bottom">
<div class="col listings--filter">
<small v-show="showRemoveFilter">Current filter: {{ selectedFilter }}</small>
</div>
<div class="col listings--filter">
<small v-show="showRemoveFilter" v-on:click="removeSortProperties" class="float-right">Remove filter</small>
</div>
</div>
<div class="row">
<property-listings v-for="(property, index) in properties" v-bind:property="property" v-bind:key="index"></property-listings>
</div>
</div>
<div v-else>
<div class="row">
<div class="col text-center">
<p class="dark-text">No properties match your search criteria. Please try again.</p>
</div>
</div>
</div>
</div>
</template>
<script>
import PropertyListings from './PropertyListings.vue'
import * as VueGoogleMaps from 'vue2-google-maps'
import ToggleButton from 'vue-js-toggle-button'
Vue.use(ToggleButton)
Vue.use(VueGoogleMaps, {
load: {
key: '-------------------',
libraries: 'places', // This is required if you use the Autocomplete plugin
// OR: libraries: 'places,drawing'
// OR: libraries: 'places,drawing,visualization'
// (as you require)
}
})
export default {
data () {
return {
showProperties: false,
properties: [],
filter: '',
sstcBtn: true,
selectedFilter: '',
showRemoveFilter: false,
center: {lat: 00000, lng: -000000},
propertyInfoName: '',
propertyInfoPrice: '',
propertyInfoLink: '',
propertyInfoType: '',
infoWindowPos: {
lat: 0,
lng: 0
},
infoWinOpen: false,
currentMidx: null
}
},
delimiters: ['<%', '%>'],
components: {
PropertyListings
},
watch: {
filter: function(newFilter, oldFilter) {
this.sortProperties(newFilter);
},
sstcBtn: function(newSstcBtn, oldSstcBtn) {
this.removeSstcProperties(newSstcBtn);
}
},
methods: {
sortProperties: _.debounce(
function(newFilter) {
if(newFilter === 'price-highest') {
this.properties = _.orderBy(this.properties, 'price', 'desc')
this.selectedFilter = 'Highest Price First'
} else if(newFilter === 'price-lowest') {
this.properties = _.orderBy(this.properties, 'price', 'asc')
this.selectedFilter = 'Lowest Price First'
} else if(newFilter === 'listing-new') {
this.properties = _.orderBy(this.properties, 'id', 'desc')
this.selectedFilter = 'Newest Listing First'
} else if(newFilter === 'listing-old') {
this.properties = _.orderBy(this.properties, 'id', 'asc')
this.selectedFilter = 'Oldest Listing First'
}
this.showRemoveFilter = true
},
500
),
removeSstcProperties: _.debounce(
function(newSstcBtn) {
if(newSstcBtn == true){
console.log('do not filter')
//this.properties = _.filterBy(this.properties, 'status_id', '1')
return this.properties.filter(function(property){
return property.status_id == "1"
}.bind(this))
} else if(newSstcBtn == false){
console.log('do filter')
}
},
500
),
removeSortProperties: function() {
this.properties = _.orderBy(this.properties, 'id', 'desc')
this.showRemoveFilter = false
},
toggleInfoWindow: function(property, idx) {
this.infoWindowPos = {lat: Number(property.latitude), lng: Number(property.longitude)}
this.propertyInfoName = property.display_address
this.propertyInfoPrice = property.price
if(property.let_type_id === '3') {
this.propertyInfoLink = '/properties/for-students/' + property.main_searchable_areas + '/' + property.slug + '/' + property.property_ref
} else if(jQuery.inArray(property.let_type_id, ['1','2']) != '-1'){
this.propertyInfoLink = '/properties/for-rent/' + property.main_searchable_areas + '/' + property.slug + '/' + property.property_ref
} else {
this.propertyInfoLink = '/properties/for-sale/' + property.main_searchable_areas + '/' + property.slug + '/' + property.property_ref
}
}
},
created() {
var self = this;
axios.get('/properties/json')
.then(function (response) {
self.properties = response.data
self.showProperties = true
})
.catch(function (error) {
console.log(error);
});
}
}
</script>
Everything else is working fine but the bit i've been working on is the removeSstcProperties method, I've got the method triggering fine, however I'm struggling to actually filter the results for properties that have the status_id = 1. I've tried 2 ways (one commented out). Can anyone point me in the right direction?

Making a value from a fetch call available immediately

I have a Go program written that has a form which checks for the existence of a file by calling a fetch on a route inside the Go code. If the file exists or not, a boolean is return inside of a JSON as fileExists. I'm having trouble with the fetch call's JSON updating this.found boolean immediately.
What happens is that when I press enter or click the buttons, the form is submitted via call to onSubmit where the checkFile() is called which does the fetch. Somehow, I have to press enter twice to see the value returned by the fetch as it is not updating the this.found immediately. I am probably thinking about this the wrong way, but I figure it wouldn't to ask. Here's the code, if anyone can help so that clicking or submitting will be based on the correct value returned by the checkFile call:
<div class="jumbotron">
<div class="container">
<div class="alert alert-dark" role="alert">
</div>
<h1 class="display-3">Title</h1>
<div id="app">
<form ref="myForm" method="POST" v-on:submit.prevent="onSubmit" action="/push" class="needs-validation" id="myForm" novalidate="true">
<div class="form-group">
Canned List:
<input v-model="cannedlist" ref="cannedlist" type="text" class="form-control" name="fileListFile" id="filelist"
aria-describedby="fileListFileHelp"
autocomplete="off" :disabled="!!individuallist" v-on:submit.prevent="onSubmit" />
</div>
<div class="form-group">
Path List:
<textarea v-model="individuallist" ref="cannedlist" :disabled="!!cannedlist" class="form-control" rows=10 name="fileListRaw" id="files" autocomplete="off"></textarea>
</div>
<div class="form-group">
<button v-on:submit.prevent="onSubmit" type="submit" name="button" value="submit" id="submitButton" class="btn btn-primary" :disabled="isDisabled">Submit</button>
<button v-on:submit.prevent="onSubmit" type="submit" name="button" value="checkOnly" id="checkOnlyButton" class="btn btn-primary" :disabled="isDisabled">Submit 2</button>
</div>
</form>
</div>
</div>
</div>
<script src="/static/js/vue.min.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
// cannedlist: "filelist.txt",
individuallist: "",
found: false,
},
computed: {
isDisabled: function() {
//found = !found;
return (this.cannedlist.length <= 0 && this.individuallist.length <= 0);
},
},
methods: {
isDisabledNew: function() {
alert((this.cannedlist.length <= 0 && this.individuallist.length <= 0));
// return (this.cannedlist.length <= 0 && this.individuallist.length <= 0);
return false;
},
isFieldDisabled: function(e) {
//console.log(app.$refs.individuallist.disabled);
return false;
},
onSubmit: function() {
if (this.cannedlist.length > 0) {
this.checkFile();
if (this.found == true) {
this.$refs.myForm.submit();
return;
}
} else if (this.individuallist.length > 0) {
this.$refs.myForm.submit();
return;
}
},
checkFile: function() {
var url = 'http://localhost:9000/CheckIfFileExists?name=' + this.cannedlist;
return fetch(url)
.then(response => {
if (response.ok) {
var v = response.json().then( response => { this.found = response.fileExists; } );
return this.found;
}
return response.json().then(error => ({ error }));
});
return this.found;
},
}
});
</script>
Your onSubmit function calls checkFile and expects found to be updated:
onSubmit: function() {
if (this.cannedlist.length > 0) {
this.checkFile();
if (this.found == true) {
this.$refs.myForm.submit();
return;
}
} else if (this.individuallist.length > 0) {
this.$refs.myForm.submit();
return;
}
},
But checkFile returns a Promise. The Promise resolves by updating found. So you need to put your found checking inside a then block:
onSubmit: function() {
if (this.cannedlist.length > 0) {
this.checkFile()
.then(() => {
if (this.found == true) {
this.$refs.myForm.submit();
}
});
return;
} else if (this.individuallist.length > 0) {
this.$refs.myForm.submit();
return;
}
},
Here're the changes I made:
methods: {
onSubmit: function(event) {
if (this.cannedlist.length > 0) {
this.checkFile()
// This promise capture is the key I was missing
.then( (data) => {
this.found = data.fileExists;
if (this.found == true) {
this.$refs.myForm.submit();
} else {
alert("File not found: " + this.cannedlist);
}
});
} else if (this.individuallist.length > 0) {
this.$refs.myForm.submit();
}
},
checkFile: function() {
var url = 'http://localhost:9000/CheckIfFileExists?name=' + this.cannedlist;
return fetch(url).then((response) => response.json());
}