Vue.js triggers button unexpectedly - javascript

I have prepared a fiddle: https://jsfiddle.net/frvuw35k/
<div id="app">
<h2>Vue Event Test</h2>
<form #submit.prevent>
<div class="form-group row">
<div class="col-sm-12 input-group">
<input v-model="search" class="form-control" placeholder="Search users by Display Name"
#keyup.enter="doSearch">
<div class="input-group-append">
<button class="btn btn-primary" :disabled="!search" type="button"
#click.prevent="doSearch">
Search
</button>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-12">
<button v-if="showButton" class="btn btn-info"
#click.prevent="doSthElse">Do something else</button>
</div>
</div>
</form>
</div>
new Vue({
el: "#app",
data: {
search: null,
showButton: false
},
methods: {
doSearch: function(){
console.log('do search:', this.search)
this.showButton = true
},
doSthElse: function(){
console.log('do something else')
}
}
})
This simulates something I have faced in my Vue application.
There is a second button, that is shown when a condition is meet. This condition is a result of a search, that is triggered by hitting enter key on the input.
On a second enter after the condition was meet, also if one has clicked somewhere else and put the focus back on the input, the second button is triggered...
I don't see the reason and haven't found out how to avoid it so fare.

Explanation
This is caused by the browser behavior in a form.
The normal behavior is that when a user press down the Enter key on an input, it will submit the form.
Also, to submit a form, the browser will look for a button in the form, which is your "Do something else" button in your case.
So when the user presses Enter, it will trigger a button press on your last button, calling the doSthElse method.
How to fix
To fix this, simply add the a #keydown.enter.prevent listener on the form to prevent the default behavior to trigger.
I updated your fiddle with the fix : https://jsfiddle.net/vy57d63f/

Use this: You need to user #keydown and prevent modifier
<input v-model="search" class="form-control" placeholder="Search users by Display Name"
#keydown.enter.prevent="doSearch"/>

Related

Alpine.js - Show an input field and add focus to it at the same time

I have a button, and when a user clicks it, an input element should be shown and it should have focus.
I tried this:
<div x-data="{ show: false }">
<input x-show="show" type="text" id="input" x-ref="input" />
<button #click="show = !show; $refs.input.focus();">Button</button>
</div>
But it does not work.
To put focus on the input immediately after showing it, you'll need to use Alpine's $nextTick function. Try this slightly altered version of your code:
<div x-data="{ show: false }">
<input x-show="show" type="text" id="input" x-ref="input" />
<button #click="show = !show; $nextTick(() => { $refs.input.focus(); });">Button</button>
</div>
Here's some more info about $nextTick: https://github.com/alpinejs/alpine#nexttick

Storing form input as local variable and using in another webpage

i'm trying to store a user input from a form and then use that variable on a different page.
It seems like it should be very simple but im getting absolutely nothing back and i cant work out why.
Code on page 1:
<div class="container-fluid d-flex justify-content-center" id="mySearchBar">
<div class="row d-flex justify-content-center ">
<h3 class="heading text-center pt-5">Search the Title Below and Find The Site It's Hosted On!</h3>
<div class="input-group">
<input type="text" class="form-control" placeholder="Search this blog" id="searchbar" name="searchbar ">
<script> localStorage.setItem('loan', document.getElementById("searchbar").value );</script>
<div class="input-group-append">
<button class="btn btn-secondary" id='searchButton' type="submit">
<i class="fa fa-search"></i>
</button>
</div>
</div>
Then on page two i have the following:
<script>
var loan = localStorage.getItem('searchbar');
console.log(loan);
</script>
Any help would be appreciated!
In order to fetch a value entered by the user you must do so after they enter the value. You need to use an event listener to fetch and store the value. For your use-case it would be best to wrap your inputs in a <form> and listen for the form submit. That way you capture the submit button's click and/or the input's enter key press.
You are using bootstrap-4 so I will assume you have jQuery imported as well.
<form class="container-fluid d-flex justify-content-center" id="mySearchBar">
<div class="row d-flex justify-content-center ">
<h3 class="heading text-center pt-5">Search the Title Below and Find The Site It's Hosted On!</h3>
<div class="input-group">
<input type="text" class="form-control" placeholder="Search this blog" id="searchbar" name="searchbar">
<div class="input-group-append">
<button class="btn btn-secondary" id='searchButton' type="submit">
<i class="fa fa-search"></i>
</button>
</div>
</div>
</div>
</form>
<script>
// use a constant key string on both pages
const searchbar_local_storage_key = 'my_unique_key_for_searchbar_value'
// on page where you need to fetch stored value
$(document).ready(function() {
let stored_value = localStorage.getItem(searchbar_local_storage_key)
console.log('searchbar localStorage value at document.ready:')
console.log(stored_value)
})
// on page where you need store/overwrite the value
$(document).ready(function() {
let $searchbar = $('#searchbar')
console.log('searchbar input value at document.ready:')
console.log($searchbar.val())
$('#mySearchBar').on('submit', function(event) {
console.log('searchbar form submitted')
// stop form submission if needed
event.preventDefault()
// get the current value
let term = $searchbar.val()
console.log('searchbar input value at form.submit:')
console.log($searchbar.val())
// store values
localStorage.setItem(searchbar_local_storage_key, $searchbar.val());
console.log('new searchbar value in localStorage:')
console.log(localStorage.getItem(searchbar_local_storage_key))
})
})
</script>
See it in action here https://jsfiddle.net/chan_omega/qt510oms/
Enter a value, submit, view the output in the console and then reload the page (to simulate being on a different page). You will see the same value loaded from localStorage.

