how to make a multipage form - php

i'm making a website for online exams. i made 1 question per page and i made a custom pagination but now i dont know how to make when i move to the next question i save the answer of the previous question so i can submit all the answers to the databse
this is the view code
<form method="POST" action="{{route("answer.store")}}">
#csrf
<div class="content" v-for="question in questions">
<div v-if="post.qtype === 'choose'">
<div class="font-weight-bold p-4"> #{{question.qname}}</div>
<div v-for="choice in question.choices">
<div class="p-4">
<input type="radio" class="form-check-input" style="display: block" id="radio" :name="'answers[q' + post.id + '][]'" :value="choice">
<label class="form-check-label" for="radio">#{{choice}}</label>
</div>
</div>
</div>
</div>
{{ Form::hidden('exam_id', Crypt::encrypt($exam->id)) }}
<input class='btn btn-primary' v-if="pagination.current_page == pagination.last_page" id='submit-btn' type="submit">
</form>
expected result : all the answers get submited
actual result : only last answer get submited
**Note: im using default laravel pagination but i use json scripts and axios to move throw pagination without refreshing page **

If I understood correctly (and you are also using Vue.js for frontend), I suggest using one of the 2 following approaches:
Use Vuex - Create 1 big json object that will be filled after submitting every step and finally, send it via axios to your API
Have 1 parent component to hold the big object in its data and child component which will represent current step of the multi-step form. Each child step should validate its inputs and then emit the data to parent component. After coming to the last step, just send the request from the parent.
Bonus: I strongly recommend taking a look at https://v2.vuejs.org/v2/guide/components-dynamic-async.html for child components with keep alive tag in case you want to be able to get to previous step as well.
General architecture for the second approach (I didn't test it but you should get the big picture):
// Parent.vue
<template>
<div>
<keep-alive>
<component v-bind:is="actualStep" #stepSubmitted="handleStepSubmitted"></component>
</keep-alive>
</div>
</template>
<script>
export default {
components: {
Step1: () => import("./Step1"),
Step2: () => import("./Step2")
},
data() {
return {
resultToSend: [],
formSteps: ["Step1", "Step2"],
actualStep: "Step1"
};
},
methods: {
handleStepSubmitted(dataFromStep) {
resultToSend.push(dataFromStep);
if (formSteps.indexOf(actualStep) === formSteps.length - 1) {
this.submitData();
} else {
this.actualStep = this.nextStep();
}
},
nextStep() {
return this.formSteps[this.formSteps.indexOf(actualStep) + 1];
},
submitData() {
// send your post request
}
}
};
</script>
// Step1.vue
<template>
<div>
<input v-model="data1" type="text" />
<button #click="submitstep">Next</button>
</div>
</template>
<script>
export default {
data() {
return {
data1: ""
};
},
methods: {
submitStep() {
this.$emit("stepSubmitted", data1);
}
}
};
</script>
// Step2.vue
<template>
<div>
<input v-model="data2" type="text" />
<button #click="submitstep">Next</button>
</div>
</template>
<script>
export default {
data() {
return {
data2: ""
};
},
methods: {
submitStep() {
this.$emit("stepSubmitted", data2);
}
}
};
</script>

You have to create an array with a key-value pair then write a method that pushes the ids and answers into the array on every page change(If a user wants to turn back and change the question then you need to implement CRUD actions for this array). If the user achieved the last page then post your array into your database with axios.

Use JavaScript to submit the form when the next button is clicked:
var nextBtn = document.getElementById("nextBtn");
nextBtn.addEventListener("click", function(e){
e.preventDefault();
let form = document.getElementById("form");
form.submit();
return true;
});

Related

Make button do Controller method without changing page - Laravel

Hello I'm trying to make a button that once clicked I save the information written in the text field plus the current user logged in ID.
Once clicked just refresh the page (or just do nothing) and save that information in the database.
But my button is doing nothing...
My Controller:
public function addSchool(Request $request)
{
DB::table('schools')->insertGetId([
'id_professor' => Auth::id(),
'escola' => $request->input('escola')
]);
return redirect('/teacher');
}
My zone where i have the textfield and button:
<div class="form-group">
<h3 style="color: #000000" for="escola">Nome da Escola</h3>
<input type="text" id="escola" name="escola" class="form-control">
</div>
<div>
<button type="submit" class="btn btn-danger">Registar Escola</button
</div>
I didn't add any web.php (routes file) here because i don't want it to go any page.
These are my Database Columns
You cant save using a method without a route with only PHP.
If you want to do this, take a look on livewire component, who allow you to use Javascript with PHP.
But you need to few understand Javascript.
I propose you to create a route with a name and just point it to the method
Here in web.php
Route::post('/post-form', [YourController::class, 'addSchool'])->name('addschool');
Then after in your view
<form action="{{route('addschool')}}" method="post">
#csrf
<div class="form-group">
<h3 style="color: #000000" for="escola">Nome da Escola</h3>
<input type="text" id="escola" name="escola" class="form-control"/>
</div>
<div>
<button type="submit" class="btn btn-danger">Registar Escola</button>
</div>
</form>
You can do that by using ajax call from the front-end using on click event attach to button. it will dynamically send the request to your specified controller method and you can display the response(data) in the front-end specified place without page loading
for example take a look at the given code
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$(".btn-submit").click(function(e){
e.preventDefault();
var escola = $("input[name=escola]").val();
$.ajax({
type:'POST',
url:'{{route('addschool')}}',
data:{name:escola},
success:function(data){
alert(data.success);
//add your login here for the response
}
});
});

re render click event for added element backbone

I'm currently new in backbone.js. I use CodeIgniter as my PHP Framework.
I'm developing an existing system which uses a backbone.js library. My problem is easy if i will do it in jquery but since this uses a backbone.js, I should do it the same way. This what happens.
Once the page is loaded, i will populate the users inside a select box. then with a button 'ADD'. I will populate also the uses already added inside the ul element to list all the users with an x anchor if you want to delete the user.
I append the user in the list after success ajax in create warehouse user. I use jquery to append. Now the click event to delete is not working because backbone already done rendering the views. How to re render backbone click event for newly added element?
Below is my sample code
HTML CODE
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-list"></i> User Access
</div>
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
<form method="POST" action="<?php echo base_url();?>warehouse/user" id="add-warehouse-user-form">
<div class="col-lg-4">
<div class="form-group">
<label for="users">Available Users </label>
<input type="hidden" name="wh_id" id="wh_id" value="<?php echo $warehouse->wh_id; ?>" />
<select class="form-control" name="users" id="users">
<?php if(!empty($users)){
foreach($users as $row){
//if(in_array('Head',$row->user_access) AND $row->status == 'ACTIVE'){
echo '<option value="'.$row->user_id.'">'.$row->first_name.' '.$row->last_name.'</option>';
//}
}
}?>
</select>
</div>
</div>
<div class="col-lg-1">
<div class="form-group">
<label for="users"> </label>
<input type="submit" class="btn btn-success form-control" value="Add" />
</div>
</div>
</form>
</div>
</div><br />
<div class="row">
<div class="col-lg-12">
<div class="col-lg-5">
<ul class="list-group" id="list_user">
<?php if(!empty($userlist)){
foreach ($userlist as $ul) {
echo '<li class="list-group-item">'.$ul['name'].' <span class="badge badge-delete"><a class="deleteUser" href="#" data-id="'.$ul['module_id'].'" data-uid="'.$ul['id'].'" data-name="'.$ul['name'].'">x</a></span></li>';
}
} ?>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
Warehouse model
var WarehouseUserModel = Backbone.Model.extend({
urlRoot: Config.apiBaseUrl + "/warehouse/user",
defaults: {
wh_id: "",
users: ""
}
});
var WarehouseUserDelModel = Backbone.Model.extend({
urlRoot: Config.apiBaseUrl + "/warehouse/user"
});
Warehouse View
var WarehouseView = Backbone.View.extend();
//-------------- add user to warehouse --------------//
var WarehouseUserAddNewView = Backbone.View.extend({
el: "#add-warehouse-user-form",
loaderEl: "#form-loader",
events:{
"submit": "createWarehouseUser"
},
createWarehouseUser: function (e) {
var self = this;
e.preventDefault();
var formData = Util.getFormData($(self.el));
var warehouseUser = new WarehouseUserModel(formData);
//disable form
$(self.el).find(" :input").prop("disabled", true);
//show loader
$(self.loaderEl).removeClass("hidden");
warehouseUser.save({}, {
success: function (model, res, options) {
if (res.status == "error") {
Util.formError(res.data);
var errorTemplate = _.template($("#toast-error-template").html());
toastr.error(errorTemplate({errors: res.data}));
//re-enable form
$(self.el).find(" :input").prop("disabled", "");
//hide loader
$(self.loaderEl).addClass("hidden");
} else {
//location.href = res.data.redirectUrl;
/** append user to list and remove from select box **/
$('#list_user').append('<li class="list-group-item">'+$("#users option[value='"+$("#users").val()+"']").text()+' <span class="badge badge-delete"><a class="deleteUser" href="#" data-id="'+res.data.id+'" data-uid="'+$("#users").val()+'" data-name="'+$("#users option[value='"+$("#users").val()+"']").text()+'">x</a></span></li>');
$("#users option[value='"+$("#users").val()+"']").remove();
//re-enable form
$(self.el).find(" :input").prop("disabled", "");
//hide loader
$(self.loaderEl).addClass("hidden");
}
}
});
},
initialize: function () {},
});
//-------------- remove user from warehouse --------------//
var WarehouseUserDeleteView = Backbone.View.extend({
el: ".deleteUser",
events:{
"click": "deleteWarehouseUser"
},
deleteWarehouseUser: function (e) {
elem = $(e.currentTarget)[0];
var self = this;
e.preventDefault();
var warehouseUser = new WarehouseUserDelModel({'id':$(elem).data('id')});
warehouseUser.destroy({
success: function (model, res, options) {
console.log(model);
console.log(res);
console.log(options);
if (res.status == "error") {
Util.formError(res.data);
var errorTemplate = _.template($("#toast-error-template").html());
toastr.error(errorTemplate({errors: res.data}));
} else {
/** append user to select box and remove from lists **/
$("#users").append("<option value='"+$(elem).data('uid')+"'>"+$(elem).data('name')+" </option>");
$(elem).parents('li.list-group-item').remove();
}
}
});
},
initialize: function () {},
});
new WarehouseUserAddNewView();
new WarehouseUserDeleteView();
The actual code that renders your list of users will probably always be jquery - backbone does not come with default render functionality. However, it is common practice to put code that will render the entire contents of the el in a render method of the view. That way it can be called initially, and then called again whenever conditions have changed.
It looks like your general approach is to use each view a bit like an event handler. Each has a single event attached, with one sizeable method to do some work. That's fine as long as it's working for you, but you can also have a more complicated view than handles multiple functions. I might recommend you use your WarehouseView to keep a list of users, and handles both a reusable render, and the delete method you have already written:
var WarehouseView = Backbone.View.extend({
el: '#list_user',
initialize: function(options) {
this.users = (options && options.users) || [];
// render once on intialize
this.render();
},
events: {
// listen for delete clicks on contained elements
'click .deleteUser': 'deleteWarehouseUser',
},
deleteWarehouseUser: function(ev) {
// your same method code should work here
},
render: function() {
// render the list of users you have
this.$el.html('');
for (var i = 0; i < this.users.length; i++) {
// use jquery to add the user to your list as a <li>
}
}
});
var warehouseView = new WarehouseView();
If you use this approach, then inside your add new user method you can do things like:
// ... create your user variable
warehouseView.users.push(user);
warehouseView.render();
The delete (client-side) can also consist of removing a particular user from your view's list, and then rerendering.
You can arrange backbone objects pretty much any way you like, but I hope this recommendation helps. Also note that once you feel more comfortable, creating a Backbone Collection for your users is the more "backbone-y" way to do things rather than a plain array.

$_POST for text in DIV elements

Because of my web style, i don't want to use input & textarea and get information by using $_POST[] and i need to get information that is in DIV element.
For example , I want to get information in this :
<div class="mine" name"myname">
this is information that i want to get and put into database by PHP !
</div>
and :
$_POST[myname];
But i can't do it with $_POST , How can i do it ??
And if this method can't do this , do you know any other method to get information from DIV like this ?
you can call a onsubmit function and make a hidden field at the time of form submission like this
HTML
need to give a id to your form id="my_form"
<form action="submit.php" method="post" id="my_form">
<div class="mine" name"myname">
this is information that i want to get and put into database by PHP !
</div>
<input type="submit" value="submit" name="submit" />
</form>
Jquery call on submit the form
$(document).ready(function(){
$("#my_form").on("submit", function () {
var hvalue = $('.mine').text();
$(this).append("<input type='hidden' name='myname' value=' " + hvalue + " '/>");
});
});
PHP : submit.php
echo $_POST['myname'];
You can use this method. First, with javascript get content of <div>
Code:
<script type="text/javascript">
var MyDiv1 = Document.getElementById('DIV1');
</script>
<body>
<div id="DIV1">
//Some content goes here.
</div>
</body>
And with ajax send this var to page with get or post method.
You would need some JavaScript to make that work, e.g. using jQuery:
$.post('http://example.org/script.php', {
myname: $('.mine').text()
});
It submits text found inside your <div> to a script of your choosing.
You can use following structure;
JS:
$(document).ready(function() {
$("#send").on("click", function() {
$.ajax({
url: "your_url",
method: "POST",
data: "myname=" + $(".mine").text(),
success: function(response) {
//handle response
}
})
})
})
HTML:
<div class="mine" name"myname">
this is information that i want to get and put into database by PHP !
</div>
<input type="button" name="send" id="send" value="Send"/>
You can see a simulation here: http://jsfiddle.net/cubuzoa/2scaJ/
Do this in jquery
$('.mine').text();
and post data using ajax.
Put the content of DIV in a variable like below:
var x = document.getElementById('idname').innerHTML;

jQuery Mobile: How to correctly submit form data

This is a jQuery Mobile question, but it also relates to pure jQuery.
How can I post form data without page transition to the page set into form action attribute. I am building phonegap application and I don't want to directly access server side page.
I have tried few examples but each time form forwards me to the destination php file.
Intro
This example was created using jQuery Mobile 1.2. If you want to see recent example then take a look at this article or this more complex one. You will find 2 working examples explained in great details. If you have more questions ask them in the article comments section.
Form submitting is a constant jQuery Mobile problem.
There are few ways this can be achieved. I will list few of them.
Example 1 :
This is the best possible solution in case you are using phonegap application and you don't want to directly access a server side php. This is an correct solution if you want to create an phonegap iOS app.
index.html
<!DOCTYPE html>
<html>
<head>
<title>jQM Complex Demo</title>
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0"/>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
<style>
#login-button {
margin-top: 30px;
}
</style>
<script src="http://www.dragan-gaic.info/js/jquery-1.8.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
<script src="js/index.js"></script>
</head>
<body>
<div data-role="page" id="login" data-theme="b">
<div data-role="header" data-theme="a">
<h3>Login Page</h3>
</div>
<div data-role="content">
<form id="check-user" class="ui-body ui-body-a ui-corner-all" data-ajax="false">
<fieldset>
<div data-role="fieldcontain">
<label for="username">Enter your username:</label>
<input type="text" value="" name="username" id="username"/>
</div>
<div data-role="fieldcontain">
<label for="password">Enter your password:</label>
<input type="password" value="" name="password" id="password"/>
</div>
<input type="button" data-theme="b" name="submit" id="submit" value="Submit">
</fieldset>
</form>
</div>
<div data-theme="a" data-role="footer" data-position="fixed">
</div>
</div>
<div data-role="page" id="second">
<div data-theme="a" data-role="header">
<h3></h3>
</div>
<div data-role="content">
</div>
<div data-theme="a" data-role="footer" data-position="fixed">
<h3>Page footer</h3>
</div>
</div>
</body>
</html>
check.php :
<?php
//$action = $_REQUEST['action']; // We dont need action for this tutorial, but in a complex code you need a way to determine ajax action nature
//$formData = json_decode($_REQUEST['formData']); // Decode JSON object into readable PHP object
//$username = $formData->{'username'}; // Get username from object
//$password = $formData->{'password'}; // Get password from object
// Lets say everything is in order
echo "Username = ";
?>
index.js :
$(document).on('pagebeforeshow', '#login', function(){
$(document).on('click', '#submit', function() { // catch the form's submit event
if($('#username').val().length > 0 && $('#password').val().length > 0){
// Send data to server through ajax call
// action is functionality we want to call and outputJSON is our data
$.ajax({url: 'check.php',
data: {action : 'login', formData : $('#check-user').serialize()}, // Convert a form to a JSON string representation
type: 'post',
async: true,
beforeSend: function() {
// This callback function will trigger before data is sent
$.mobile.showPageLoadingMsg(true); // This will show ajax spinner
},
complete: function() {
// This callback function will trigger on data sent/received complete
$.mobile.hidePageLoadingMsg(); // This will hide ajax spinner
},
success: function (result) {
resultObject.formSubmitionResult = result;
$.mobile.changePage("#second");
},
error: function (request,error) {
// This callback function will trigger on unsuccessful action
alert('Network error has occurred please try again!');
}
});
} else {
alert('Please fill all nececery fields');
}
return false; // cancel original event to prevent form submitting
});
});
$(document).on('pagebeforeshow', '#second', function(){
$('#second [data-role="content"]').append('This is a result of form submition: ' + resultObject.formSubmitionResult);
});
var resultObject = {
formSubmitionResult : null
}
I have run into same issue where I am calling another .php page from my index.html.
The .php page was saving and retrieving data and drawing a piechart. However I found that when piechart drawing logic was added, the page will not load at all.
The culprit was the line that calls the .php page from my index.html:
<form action="store.php" method="post">
If I change this to:
<form action="store.php" method="post" data-ajax="false">
, it will work fine.
On using PHP and posting data
Use
data-ajax = "false" is the best option on <form> tag.
Problem is that JQuery Mobile uses ajax to submit the form. The simple solution to this is to disable the ajax and submit form as a normal form.
Simple solution: form action="" method="post" data-ajax="false"

