I have little knowledge of Javascript, but I think it might be the only way to make things work in my problem.
I am using rails 5.
I basically have checkboxes in a view that represent a price, and every time I check or uncheck one, I would like to update the total price for that view (that I then pass in a hidden_field and a post request).
I'm guessing that what I have to do is get an onclick event going everytime I check or uncheck a box, and update a variable that I then show in the view.
I've found something that looks very similar to my case, but unfortunately I'm unable to reproduce it: Rails Jquery compute total from selected checkboxes in a table
I have my checkboxes with a class "checkbox-count", and I can send an alert everytime I check them, but that's about all I have so far...
Your help would be very appreciated!
This could be handled on the server side by getting an array(checkbox names are all the same array value) of the checked boxes values in a controller action and adding the values together there, maybe you have a reason not to though?
Otherwise this is more of a javascript question, but it could be handled with some vanilla javascript like this maybe:
// a quick custom function for calculating total values of all checked checkboxes in a given form
function calcFormCheckedBoxesTotal(form) {
total = 0;
form.querySelectorAll("input[type='checkbox']:checked").forEach(checked_box => {
total += parseInt(checked_box.getAttribute("value"));
});
return total;
}
// get all form checkbox inputs to be used
checkboxes = document.querySelectorAll("form input.checkbox-count");
// loop through all given form checkbox inputs so we can...
checkboxes.forEach(checkbox => {
// ... add click event listener to each checkbox
checkbox.addEventListener('click', event => {
// ... use my custom function to calculate totals of all checked boxes in the parent form of currently clicked on checkbox and store in "total" variable
total = calcFormCheckedBoxesTotal(event.target.parentElement);
// ... change value of my text input with id="total_price" to show total of checked boxes. Change the target of the querySelector to whatever you want to update(your hidden field) with the total.
document.querySelector("#total_price").value = total;
});
});
<form>
<input type="checkbox" class="checkbox-count" name="price[]" value="25"><label>$25</label><br>
<input type="checkbox" class="checkbox-count" name="price[]" value="50"><label>$50</label><br>
<input type="checkbox" class="checkbox-count" name="price[]" value="100"><label>$100</label><br>
<input type="text" id="total_price" name="total_price" value="0">
</form>
Related
In my ASP.NET Core application, I have an ASP.NET MVC View which displays a list of products. (I guess this applies to other versions of MVC as well).
When I select an item from this list and submit the page, I want the selected product ID to be bound to a ViewModel property in the action method of the controller. I am using POST for this.
I do NOT want to use SelectList for rendering the list of products due to some formatting issues. Therefore I am looping over the list in my view.
How can I bind the selected product with the ProductId property of the inbound ViewModel object?
It's unclear what you mean by "select an item from this list and submit the page". Are you picking an item, potentially filling out more fields, and then submitting the whole shebang, or does picking an item constitute submitting the form. Depending on the situation there's a few approaches:
If picking an item submits the form, then you can simply make the "Select" button a submit button and give it a name and value. For example:
Item 1 <button type="submit" name="ProductId" value="1">Select</button>
Whichever "Select" button is clicked, then, will have its value posted as ProductId.
If you need to pick an item while remaining on the page to fill out other fields, then you can use radio buttons as an alternative to a select list. This is similar to approach above, except you will not instantly post the form. Your inputs would look similar though:
<label>
<input type="radio" name="ProductId" value="1"> Item 1
</label>
<label>
<input type="radio" name="ProductId" value="2"> Item 2
</label>
...
Finally, if you need to not instantly submit and you do not want to use radio buttons either, then your only real option is using JavaScript to set a hidden input. You would bind to the click event of your "Select" button or whatever and then set a hidden input with name="ProductId" to the appropriate value. Then, when you finally submit the form, the value of the hidden input will be posted as ProductId.
I have a form that will have this format:
I am first row (textbox) [Submit Button]
I am second row (radiobutton) [Submit Button]
I am third row (checkbox) [Submit Button]
I am fourth row (dropdown) [Submit Button]
I am fifth row (textbox) [Submit Button]
I am sixth row (textbox) [Submit Button]
I am seventh row (radiobutton) [Submit Button]
The text (ex: I am fourth row) and the value of the control will be loaded from a database. I would like the Submit button to only send the value of its control (ex: row 4, dropdown value == N/A) to the server. Not all the controls' values.
Now will I have to wrap each row with a Html.BeginForm or can I wrap all rows with one Html.BeginForm? What would be the best (or even better) way to handle such a thing.
Note: I've searched around SO and haven't seen a problem like this discussed.
Sounds like you need to create a loop to build your table.. and conditionally create the rows based on whatever it is that you are keying on to decide to put a specific element type( text, radio, checkbox, etc..) and each row would be have to be wrapped in form tags. Since you would need to evaluate for the correct element, you can use that to also build your BeginForm to tell it where to post to an action, possibly a different action per element type so that the action receives only the data you want it to receive
I believe you can do this using Jquery:
First of all create individual forms for each row.
Try using below code..
Jquery:
function SubmitForm(btn)
{
var form = btn.serialize();
$.post("your URL here",form,function() {
alert("Saved");
});
}
Html:
<form id='form1' >
...
Other controls on your form
...
<input type="button" id="form1" onclick="SubmitForm(this)" />
</form>
First off, you cannot nest form tags (browsers don't support it).
An input[type=submit] on click triggers a post back event on its' parent form.
ex.
<form action='/PostBackTo' onsubmit='DoSomething()'>
<input type='submit />
</form>
So you will have to wrap every control inside its own form and any additional data you want posted back will need to reside in input or select tags inside the form.
Say you would like to post back an id with every submit, you would have to add
<input type='hidden' value='#id' />
inside every form tag to have it included in the postback.
I'd suggest if you do it this way, use javascript to intercept the submit action and submit the forms' data via AJAX post (if it's something like a 'save changes' button).
For example: 1. I am first row:
<input type="text" value="#textValue" id="txtFirstRow" />
<input type="button" onclick="post('txtFirstRow');" />
Javascript code:
function post(name)
{
var txt = document.getElementById(name).value;
$.getJSON("/Controller/Action",
{
text: txt
},
function (data) {
//returned result
});
}
I've got an editor template which renders out a checkbox:
#Html.CheckBoxFor(model => model.Follow)
Which renders something like this:
<input checked="checked" data-val="true" data-val-required="The Follow field is required." id="Follow" name="Follow" type="checkbox" value="true" />
<input name="Follow" type="hidden" value="false" />
AFAIK the hidden field is something to do with catering when an unchecked box isn't sent to the server or something.
Anyway, if i take a look at the Request.Form["Follow"] when the checkbox is checked, i see a value of "true,false".
How do i coerce a bool from this value? Do i simply ignore the second field? (e.g the hidden field).
I'm doing this is a base controller (protected method, invoked from child controller), so i don't have a strongly-typed view model, only the raw Request object.
Can anyone help? Or alternatively, if someone could point me to where in the MVC source code this happens, i could take a look myself, but not sure where to start looking.
You are correct the hidden field is just so the form will be submitted to the server. Because if the form had just checkboxes that are not checked then nothing will be submitted and the server would not know to set them to false.
You only require 1 hidden field per form, you do not need one per checkbox. But if your making your own control it is hard to tell if a hidden textbox is already on the field or not. If you know you are always going to have a textbox or select list etc somewhere else on your forms you do not need a hidden textbox at all
You can rename your hidden textbox to anything name it "dummy" or something different to the checkbox name so Request.Form["Follow"]; will only return the value of the check box not need to split. You never need to check the value of the "hidden textbox".
On a side note you shouldn't be using Request.Form["Follow"] you Action method should have a parameter like this instead "bool? follow"
MVC helper renders checkbox input control with two input fields, the checkbox and the hidden, because the browser do not send a value for checkbox input field if the checkbox is not selected. If you do not use auto mapping, you need to parse the input value that you receve from your form.
Use this simple rule to detect the checkbox:
var rawFollow = Request.Form["Follow"];
if (rawFollow.Contains("true"))
{
// do something
}
As far as i know, the extra hidden field is because if the checkbox is NOT checked, that input will not be submitted with the form and therefore we need the hidden field with the value of false.
So the only solution is can think of is this:
var rawFollow = Request.Form["Follow"];
var rawFollows = rawFollow.Split(',');
if (rawFollows.Count() > 1)
{
rawFollow = rawFollows[0];
}
But this seems hacky (and what about the order of the elements on the page, what if for some reason the hidden field was FIRST, then it would always evaluate to false), which is why i'm wondering how the MVC source does this.
I can't seem to get the inputted text of a textarea. When I do :
die($request->getPostParameter('comment'))
It outputs the word "array". When I print_r() it does show the textarea is an array and its value is stored in the array. But I don't know how to get that value so I can put it into a field in a table.
#greg0ire: I am doing this because I am trying to save data to two different tables. My html page displays a form that is actually made up of two forms from two different classes/models. I have managed to save all fields to both tables except for the comment field. I then tried getting the value and realising it was an array, wondered if this was what was causing my data not to save. This is why I am asking this question. I have asked another question which explains the context.
These are the functions that run on clicking the submit button
public function executeUpdateInlineForm(sfWebRequest $request)
{
$overdueInvestigation = Doctrine_Core::getTable('investigation')->find( $request->getParameter('id'));
$investigationForm = new investigationInlineForm($overdueInvestigation);
$commentForm=new commentForm();
$investigationForm->bind($request->getParameter($investigationForm->getName()), $request->getFiles($investigationForm->getName()));
$commentForm->bind($request->getParameter($commentForm->getName()), $request->getFiles($commentForm->getName()));
$this->processInlineForm($investigationForm, $commentForm);
}
protected function processInlineForm(sfForm $investigationForm, sfForm $commentForm)
{
if ($investigationForm->isValid())
{
$investigation = $investigationForm->save();
$comment = $commentForm->updateObject();
$comment->setInvestigation_id($investigationForm->getObject()->getId());
$comment->setComment($commentForm->getObject()->getComment());
$comment->setuserId($investigationForm->getObject()->getCreatedUserId());
$comment->setDateEntered(time());
$comment->save();
$this->redirect('investigation/overdue/');
}
}
you could simply store $request->getPostParameter('comment') in an array and use array_pop() on this array, but I think it would be better to understand why you're getting an array. I think the name of the textarea must be comment[], when it should probably be just comment.
UPDATE
After reading your update and your other question it seems you need to have this naming convention for your fields:
<input type="text" name="investigation[field1]"/>
<input type="text" name="investigation[field2]"/>
<input type="text" name="investigation[field3]"/>
<input type="text" name="comment[content]"/>
Use the setNameFormat() method on the widget schema of your forms to achieve this, then bind your investigation form to the investigation request parameter, and your comment form to the comment parameter and you will be fine.
Good luck!
I am running into an issue with a parameter not getting the value from the form data. It is showing the correct number of items (i.e. if the user select 5 options, the list contains 5 items) in the List but all values are zero. Below is my from my HTML view:
#using (Html.BeginForm())
{
#Html.HiddenFor(s => s.SOWId)
foreach (LabelTable.Domain.Entities.Option option in ViewBag.Options)
{
<div class="wizard-section" id=#option.Level>
#Html.RadioButton("["+(option.Level-1)+"].OptionId", option.OptionId) #option.OptionName
</div>
}
<div class="buttons">
<input type="submit", value="Continue", class="button"/>
</div>
}
Here is my controller method:
[HttpPost]
public ViewResult Wizard(StatementOfWork SOW, List<int> OptionIds)
{
//do something
}
OptionIds contains the following upon posting:
[0] = 0
[1] = 0
[2] = 0
and so on...
What I am trying to do is create a form where the user is presented with some options to select from (this form is one section of a wizard).
There are 5 level (or more) of options. All data for the form is sent to the view via the ViewBag.Options. All levels are hidden except level 1. Upon making a selection on level 1 the next level shows and so on. The form only posts back the options selected via each level. Originally I was doing this with mulitple post backs to the server but I did not like that (to many round trips)
I plan to add the options selected in each level to the SOW model which I am passing from view to view of the wizard.
Your View code is a bit confusing, but as far as I understand, you want the ModelBinder to bind your radiobutton values to the OptionIds list upon posting. In that case, the names of your radiobuttons should be OptionIds[0], OptionIds[1], etc. So again, I am not sure what the Level property is, but I assume you want something like this:
#Html.RadioButton("OptionIds["+(option.Level-1)+"]", option.OptionId)
Try replacing :
#Html.RadioButton("["+(option.Level-1)+"].OptionId", option.OptionId)
with:
#Html.RadioButton("["+(option.Level-1)+"]", option.OptionId)