Validate a form element without/before submitting the form with JavaScript

I have an HTML form that has its elements displayed in various Bootstrap modals. The first modal has a text box input that and a "Next" button to open the next modal. When the "next" button is pressed. I want to check if the text box is empty, and trigger a validation message. The form does not get submitted until the very end. Everything I've tried has not worked so far.
Javascript/jQuery code
$("#add_assistant_next").click(function () {
var textInput = document.getElementById('add_assistant_user');
var text = textInput.value;
if (text === "") {
textInput.setCustomValidity('Please fill out this field.');
textInput.checkValidity();
var form = $('#form_add_assistant');
form.find(':submit').click();
} else {
textInput.setCustomValidity('');
}
});
HTML
<form name="add_assistant" method="post" id="form_add_assistant">
<div class="modal-body">
<div class="step">
<span class="fas fa-arrow-right choose-arrow mr-1"></span>1. Choose a user to add
</div>
<div class="pl-3 pt-1">
<div>
<input type="text" id="add_assistant_user" name="add_assistant[user]" required="required" placeholder="UCInetID or UCI email address" class="mr-0 form-control" />
<button type="button" id="add_assistant_next" name="add_assistant[next]" data-toggle="modal" data-target="#add-user-modal" class="btn btn-outline-secondary btn">Look up user</button>
</div>
<input type="hidden" name="user_search_route" value="/courseSpace/20900/listAssistantEnrollment">
</div>
</div>
... form continues in other modals
Your JS code is probably fighting with Bootstrap for control of that button. To get around that, and have your validation, you could try modifying your code to have a middle step / temporary button to help with validation first before actually submitting. So something like this:
Javascript/jQuery code
$("#my_temp_button").click(function () {
var textInput = document.getElementById('add_assistant_user');
var text = textInput.value;
// Might also want to handle null and undefined cases?
if (text === "" || text === undefined || text === null) {
// I'm assuming if it's empty, it doesn't pass validation,
// so we just display this warning and wait for the user to fix it:
textInput.setCustomValidity('Please fill out this field.');
} else {
// it's not empty so validate:
if (textInput.checkValidity()) {
// it passed validation, so ok to submit.
// call the real button:
$('#add_assistant_next').click();
// do you need this?
var form = $('#form_add_assistant');
form.find(':submit').click();
} else {
// it failed validation, so display another error?
textInput.setCustomValidity('Try again.');
}
}
});
HTML:
<form name="add_assistant" method="post" id="form_add_assistant">
<div class="modal-body">
<div class="step">
<span class="fas fa-arrow-right choose-arrow mr-1"></span>1. Choose a user to add
</div>
<div class="pl-3 pt-1">
<div>
<input type="text" id="add_assistant_user" name="add_assistant[user]" required="required" placeholder="UCInetID or UCI email address" class="mr-0 form-control" />
<!-- Feel free to change the id name. This is the button the user sees. It's only purpose is to give your function above full control to it and prevent Bootstrap from touching it and jumping to the next modal without having the user fix the validation failure first: -->
<button type="button" id="my_temp_button" class="btn btn-outline-secondary btn">Look up user</button>
<!-- Hide the real button from the user: -->
<div style="display:none">
<button type="button" id="add_assistant_next" name="add_assistant[next]" data-toggle="modal" data-target="#add-user-modal" class="btn btn-outline-secondary btn">Look up user</button>
</div>
</div>
<input type="hidden" name="user_search_route" value="/courseSpace/20900/listAssistantEnrollment">
</div>
</div>
...
Have you tried adding a trap for the submit event itself?
$('#form_add_assistant').submit(function(evt){
//do your validation here
if (validation fails){
return false; // OR, alternatively, `evt.preventDefault()`
}
//form submission will continue if not returned false
});
References:
https://api.jquery.com/submit/
How to conduct manual form validation via jQuery .submit()

'Send' button remains active while conditions aren't satisfied

