How to send list value in Ruby Sinatra? - ruby

I have a simple form where there is a list:
<form method ="post" action ="">
<select>Select subject
<option value="1">Maths</option>
<option value="2">Science</option>
</select>
<input type="submit" name="Submit" />
My question is, if I select the option Maths, I would like the value to be sent eg /1.
What should be written in action? How should the route be written ?
get '' do
end

Your route could look something like this:
post '/subject' do
#subject = params[:subject]
# do whatever you want now
end
But you would need to give your select tag a name and your form an action:
<form method="post" action="/subject">
<select name="subject">
<!-- etc etc -->
Also have a look at related questions.

we tend to look at queries as GETs (makes sense, it is after all retrieving information)
rather than a POST which (doesn't actually change data) yet responds with a result page
a common (gnarly) pattern we often see is to rewrite (in js or redirect)
to the form
GET '/search/:q1/and/:q2' do
// result of search filtered by q1 and q2
end
which is also quite neat

Related

Laravel confused if I should use <form> tag or not when doing a ajax put request

I am making a simple put request to my app backend using axios.put();
This all works, I have a button that is binded to vue like #click="submitForm"
However looking around I see that some people still wrap their input fields in forms like those:
<form method="POST" #submit.prevent="onSubmit" action="{{ route('someRoute') }}" id="form-submit">
{{ method_field('PUT') }}
{{ csrf_field() }}
Even if I dont use a form like the one above I get the same result when calling my ajax put request.
Laravel allready adds csfr headers to axios by default in resources/assets/js/bootstrap.js
So is there any reason I still should wrap my inputs in a form like above?
Thanks
Your ajax request doesn't matter if you do your inputs in form tags or not, because the request still sends and receives data from a server.
I would use a form tag because everybody can read the markup much easier and it could be usefull for writing less code in javascript - one example
<form action="" method="">
<div class="form-group">
<label class="control-label">Input</label>
<input type="text" name="input" />
</div>
</form>
$(document).ready(function() {
$('#some-form').on('submit', function() {
var data = $(this).serialize();
... do whatever you want (like ajax call) ...
return false;
});
);
You're using an Ajax request, in which case a standard "form submit" would get prevented. Putting a form around it is not obligatory, especially if you use a button element, which is not a classic form element anyway.

Angular 2 form valid by default

Having issue with form validation .
i want to submit the form only when form is valid.
but with the empty inputs and clicking on submit button is submitting the form although the inputs are empty.
<form name="equipmentForm" #f="ngForm" (ngSubmit)="f.form.valid && addEquipment()" validate>
Inputs be like this.
<input name="equimentId" class="text-input form-control" type="text" [(ngModel)]="model.equipmentNumber" pattern="^[0-9][0-9]{1,19}$" title="Equipment ID. can be upto 20 digits only.">
I cant post the whole code although.
this
f.form.valid is true from form initialization
wanted to acheive something like this
<div *ngIf="!model.equipmentModel && f.submitted" class="text-danger">
Please enter Equipment Model
</div>
So on submit i want to show this message instead of default browser's.
but this f.form.valid is goddamn true from default.
You should add required attribute to your input tags to, then as #Cobus Kruger mentioned, form will not be submitted untill it is filled.
However you can also give a try to pristine, dirty options, which allow you to check if the user did any changes to the form so in this case your condition may look like this:
<form name="equipmentForm" #f="ngForm" (ngSubmit)="f.form.valid && f.form.dirty ? addEquipment() : ''" validate>
and the input:
<input name="equimentId" class="text-input form-control" type="text" [(ngModel)]="model.equipmentNumber" pattern="^[0-9][0-9]{1,19}$" title="Equipment ID. can be upto 20 digits only." required />
In this case it will check if any changes were applied to the input, and submit the form if both conditions are met.
If you specify the required attribute on the input, then the form will not be submitted unless a value is filled in. But that only covers values that were not supplied and you may want to check for invalid values as well.
The usual way is to disable the submit button unless the form is valid. Like this:
<button type="submit" [disabled]="!f.form.valid">Submit</button>
The Angular documentation about form validation also shows this. Look near the bottom of the "Simple template driven forms" section
In function which you call on submit you can pass form as parameter and then check. In html you will need to pass form instance:
<form name="equipmentForm" #f="ngForm" (ngSubmit)="addEquipment(f)" validate>
In typescript:
addEquipment(form){
if(form.invalid){
return;
}
//If it is valid it will continue to here...
}

How to use multiselect in codeception and laravel

Is it possible to use multiselect boxes on Codeception?
My form code:
<form accept-charset="utf-8" class="form-vertical" id="solicitor-form" method="POST" action="http://mytest.dev/role">
<select multiple="true" id="optgroup" name="solicitor[]">
<option value="1" selected>Yorkshire</option>
<option value="2" selected>Quarry</option>
<option value="3" selected>William Hurst</option>
</select></div></div>
<input class="btn-large btn-success btn" type="submit" value="Update Access">
</form>
I've tried something like this for the test:
$i->SeeOptionIsSelected("#solicitor-form", 'Yorkshire');
$i->SeeOptionIsSelected("#solicitor-form", 'Quarry');
But codeception fails on SECOND select. So then I tried this:
$i->SeeOptionIsSelected('#solicitor-form select[name=solicitor[]]', 'Yorkshire');
$i->SeeOptionIsSelected('#solicitor-form select[name=solicitor[]]', 'Quarry');
but it doesnt seem to resolve solicitor[] correctly, specifically the [] because it trips itself up with the pattern match.
Edit: I tried Daverts answer like this:
$i->selectOption('optgroup',array('Quarry', 'Yorkshire'));
But this is the output when running the test:
* I select option "optgroup","lambda function"
It seems the "lambda function" is not returning the correct result?
Sorry for a delay.
It looks like this feature was not documented. Sorry, I totally forgot to update docs, when released 1.6.3.
You can pass an array of options as a second parameter to select multiple options.
$I->amOnPage('/form/select_multiple');
$I->selectOption('What do you like the most?',array('Play Video Games', 'Have Sex'));
$I->click('Submit');
Thanks, I will update a reference soon.
The bug is exactly with [] as far as I can see in my application, for example I have this select:
<select multiple="true" class="span h300" id="products[]" name="products[]">...</select>
and when I do:
$I->selectOption('Products', array('value', 'someOtherValue') );
I'll get the same error as you do.
As you can see I have some additional classes, .span and .h300 so I've used .h300 selector which is unique on that page and the test works perfectly, the values are in db and verification works as expected...
So to sum it up my selector which works is:
$I->selectOption('.h300', array('value', 'someOtherValue') );
Just my 2 cents on the issue, don't have enough time now to investigate what causes the problem with []...

How does Laravel handle PUT requests from browsers?

I know browsers only support POST and GET requests, and Laravel supports PUT requests using the following code:
<?= Form::open('/path/', 'PUT'); ?>
... form stuff ...
<?= Form::close(); ?>
This produces the following HTML
<form method="POST" action="http://example.com/home/" accept-charset="UTF-8">
<input type="hidden" name="_method" value="PUT" />
... form stuff ...
</form>
How does the framework handle this? Does it capture the POST request before deciding which route to send the request off to? Does it use ajax to send an actual PUT to the framework?
It inserts a hidden field, and that field mentions it is a PUT or DELETE request
See here:
echo Form::open('user/profile', 'PUT');
results in:
<input type="hidden" name="_method" value="PUT">
Then it looks for _method when routing in the request.php core file (look for 'spoofing' in the code) - and if it detects it - will use that value to route to the correct restful controller.
It is still using "POST" to achieve this. There is no ajax used.
Laravel uses the symfony Http Foundation which checks for this _method variable and changes the request to either PUT or DELETE based on its contents. Yes, this happens before routing takes place.
You can also use an array within your form open like so:
{{ Form::open( array('route' => array('equipment.update', $item->id ),
'role' => 'form',
'method' => 'put')) }}
Simply change the method to what you want.
While a late answer, I feel it is important to add this for anyone else who finds this and can't get their API to work.
When using Laravel's resource routes like this:
Route::resource('myRoute','MyController');
It will expect a PUT in order to call the update() method. For this to work normally (outside of a form submission), you need to make sure you pass the ContentType as x-www-form-urlencoded. This is default for forms, but making requests with cURL or using a tool like Postman will not work unless you set this.
PUT usually refers to update request.
When you open a form inside laravel blade template using,
{{ Form::open('/path/', 'PUT') }}
It would create a hidden field inside the form as follows,
<input type="hidden" name="_method" value="PUT" />
In order for you to process the PUT request inside your controller, you would need to create a method with a put prefix,
for example, putMethodName()
so if you specify,
{{ Form::open('controller/methodName/', 'PUT') }}
inside Form:open. Then you would need to create a controller method as follows,
class Controller extends BaseController {
public function putMethodName()
{
// put - usual update code logic goes here
}
}

How to serialize a form with dynamically added inputs using jQuery?

I've read through a lot of questions addressing similar question but I can't get a grip on it, yet.
I have a simple HTML form just like
<form id="edit-items" name="edit-items" onsubmit="saveItems();">
<input type="submit" value="Save">
<input class="item" id="ei81" type="hidden" name="i[81]" value="1">
<input class="item" id="ei124" type="hidden" name="i[124]" value="1">
</form>
The two existing hidden inputs could be set upon document loading due to a prior save.
Now I have images (kind of a menu). If they are clicked a corresponding hidden input is appended to the form:
<img id="i37" class="clickable-item" src="items/i37.gif" title="item name" onclick="addItem(37,1)" />
The addItem function:
function addItem(id,n) {
var zitem = $("#e"+id);
if ( 0 in zitem ) {
if ( zitem.val() > 0 ) {
var newcnt = parseInt(zitem.val()) + n;
if ( newcnt <= 0 ) {
zitem.remove();
}
else {
zitem.val(newcnt);
}
}
}
else if(n == 1) {
var iform = $("#edit-items");
iform.append("<input class=\"item\" id=\"e"+id+"\" type=\"hidden\" name=\"i["+id+"]\" value=\"1\">");
}
}
This part all works correct, after clicking the image, my form looks like
<form id="edit-items" name="edit-items" onsubmit="saveItems();">
<input type="submit" value="Save">
<input class="item" id="ei81" type="hidden" name="i[81]" value="1">
<input class="item" id="ei124" type="hidden" name="i[124]" value="1">
<input class="item" id="ei37" type="hidden" name="i[37]" value="1">
</form>
which is exactly what I want. But then when hitting the submit button only the first two elements are submitted (the ones which have not been added dynamically).
Now, I read a lot about .bind and .live handlers but I am missing some point obviously. I tried to delete the onclick attribute on the images and to bind the .live to them since they are causing the new inputs:
$(".clickable-item").live("click", function() {
addItem($(this).attr("id"),1);
});
However, the ID is not transferred which is needed, though (hence no correct input is added). I learned that .live doesn't bind the handler to any elements but to the event.
Is it even possible to pass the element which has been clicked to the live handler?
Should the images even be watched by .live or should it be bound to something else?
The last thing I learned form another question here is that the inputs should be watched by .live, since they are dynamically added. But what kind of event I would attach? The inputs themselves are not clicked.
I would really appreciate any help as I am cracking my head and starting to get lost on that one.
Thanks in advance,
Paul
Regarding live() [docs]: this refers to the clicked element, so you can pass it to addItem with addItem(this, 1). This part of your code should work.
If you don't add or remove images dynamically then there is no reason to use live. You can just use click() [docs] (and yes, don't use onclick in the HTML).
But I see another problem:
The image id is i37. $(this).attr("id") will return this value.
In your addItem function you then take this value and perform string concatenation. The result will be $("#ii37") (note the two is).
The input element you create will have the id ii37 and not i37.
If you correct this to match it with the other elements like in your example (i.e. i37) , you will have problems because you have several elements with the same id (the input element and the image). If the image comes before the input field in the hierarchy, then $("#i37") will always select the image and you cannot call .val() on an image.
As I don't know what is the overall purpose of the code and what you want to do, I cannot give any suggestion how to improve this. Maybe it is enough to just change the prefix of the image and input field ids.
I learned that .live doesn't bind the handler to any elements but to the event.
That is not correct. .live() binds the event handler to the document root. Events, if not cancelled, bubble up the DOM tree, so they reach the root eventually. There, the event.target [docs] property is examined to determine the element that was clicked.

Resources