Simple PHP/AJAX question

Ok, so I am fairly new to webdeveloping, so probably a silly question:
I have this search form which does autocomplete for fooditems (gets values from a database column) and that works. Now when I press the submit button I want to load a block of code that displays the food-items' calories etc (also in the database on the same row as the food-item).
How can I accomplish such a thing. I kno this is a fairly broad question, but what i am really asking is, how can I make a small part of my website reload when pressing the submit button and using the input given in the text field as a parameter of some kind.
I don't need whole answers, just any tips getting to the right path would be greatly appreciated!
here my code for the input and button:
in head
<script type="text/javascript" src="jquery.js"></script>
<script>
function ok(){
$.post("test.php", { name: "John", time: "2pm" }, function(data){ alert("Data Loaded: " + data); });
}
</script>
in body:
<form autocomplete="off">
<p>
Food <label>:</label>
<input type="text" name="food" id="food" / >
</p>
<input type="submit" id="submit" value="Submit" onclick="ok()" />
</form>
or:
head:
<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.js"></script>
<script>
$("input[type='submit']").bind("click", function (event) {
event.preventDefault(); // Stop a form from submitting
$.post("/path/to/call", { /* data? */ }, function (data) {
// Process return data here
});
});
</script>
body:
<form autocomplete="off">
<p>
Food <label>:</label>
<input type="text" name="food" id="food" / >
</p>
<input type="submit" id="submit" value="Submit" />
</form>
jQuery and Ajax.
Change that input to a button
<button id="submit">Save</button>
For this I would do something like:
$("button#submit]").bind("click", function (event) {
event.preventDefault(); // Stop a form from submitting
$.post("/path/to/call", { /* data? */ }, function (data) {
// Process return data here
});
});
You need to first catch the click event .bind("click"). Then initiate an ajax call $.post which you will send data to. This data is received on the server via the POST array.
Like Josh said, jQuery is the way to go here.
You'll want to do 3 things:
Attach a click handler to a button like "onclick='doSomething();'"
In that function,use jQuery to do an async post to a script like
$.post("test.php", { name: "John", time: "2pm" },
function(data){
alert("Data Loaded: " + data);
});
When this comes back, you can do something with that data(instead of the alert above), like $('#listnode').append... which would stick the HTML into your list
This is the general pattern, but you'll have to fit it to your scenario.
It is hard to answer your question from what little you have given us, but I will assume little knowledge.
Your input fields have to be inside a form tag. The form tag includes an action and a method. The method must be "POST" to send the data. The action can be any URL.
You simply have to name the URL of your php script that will handle the results.
It will find the data in $_POST['food'] etc. It has to build the reply page - the whole screen, with the food and data and the search form for the next submit if you want.
If you want to use AJAX to replace part of the screen, then you have a whole nother level of problems. The trick is to replace the content of a div tag with the requested data.

Categories