I have an form in my web app that is displayed via data-toggle. I'm altering the behavior of the submit event because I want to submit data without reloading the page. I can submit the form successfully and the toggle folds as expected, but afterwards, I can no longer collapse the form to use it again. What am I doing wrong?
Here is how I control the submit event
$('form').submit(function(event){
//event.preventDefault();
console.log('submit ' + $("input[name=personName]").val());
//console.log('submit ' + $('#personName').val());
//socket.emit('add', $('#personName').val());
socket.emit('add', $("input[name=personName]").val());
//$('#personName').val('');
$("input[name=personName]").val('');
//$("#add-person-panel").toggle();
$("div[id=add-person-panel]").toggle();
$("div[id=add-person-panel]").addBack('aria-expanded','false');
//$("input[name=personName]").toggle();
//$('#add-person-panel').attr('aria-expanded','');
//socket.emit('add', $('input[name=personName]'));
//$('input[name=personName]').val("");
return false; //do not let the page refresh on submit
});
form
<div class="panel panel-default">
<div class="panel-heading">
<%
if (hasKioskPermissions === true || hasDigmaKioskPermissions === true){ %>
<a data-toggle="collapse" href="#add-person-panel" class="collapsed">
"Add Person To Local Queue"
::after
</a>
<% } else { %>
<a data-toggle="collapse disabled" href="#add-person-panel" class="collapsed">
"Add Person To Local Queue"
::after
</a>
<%}%>
</div>
<div id="add-person-panel" class="panel-body collapse">
<form data-parsley-validate="" class="form-horizontal">
<div class="form-group">
<div class="col-sm-5 col-xs-8">
<input name="personName" type="text" maxlength="40" placeholder="Enter name" required class="form-control" autocomplete="off">
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="submit" data-loading-text="Adding..." class="btn btn-lg btn-block btn-primary">Add</button>
</div>
</div>
</form>
</div>
</div>
Use $('div#add-person-panel') instead of $("div[id=add-person-panel]").
What is the template type? It's not plain html. There are <% %> in the code.
Are you trying to use server-side sockets in browser (socket.emit(...))?
UPD
Did you initialize your socket before using?
There is an example from docs:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' }); });
</script>
The problem was that I was not using the same plugin (from bootstrap) to close as I did with open. This is necessary since the plugin tracks it's own state.
before:
$('div#add-person-panel').toggle();
after:
$('div#add-person-panel').collapse('hide');
minimal solution below:
$('form').submit(function(event){
event.preventDefault();
console.log('submit ' + $("input[name=personName]").val());
$("input[name=personName]").val('');
$('div#add-person-panel').collapse('hide');
$('div#add-person-panel').addBack('aria-expanded','false');
return false; //do not let the page refresh on submit
});
Related
I have a code, who helps me switch between forms, however, when I submit the form, the page will reset and display first(default) tab again. Could anyone help me understand how I can make it so the tab I submit the form from stays there if the submision fails or even if the submision was successfull?
Forms are switching using a little JS code and are submited from a PHP POST method form.
Please find the code below:
Javascript responsible for switching between tabs:
function onTabClick(event) {
let activeTabs = document.querySelectorAll('.active');
// deactivate existing active tab
for (let i = 0; i < activeTabs.length; i++) {
activeTabs[i].className = activeTabs[i].className.replace('active', '');
}
// activate new tab
event.target.parentElement.className += 'active';
document.getElementById(event.target.href.split('#')[1]).className += 'active';
}
const elements = document.getElementsByClassName('nav-tab-element');
for (let i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', onTabClick, false);
}
CSS:
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
And here is the HTML forms:
<body>
<header>
<h1 class="main-header">
Add a New Product
</h1>
</header>
<main>
<ul id="nav-tab" class="nav">
<li class="active">
<a class="nav-tab-element" href="#books">Books</a>
</li>
<li>
<a class="nav-tab-element" href="#dvds">DVD's</a>
</li>
<li>
<a class="nav-tab-element" href="#furniture">Furniture</a>
</li>
</ul>
<form method="POST">
<div class="tab-content active" id="books">
<div class="book-tab">
<input type="text" name="sku" placeholder="test form for books" autocomplete="off">
</div>
<div class="btn">
<input type="submit" value="Submit">
</div>
</div>
</form>
<form method="POST">
<div class="tab-content " id="dvds">
<div class="dvd-tab">
<input type="text" name="sku" placeholder="test form for DVD" autocomplete="off">
</div>
<div class="btn">
<input type="submit" value="Submit">
</div>
</div>
</form>
<form method="POST">
<div class="tab-content " id="furniture">
<div class="furniture-tab">
<input type="text" name="sku" placeholder="test form for furniture" autocomplete="off">
</div>
<div class="btn">
<input type="submit" value="Submit">
</div>
</div>
</form>
</main>
<script src="main.js"></script>
</body>
Clicking submit submits the form data to the page given in the action attribute in form. If you don't put this attribute in (as you have not done) the default is to submit to the current page.
To fix the issue you have, I would suggest that rather than using vanilla form submit, you do you submission via ajax. Making an ajax call is quite simple in jQuery, so I recommend you look into that.
There is an event that is triggered when you send a form. You can prevent your page to reload doing the following:
event.preventDefault()
you can find more about here: https://www.w3schools.com/jsref/event_preventdefault.asp
or here https://www.w3schools.com/jquery/event_preventdefault.asp
All you have to do is add event.preventDefault() to the first line of your onTabClick(event) function. After you preventDefault you can run whatever logic you want right there.
The way vanilla html/js interact is: On form submission, the page attempts to send the info to a server and then it refreshes to update with new information. The rise of SPAs has shifted the desired behavior, and you need to override the browser default behavior to stop the refresh.
Adding Ajax/Axios would work as most of those API libraries have built in functions to override the default, but it is not necessary.
I have a form inside a modal, I want to prevent the modal from closing and refreshing the page after submiting the form if there's errors on some fields and show error messages inside the modal, if everything is okay the modal shoud submit the form and refresh the page.
This is my code :
<div class="modal fade" id="addTeam">
<div class="modal-dialog rap-modal-thumb">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">X</span></button>
<h4 class="modal-title" id="myModalLabel">Add team</h4>
</div>
<div class="modal-body"><br>
<div class="page-wrap">
<form action= "<?php echo $action; ?>" enctype="multipart/form-data" method="post">
<div class="container">
<div class="row">
<div class="input-group input-group-icon">
<div class="col-third input-group-icon">
<input type="text" id="name" name="name" placeholder="Nom*" required="required">
<div class="input-icon"><i class="fa fa-users"></i></div>
</div>
<div class="col-third input-group-icon">
<input type="text" id="abreviation" name="abreviation" placeholder="Abréviation*" required="required">
<div class="input-icon"><i class="fa fa-flag-o"></i></div>
</div>
<br>
* Required fields
<br><br>
<?php
if (isset($error))
echo '<div style="color:#fff;" class="alert bg-danger" role="alert"><em class="fa fa-lg fa-warning"> </em>',$erreur,'</div>';
?>
<button type="submit" id="addTeam" name="addTeam" class="btn btn-primary">Ajouter</button>
</div>
</form>
</div>
<br>
</div>
</div>
</div>
In php if for example the name of the team is less than 6 characters then show the error message inside the modal without closing it. In my case here the message appear after the page is refreshed and the show button of the modal is clicked again.
if (isset($_POST['addTeam'])) {
$name= $_POST['name'];
if (strlen($name)<3){
$error = 'Name must be atleast 6 characters';
}
else{
$action = "uploadTeam.php";
}
}
Anyway to do that ?
If your form is submited by default by the browser, it'll auto-refresh the page (to create a new HTTP POST request to the server)
You have to use AJAX to call the server on background and avoid reloading the content:
// Create an event listener to catch "when the form is submited"
$('.modal-body form').submit(function(event) {
// to stop the form from submitting (and the page reloading, so the modal will not close)
event.preventDefault();
// Call server manually and send form data (see Mikey's comment)
$.post('my.url.com/file.php', $(this).serialize(), function(err, result) {
if (err) {
// Display error on form
} else {
// Success... Redirect ?
window.location = 'my.new.url/path.html'
}
})
});
You will need to override some client behavior for this. In fact, it will be easier for you to do your validation all on the client side (if possible). Override the form's default behavior, validate, and then return true or false based on the results of your validation function:
<script>
$('form').on('submit', function(e) {
if (validate()) { //your validation function here
return true;
}
return false;
});
function validate() {
if (!$('input[name=name]').val() || $('input[name=name]').val().length < 3) {
return false;
}
return true;
}
</script>
I'm a newbie in coding and I need your expertise help.
This is my index.php codes
<div class="container">
<div class="row text-center"><h1>Stamford Network</h1></div>
<div class="row">
<div class="col-md-9">
<input type="textarea" name="text" placeholder="What's on your mind?" class="form-control" id="info" />
<input type="button" name="post" value="Post" class="btn btn-primary" id="post" />
</div>
<div class="col-md-3">
<h3>Hello,
<?php echo $_SESSION['username']; ?>
</h3>
<a class="btn btn-primary" href="login.php" role="button" >Logout</a>
</div>
</div>
<div class="row">
<div class="col-md-9">
<h4 id="display"></h4>
</div>
<div class="col-md-3"></div>
</div>
</div>
My .js code which link to the above index.php
window.onload = function() {
var button = document.getElementById("post");
button.addEventListener("click",
function() {
document.getElementById("display");
});
}
Can anyone tell me how create a post and display it without refreshing the page. Simply just click on the Post button then the information should appear below the posting form. While the words in the textarea should be gone when the button is clicked.
Please only show me the javascript way
var button = document.getElementById('post'),
info = document.getElementById('info'),
display = document.getElementById('display');
button.addEventListener('click', function(){
display.innerText = info.value;
info.value = '';
});
If you want the value to be uploaded to server for processing, you will need to add ajax XMLHttpRequest in the event listener.
Learn more about ajax here.
You should do it asynchronously.
First, use the tag to surround the data that you want to post:
<form>
...
</form>
Tutorial about forms:
https://www.w3schools.com/html/html_forms.asp
To post form asynchronously, you can use jquery or js. The simple and quick way is jquery. Here is a link to the documentation:
https://api.jquery.com/jquery.post/
There is an example at the end of the page of the jquery post doc's page, that explains how to use it, and basically do the thing that you wanted.
try this.
<script type="text/javascript">
window.onload = function() {
var button = document.getElementById("post");
button.addEventListener("click",
function() {
//document.getElementById("display");
document.getElementById('display').innerHTML = document.getElementById('info').value;
document.getElementById("info").style.display = "none";
});
}
</script>
I want to change the label of same button in angularjs according to requirement, same button can be for update and submit.
See the following demo,
Above demo is about the replicate the template. If some template has already data then label of submit button should be Update, other-wise for empty template label should be Submit.
I can't use following logic because it will change all button with same label, but I want to show label Submit only for empty and no-empty to show label Update. How I will do that?
<a class="btn btn-success" ng-click="updateOrder($index)">{{btnText}}</a>
And add some logic to your controller, that will specify text for button:
if (newItem){
$scope.btnText = 'Submit';
}else{
$scope.btnText = 'Update';
}
HTML
<div class="col-md-12" style="bottom:10px" >
<div class="form-group" ng-repeat="field in fields">
<div class="col-md-12">
<div class="col-md-4">
<label class="col-md-12 control-label">Field1</label>
<div class="col-md-12">
<input data-ng-model='field.field1' class="chosen-select input-md form-control sme-input-box"/>
</div>
</div>
<div class="col-md-4">
<label class="col-md-12 control-label">Field2</label>
<div class="col-md-12">
<input ng-model='field.field2' class="chosen-select input-md form-control sme-input-box"/>
</div>
</div>
</div>
<div class="col-md-12">
<div class="col-md-3">
<a class="btn btn-success" ng-click="removeTemplate($index)">Remove</a>
</div>
<div class="col-md-3">
<a class="btn btn-success" ng-click="updateOrder($index)">Submit</a>
</div>
</div>
</div>
<div class="col-md-3" style="top:5px">
<a class="btn btn-success" ng-click="cloneTemplate()">Add</a>
</div>
</div>
Angularjs
$scope.fields=[
{
"field1": "",
"field2": "",
}
]
// update and get invoice details
$scope.cloneTemplate=function(){
var clone_template={ "field1": "", "field2": ""};
$scope.fields.push(clone_template);
}
$scope.removeTemplate= function(templateIndex){
$scope.fields.splice(templateIndex,1);
}
$scope.updateOrder=function(i){
var updateOrder={
"field1":$scope.fields[i].field1,
"field2":$scope.fields[i].field2,
}
alert(updateOrder.field1);
$http.post(config.server, updateOrder)
.success(function(response, status){
console.log(response);
})
.error(function(response, status){
console.log(response);
})
}
I understand that while while adding data you wanted to show Submit button label & show Update button label while updating record.
So as normal practice you are getting this value from the DB, so I'd suggest you to add id column in this object which will be there with fields. Now object will look like {id: 1, field1: '1', field2: 2} so if the element has id that means it has persisted in the database. And obviously if you don't have id in fields record means it has been added from UI.
So the whole logic will look at the id property of your object, if you have id in the record then it will show Update as button label otherwise it would be Submit
<div class="col-md-3">
<a class="btn btn-success" ng-click="updateOrder(field)"
ng-bind="field.id? 'Update': 'Submit'">
Submit
</a>
</div>
So for make your logic working good, you need to get the list again from the database to make your UI consistent.
Working Plunkr
Change your markup for button to show some scope property:
<a class="btn btn-success" ng-click="updateOrder($index)">{{btnText}}</a>
And add some logic to your controller, that will specify text for button:
if (newItem){
$scope.btnText = 'Submit';
}else{
$scope.btnText = 'Update';
}
I'm trying to use CasperJS to upload images to a web-form.
My form looks something like this:
<form action="" method="POST" enctype="multipart/form-data" class="form-vertical">
...
<legend>Campaign Banner</legend>
<div class="control-group image-field ">
<label class="control-label">Now Large</label>
<div class="controls">
<div class="file-field"><input id="id_now_large_image" name="now_large_image" type="file"></div>
<div class="image-preview"></div>
<div class="clear"></div>
<span class="help-inline"></span>
</div>
</div>
<div class="control-group image-field ">
<label class="control-label">Now Medium</label>
<div class="controls">
<div class="file-field"><input id="id_now_medium_image" name="now_medium_image" type="file"></div>
<div class="image-preview"></div>
<div class="clear"></div>
<span class="help-inline"></span>
</div>
</div>
<div class="control-group image-field ">
<label class="control-label">Now Small</label>
<div class="controls">
<div class="file-field"><input id="id_thumbnail_image" name="thumbnail_image" type="file"></div>
<div class="image-preview now-small"></div>
<div class="clear"></div>
<span class="help-inline"></span>
</div>
</div>
The submit button looks like this:
<div class="form-actions">
<button type="submit" class="btn btn-small ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" role="button" aria-disabled="false"><span class="ui-button-text">Save changes</span></button>
</div>
I've put a Gist of the full HTML here: https://gist.github.com/victorhooi/8277035
First, I've tried using CasperJS's fill method:
this.fill('form.form-vertical', {
'now_large_image': '/Users/victor/Dropbox/CMT Test Resources/Test Banners/Default Banners/now_large.jpg',
}, false);
this.click(x('//*[#id="content-wrapper"]//button/span'));
I also did a this.capture(), and I saw that the file field had been filled in:
I'm not using the fill method's inbuilt submit, but I'm clicking on the submit button myself:
this.click(x('//*[#id="content-wrapper"]//button/span'));
I then do another capture, and I can see that the form has been submitted:
However, the image doesn't seem to have been uploaded at all.
I've also tried using PhantomJS's uploadFile() method:
this.page.uploadFile('input[name=now_large_image]', '/Users/victor/Dropbox/CMT Test Resources/Test Banners/Default Banners/now_large.jpg');
and then clicking on the submit button as well.
Same issue - the form field gets filled in - however, the image itself doesn't seem to get submitted.
Any ideas on how I can get the images to upload correctly here?
Since you are filling and submitting successfully, try a Wait command on the click.
casper.then(function() {
//+++ form fill here
//waits 1 sec
this.wait(1000, function() {
this.click(x('//*[#id="content-wrapper"]//button/span'));
});
});
Try this.
casper.thenOpen('about:blank', function(){
this.evaluate(function(){
var action = 'upload.php'
var html = '<form action="'+action+'" method="post" enctype="multipart/form-data">'
html += '<input type="file" name="files[]" multiple="multiple">'
html += '<button type="submit">Submit</button>'
html += '</form>'
document.write(html)
})
this.fill('form',{
'files[]': 'file.txt'
}, true)
this.waitFor(function(){
var uri = casper.evaluate(function(){
return document.documentURI
})
if ( 'about:blank' === uri ){
return false
}
return true
})
})