Multiple PHP Function handlers in HTML Form? - php

I'm using OctoberCMS based on Laravel and Twig.
I'm trying to call 2 different functions form 2 php files using 1 form and 2 submit buttons.
I connect components I made, Edit.php and Delete.php, to a page.
Instead of directing the Form action to /Edit.php, I direct it to the current url and use a handler to call the php function onEdit() in Edit.php, using the Edit submit button.
In the same form, how can I call onDelete() in Delete.php using the Delete submit button?
It only selects 1 handler and calls its function.
I cannot merge the two functions into 1 php file.
https://jsfiddle.net/t3t5e2Ln/
Form
<!-- Edit or Delete -->
<form method="POST" action="{{ url_current() }}" enctype="multipart/form-data">
<!-- Edit Handler -->
<input type="hidden" name="_handler" value="onEdit" />
<!-- Delete Handler -->
<input type="hidden" name="_handler2" value="onDelete" />
<!-- Title -->
<input type="text" name="title" maxlength="255" />
<!-- Edit Submit -->
<input type="submit" name="edit" value="Edit" />
<!-- Delete Submit -->
<input type="submit" name="delete" value="Delete" />
</form>
Edit.php
public function onEdit() {
//edit
}
Delete.php
public function onDelete() {
//delete
}

Both previous answers are incorrect. See http://octobercms.com/docs/cms/components and http://octobercms.com/docs/plugin/components for more information on developing custom components for October.
First off, I would put both handlers within the same component (RecordData.php as an example of a name). Secondly, you should be taking advantage of October's excellent AJAX framework: http://octobercms.com/docs/ajax/introduction.
Here's an example of what your RecordData.php component class could look like:
<?php namespace MyVendor\MyPlugin\Components;
use Auth;
use Flash;
use Cms\Classes\ComponentBase;
use MyVendor\MyPlugin\Models\MyRecord as MyRecordModel;
class RecordData extends ComponentBase
{
/**
* Provide information about the component
*/
public function componentDetails()
{
return [
'name' => 'RecordData Component',
'description' => 'Used for editing and deleting custom record data'
];
}
/**
* Register any component properties
* http://octobercms.com/docs/plugin/components#component-properties
*/
public function defineProperties()
{
// return [];
}
/**
* Get the record that will be edited, factoring in the user's access to the specified record
*
* #return MyRecordModel
*/
public function getRecord()
{
$user = Auth::getUser();
if ($user) {
return MyRecordModel::findOrFail(post('recordId'));
} else {
throw new \Exception("You do not have access to do that.");
}
}
/**
* AJAX Handler for editing data
*/
public function onEdit()
{
// Get the record
$record = $this->getRecord();
// Modify the record
$record->title = post('title');
// Save the modifications to the record
$record->save();
// Notify the user that the record has been edited
Flash::success("Record successfully edited");
}
/**
* AJAX Handler for deleting data
*/
public function onDelete()
{
// Get the record
$record = $this->getRecord();
// Delete the record
$record->delete();
// Notify the user that the record has been deleted
Flash::success("Record deleted");
}
}
And then your default.htm partial to render that component would look like this:
{{ form_open() }}
{# Hidden form field containing the record id. Passing the record id through the URL or other means is possible as well #}
<input type="hidden" name="recordId" value="{{ __SELF__.recordId }}">
{# Title #}
<input type="text" name="title" maxlength="255" />
{# Edit Button #}
<button type="button" data-request="{{ __SELF__ }}::onEdit">Save changes</button>
{# Delete Button #}
<button type="button" data-request="{{ __SELF__ }}::onDelete">Delete record</button>
{{ form_close() }}
Let me walk you through the Twig markup that is pasted above:
{{ form_open() }} and {{ form_close() }} are Twig helper functions registered by October to simplify the act of creating form elements because they will automatically make sure that the correct markup is generated and it includes the csrf token hidden field if you choose to enable that on your site.
{# #} represent a comment block in Twig, I usually prefer to use them instead of <!-- --> because that way the comment will only be visible to people viewing the actual source code of the Twig file, not all your website's users.
data-request utilizes the attributes API of the October AJAX framework to indicate to the AJAX framework what method on the server will be responsible for handling requests triggered by the element that the data-request attribute is included on.
{{ __SELF__ }} refers to the current component, it will essentially drop in the value of that component's alias. Basically, all you need to know is that using it will enable to you put more than one component on the page at a time in the future. ::onDelete and ::onEdit after the {{ __SELF__ }} is what tells the server what method you want to run on the component specified by {{ __SELF__ }} to handle that AJAX request.

Usually this should be done by ajax request, so you can choose the endpoint independently, but use a few js can do the trick also.
$('input[type=submit]').on('click', function(e) {
e.preventDefault();
var url = '/Edit.php';
if (this.name == 'delete') {
url = '/Delete.php';
}
this.form.action = url;
this.form.submit();
});

in your header
<head>
<script language="javascript" src="editordelete.js" type="text/javascript"></script>
</head>
your buttons
<input type="button" name="edit" value=edit onClick="seteditAction();" />
<input type="button" name="edit" value=edit onClick="setdeleteAction();" />
create a file called "editordelete.js and put this inside put your form name where i wrote yourformnamesgoeshere
function seteditAction() {
document.yourformnamegoeshere.action = "Edit.php";
document.yourformnamegoeshere.submit();
}
function setdeleteAction() {
document.yourformnamegoeshere.action = "Delete.php";
document.yourformnamegoeshere.submit();
}
give your form a name ,method is post and action is noting
<form name="yourformnamegoeshere" method="post" action="">

Related

error: The POST method is not supported for this route. Supported methods: GET, HEAD. - using laravel livewire

I'm trying to do an image upload using Laravel livewire, but when I click on the button "upload" to test the functionality this error appears
The POST method is not supported for this route. Supported methods: GET, HEAD'
The programs:
ROUTE
Route::get('/upload', UploadFoto::class)->name('upload.foto.user');
CONTROLLER (using dd for the tests)
<?php
namespace App\Http\Livewire\User;
use Livewire\Component;
class UploadFoto extends Component
{
public $foto;
public function render()
{
return view('livewire.user.upload-foto');
}
public function storageFoto()
{
dd('aqui');
}
}
VIEW
#extends('layouts.app')
#section('content')
<div>
{{-- To attain knowledge, add things every day; To attain wisdom, subtract things every day. --}}
<form action="#" method="post">
<input type="file" name="foto" id="foto" wire:submit.prevent="storageFoto">
<button type="submit">Upload</button>
</form>
</div>
#endsection
You set get method on this route - but upload use post method. Change it:
Route::post('/upload', UploadFoto::class)->name('upload.foto.user');
please check this, you added submit in wrong place of form
<div>
<form wire:submit.prevent="storageFoto" method="post">
<input type="file" name="foto" id="foto">
<button type="submit">Upload</button>
</form>
</div>
and you should check this lines into app file
#livewireStyles
#livewireScripts
change route method to Post
Route::post('/upload', UploadFoto::class)->name('upload.foto.user');

Trying to submit one <form> with method="POST" duplicates the route and doesn't save the information with an store function()

Im trying to submit one form with method post to save one element in astore function() but when I click submit duplicates the route, for example looking like this:entradas/1/ventaEntrada/200000/montoTotal/entradas/1/ventaEntrada/200000/montoTotal and doesn't save the information, I dont know why this is happening
Below i will let the code of my route,my form,my create function() and my store function()
Also show404 Not Found when I click submit
Route
Route::resource('/entradas/{id_entrada}/ventaEntrada/{precio_entrada}/montoTotal', 'Venta_entradaController');
create function()
public function create(Request $request,$id_entrada,$precio_entrada){
$venta_entrada = DB::select(DB::raw(
"SELECT monto_total,fecha,fk_cliente_natural,fk_cliente_juridico
FROM venta_entrada "
)
);
return view('home.crearVenta_entrada')
->with('venta_entrada',$venta_entrada)
->with('id_entrada',$id_entrada)->with('precio_entrada',$precio_entrada);
}
store function()
public function store(Request $request,$id_entrada,$precio_entrada)
{
$venta_entrada=new Venta_entrada();
$venta_entrada->monto_total=$precio_entrada+$request->monto_total;
$now = new \DateTime();
$venta_entrada->fecha=$now->format('d-m-Y');
$venta_entrada->fk_cliente_natural=1;
$venta_entrada->save();
return back();
}
Form with the method POST
<form action="entradas/{{$id_entrada}}/ventaEntrada/{{$precio_entrada}}/montoTotal" method="POST">
#csrf
<input type="number" name="monto_total" placeholder="Monto total" class="form-control mb-2" required>
<button clas="btn btn-primary btn-block" type="submit">ADD</button>
BACK
</form>
I have check your problem and you have use "Resource Route" right.
so for routing run following command in your terminal/command prompt
php artisan route:list
It will show all routes lists and find your action name
Then you'll add in form action name like
<form action="{{ route('name') }}" method="post">
...
</form>
Example:
<form action="{{ route('Venta_entrada.store') }}" method="post">
...
</form>
I hope it will help you :)

Validate Laravel form in real time using laravel-jsvalidation

I am using laravel-jsvalidation to validate forms on client side but the plugin validate the form after submit.
How can I change it to a real-time validation while user is inputting data?
Calling plugin:
<script type="text/javascript" src="{{ asset('vendor/jsvalidation/js/jsvalidation.js')}}"></script>
{!! $validator->selector('#review-form') !!}
Form:
<form action="{{action('GoToTheController')}}" method="POST" id="review-form">
<div class="form-group"><input type="text" class="fullName" name="fullName">
</div>
</form>
Controller:
$validator = JsValidator::make( ['fullName'=> 'required']);
return view('create')->with('validator', $validator);
In bootstrap.php under the plugin(laravel-jsvalidation) folder I added these lines so it works fine by clicking on input elements.
onfocusout: function (element) {
if (!this.checkable(element)) {
this.element(element);
}
}
or you can make a copy of the file, add the above lines into it and use it.

Serializing FormView data in JSON

I am trying to change the approach of rendering templates. I was using a server-side template engine. Now that I need to return only JSON from backend instead of HTML, I need to move my templating to front-end.
The problem for me as a newbie, is when the template contains a form. In other words, when the final JSON should also contain a csrf token. Please to take the example of CRUD application for books (one entity Book(id_book, name)). The template for Reading a record shows the book name and allow deletion of a book.
In Symfony2 controller, I use createFormBuilder() method that creates the delete form object, to which I apply createView()method. The object returned by the latter is used by form_widget()in the template engine (Twig). At the end:
<div id="bookName">{{book.name}}</div>
<div id="bookDelete">
<form action="{{ path('book_delete', { 'id': book.id }) }}" method="post">
<input type="hidden" name="_method" value="DELETE" />
{{ form_widget(delete_form) }}
<button type="submit"></button>
</form>
</div>
Which will return:
<div id="bookName">Symfony2 In Depth</div>
<div id="bookDelete">
<form action="/web/app_dev.php/deletes" method="post">
<input type="hidden" name="_method" value="DELETE">
<div id="form">
<input type="hidden" id="form_id" name="form[id]" value="15">
<input type="hidden" id="form__token" name="form[_token]" value="dd6573ae916ae30f78ba35a8c67e5d42a2764c1c">
</div>
<button type="submit"></button>
</form>
What I imagine when moving template rendering to front-end is a final JSON from server looking like:
{
'id':15,
'name': 'Symfony2 in Depth',
'csrf_token' : 'dd6573ae916ae30f78ba35a8c67e5d42a2764c1c'
}
Question is how to implement the same Symfony2 internal mechanism to render csrf token for DELETE form, as part of the final JSON to read a book entity? Is it acceptable to get rid of {{ form_widget(delete_form) }} and all its long objects, and only serialize csrf token with book name? What does this will affect? I feel it is good for performance but how?
Your usual guidance is much appreciated.
You can create you twig file something like:
{
'id': '{{ form.id.vars.value }}'
'name': '{{ form.name.vars.value }}'
'csrf_token': '{{ form._token.vars.value }}'
}
Anyway I dont recommend you use csrf token when you are using API, it is better if you disabled. If you want to disable for all application in the config.yml:
framework:
csrf_protection:
enabled: false
Or just for one form in the Type form add:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'csrf_protection' => false,
));
}

Posting a Laravel form is not working

I am setting up a simple form in laravel:
This is the route file:
Route::get('backoffice/upload', [ 'as' => 'backoffice/upload',
'uses' => 'UploadController#uploadForm']);
Route::post('backoffice/saveimage',[ 'as' => 'backoffice/saveimage',
'uses' => 'UploadController#saveImage']);
This is the controller:
class UploadController extends \BaseController
{
public function uploadForm()
{
return View::make("backoffice.upload.create");
}
public function saveImage()
{
return "Uploading...";
}
}
And this is the View file:
<h1>Upload Image</h1>
{{ Form::open(['action' => 'UploadController#saveImage']) }}
<div class='formfield'>
{{ Form::label('newfilename','New File Name (optional):') }}
{{ Form::input('text','newfilename') }}
{{ $errors->first('newfilename') }}
</div>
<div class='formfield'>
{{ Form::submit($action,['class'=>'button']) }}
{{ Form::btnLink('Cancel',URL::previous(),['class'=>'button']) }}
</div>
{{ Form::close() }}
// Generated HTML
<h1>Upload Image</h1>
<form method="POST" action="http://my.local/backoffice/saveimage" accept-charset="UTF-8"><input name="_token" type="hidden" value="x9g4SW2R7t9kia2B8HRJTm1jbLRl3BB8sPMwvgAM">
<div class='formfield'>
<label for="newfilename">New File Name (optional):</label>
<input name="newfilename" type="text" id="newfilename">
</div>
<div class='formfield'>
<input class="button" type="submit" value="Create">
</div>
</form>
So, if I go to: http://my.local/backoffice/upload I get the form with the HTML above.
However, if I type anything, then click SUBMIT, I return to the form but now have the following URL:
http://my.local/backoffice/upload?pz_session=x9g4SW2R7t9kia2B8HRJTm1jbLRl3BB8sPMwvgAM&_token=x9g4SW2R7t9kia2B8HRJTm1jbLRl3BB8sPMwvgAM&newfilename=ddd
This makes no sense to me. Up until now I have always used route::resource when dealing with forms, and had no problem. I am trying to do a simple form with GET and POST and am having no end of grief. What am I missing?
Furthermore, if I modify routes.php and change it from post to any, then open a browser window and type: http://my.local/backoffice/saveimage then I get the message "Uploading..." so that part is working ok.
Found the solution. In making the backoffice of the system, I had re-used the frontoffice template but removed all the excess. Or so I had thought. However, the front office header template had a form which I had only partially deleted.
So the problem was that there was an opening FORM tag I didn't know about. Consequently, when I clicked on submit to my form, it was actually submitting to this other form.
As the other form had no action it was default to itself.
Of course, had I just validated the HTML this would have shown up straight away. The lesson learned here is to validate my html before submitting questions!
Try this, and be sure to correctly configure your url at app/config/app.php
{{Form::open(['url'=>'backoffice/saveimage'])}}
//code
{{Form::close()}}

Categories