I'm learning Ember.js and now I'm stuck with a little contact form. I have two fields, one for email, another for the message, and I've set some validations for them. Unless the validations are satisfied, the 'Send' button must be disabled. Also, when everything is OK and user sends a message, the form must be substitued with a flash notice that message was sent. So, here's the code:
app/controllers/contact.js:
import Ember from 'ember';
export default Ember.Route.extend({
emailAddress: '',
message: '',
isValidEmail: Ember.computed.match('emailAddress', /^.+#.+\..+$/),
isValidMessage: Ember.computed.gte('message.length', 5),
isValid: Ember.computed.and('isValidEmail', 'isValidMessage'),
isInvalid: Ember.computed.not('isValid'),
actions: {
sendMessage() {
alert(`Sending message from: ${this.get('emailAddress')}`);
this.set('responseMessage', `Thank you! We've received message from: ${this.get('emailAddress')} . You will be responsed ASAP!`);
this.set('emailAddress', '');
}
}
});
and the template contact.hbs:
<h1>Contact us</h1>
<div class="well well-sm">
<p> If you have any questions, feel free to contact us!</p>
</div>
<div class="row">
<div class="col-md-6">
{{#if responseMessage}}
<br/>
<div class="alert alert-success">{{responseMessage}}</div>
{{else}}
<div class="form-group">
{{input type="email" value=emailAddress class="form-control" placeholder="Please type your e-mail address." autofocus="autofocus"}}
{{#if emailAddress.isValidEmail}}<span class="glyphicon glyphicon-ok form-control-feedback"></span>{{/if}}
</div>
<div class="form-group">
{{textarea class="form-control" placeholder="Your message. (At least 5 characters.)" rows="7" value=message}}
{{#if message.isValidMessage}}<span class="glyphicon glyphicon-ok form-control-feedback"></span>{{/if}}
</div>
{{/if}}
<button class="btn btn-primary btn-lg btn-block" disabled={{isInvalid}} {{action 'sendMessage'}}>Contact us!</button>
</div>
but, still:
The button remains active while the form is empty.
There's no glyphicons appearing while completing the form.
No notice appears when the message is sent.
What am I doing wrong?
You need to use the name of your form, as well as ng-disabled: DEMO
<form name="myForm">
<input name="myText" type="text" ng-model="mytext" required />
<button ng-disabled="myForm.$invalid">Save</button>
</form>
Please, feel free to vote me down, as I've shown a notorious lack of attention - the code which was pretended to be in app/controllers/contact.js was in app/routers/contact.js... So, naturally, when I removed it to the right place, everything worked. Special thanks to #Parag who made me enlighten. I am terribly sorry for disturbing and stealing time for this BS :(

Skip Validation on cancel button in AngularJS

I try to achieve the following functionality. Have editable form inputs in an angular application. For example a user can see his first name being fetched by the server and then clicking an edit button the form text input appears, edit button disappears and in its place the buttons save and cancel appear. I use the angular-bootstrap-show-errors component to show errors.
However when a validation rule is not fulfilled during editing and I click on cancel button the form tries to show the error before going back to the starting state. For example, I press edit and delete all the first name characters, then press cancel, so before disappearing it tries to validate. Below is my view.
<!--First name edits-->
<div class="row">
<form name="firstNameEditForm" role="form" novalidate>
<div class="col-xs-3">
<p class="text-right">First Name:</p>
</div>
<div class="col-xs-6" ng-if="model.beforeFirstNameEdit">
<p class="text-success">
{{accountData.firstname || "Loading..."}}
</p>
</div>
<div class="col-xs-6" ng-if="!model.beforeFirstNameEdit">
<div class="form-group" show-errors>
<input name="firstName" ng-model="accountData.firstname" class="form-control" placeholder="First Name" type="text" required minlength=2 auto-focus />
<small class="help-block" ng-if="firstNameEditForm.firstName.$error.required">At least 2 characters required</small>
<small class="help-block" ng-if="firstNameEditForm.firstName.$error.minlength">At least 2 characters required</small>
</div>
</div>
<div class="col-xs-3" ng-if="model.beforeFirstNameEdit">
<button type="button" class="btn btn-warning btn-xs" ng-click="editFirstName()">Edit</button>
</div>
<div class="col-xs-3" ng-if="!model.beforeFirstNameEdit">
<button type="button" class="btn btn-success btn-xs" ng-click="update(accountData.firstname)">Save</button>
<button type="button" class="btn btn-danger btn-xs" ng-click="cancelFirstNameEdit()">Cancel</button>
</div>
</form>
</div><!--First name edits-->
And the controller
$scope.preFirstNameEditModel = {};
$scope.editFirstName = function() {
// Copy preedited data locally
$scope.model.beforeFirstNameEdit = false;
$scope.preFirstNameEditModel = angular.copy($scope.accountData.firstname);
}
$scope.cancelFirstNameEdit = function(){
$scope.model.beforeFirstNameEdit = true;
$scope.accountData.firstname = angular.copy($scope.preFirstNameEditModel);
};
How can I completely avoid validation when I click on cancel button? I read some answers on similar questions suggesting to change the type of button to type = "button" but still doesn't solve my issue.
The validation of the fields is triggered on focus lost, whichis causing the validation message. You can prevent this behaviour by using ng-show="submitted && firstNameEditForm.firstName.$error.required" and ng-show="submitted && firstNameEditForm.firstName.$error.minlength". This causes the message showing up only when the form is submitted.
Furthermore you have to change the type of the update button to submit.

Categories