ROR: How to fetch data from View to Controller - ruby-on-rails

It confused me for a long time.
I have this input field in my Partial Views:
<input name="promocode" class="field" placeholder="Arlington" id="promo_code">
And I have a main form in my layout page called "new_user" and one button signupBtn
$("#signupBtn").click(function (e) {
e.preventDefault();
var promocode = document.getElementById('promo_code').value;
...
here when I clicked the button, this promocode will fetched to promocode variable.
Here in the main form, I have a hidden field
<%= hidden_field_tag :promo_code, '' %>
I want to pass the promo_code to my controller, I write this line inside the controller:
$("#promo_code").val(promocode);
Then problem come, when I want to fetch the data in controller,
aaa = params[:promo_code]
It give me a "", I don't understand, since I checked the $("#promo_code").val( ) in view, it shows the correct data, but when I checked the controller, it is not passed;
I have stacked here for a day, I know I am a new guy in ROR, but I just can't find the problem...

If I had to venture a guess then the issue is probably that you have the same id for both the inputs on the page.
Clients must return the first element in the DOM in the case of duplicate ids when you call document.getElementById and document.querySelector.
Thus the line $("#promo_code").val(promocode); is really just changing the value of the first element to its own value. In other words its doing absolutely nothing.
If you instead just use the form property on the button to get the input contained in the same form as the button it will work as intented.
$(document).on('click', '#signupBtn', function(e){
this.form["promo_code"].value = $('#promo_code').val();
e.preventDefault(); // prevents a redirect for the purpose of demonstration.
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="promo_code" value="foobarbaz" type="hidden" />
<form>
<input name="promo_code" value="" />
<button id="signupBtn">Copy code</button>
</form>
And as pointed out by #3limin4t0r form values are submitted using the input name, not the id. So that input would be submitted as params[:promocode] not params[:promo_code].

Related

How to pass hidden field value into my Onclick method on a button in a MVC View

I have a hidden field like this in my view:
#Html.HiddenFor(m => m.Url)
then i have a form in which i'm posting the data via Ajax call like this:
<form id="formdata">
<input class="btn primary" type="submit" value="Submit" onclick="submitForm('#Url.RouteUrl("createAccount/"+ '#Html.HiddenFor(m => m.Url)'+ )'">
</form>
How do i Pass the url from the hidden form into my submit function. I'm not sure if i have to use double quotes or single quotes around it? or is this achievable?
Thank you
HtmlHelper.HiddenFor used for creating hidden field with specified value assigned to viewmodel binder, instead of rendering its value directly. What you need is using Model.Url property to pass viewmodel property into JS function like this:
<input class="btn primary" type="submit" value="Submit"
onclick="submitForm('#Url.RouteUrl("createAccount/" + Model.Url)')">
In case it returns encoded URL containing query string, use Html.Raw() i.e. Html.Raw(Model.Url).
NB: You can use AjaxHelper.BeginForm to submit a form through AJAX as alternative to handling submit button click event & using jQuery.ajax with passed URL.

text displaying in every form field

i'm making an Ember app with a Rails back end. In one of the templates, I list the available teams from a database and beside each team put a form field for the user to enter some textual information. If I enter information in one form field, the text appears in all of the form fields (kind of like a multiple cursor experience). That's one problem. Also, when I submit the button to attend one of the conferences, nothing's happening in the controller. I'm wondering if this is a related problem as Ember might think I'm trying to submit from multiple forms at one time due to the fact that these forms are acting as if they're the same form.
Can you see what I'm doing wrong?
<script type="text/x-handlebars" id="conferences">
<div class='span4'>
{{#each item in model}}
<li> {{#link-to 'conference' item}}
{{ item.name }}
{{ partial 'conferences/form'}}
{{/link-to }}</li>
{{/each}}
</ul>
</div>
<div class="span4 offset4">
{{ outlet}}
</div>
</script>
Inserted Form
<script type="text/x-handlebars" id="conferences/_form">
<form class="form-horizontal" {{action "attend" on="submit"}}>
<div class="controls">
{{input value=username type="text"}}
</div>
<button type="submit" class="btn">attend</button>
</form>
</script>
Conferences controller
App.ConferencesController = Ember.ObjectController.extend({
actions: {
attend: function() {
console.log('this is not logging, & no indication rails route is posted to)
$.post("/join_conference_path", {
username: this.get("username"),
}).then(function() {
document.location = "/";
}, function() {
}.bind(this));
}
}
});
Having all input values synced to the same text happen due to fact that each input value is bound to the same property username.
This happens because all _form partials are rendered in the same context which is in your case App.ConferencesController. To make them render in individual context use itemController argument for each helper. See spec here: http://emberjs.com/api/classes/Ember.Handlebars.helpers.html#method_each
{{#each item in model itemController="conference"}}
In this case I suggest you rename your App.ConferencesController to App.ConferenceController which will represent individual context for each "item". Having it done this way your action will always use username input for specific "item" only.
Action may not trigger because by default all actions targets routes and not controllers. Try to add target="controller" attribute to action helper:
{{action "attend" on="submit" target="controller"}}

how to have two buttons in my view to same action method asp.net mvc

I have two submit buttons which call the same action method. How can I tell which of these buttons was clicked in the formcollection of the action method (without setting the value property of the buttons)?
HTML code for buttons:
<input type="submit" name="button" />
<input type="submit" name="button" />
Action method as:
public ActionResult submitted(FormCollection form)
{
}
i know how to do if we have a value property, but I just want to try like this without value property. How can this be done?
thanks,
michaeld
The best thing to do, is intercept the click action to set a hidden form variable before the form is submitted, e.g.:
<script language="text/javascript">
$("form input[submit]").click(function() {
$("#buttonSelected").val("some unique value here");
});
</script>
Where you might have a hidden input:
<input type="hidden" id="buttonSelected" name="buttonSelected" />
That way, you can then check the specific "buttonSelected" form value to figure out which button was pressed.

ASP.NET MVC Ajax.BeginForm eats params of submit button clicked. Looks like bug

If you are using Ajax.BeginForm() with multiple submit buttons similar to this:
// View.aspx
<% using (Ajax.BeginForm("Action", "Controller",
new AjaxOptions { UpdateTargetId = "MyControl", }))
{ %>
<span id="MyControl">
<% Html.RenderPartial("MyControl"); %>
</span>
<% } %>
//MyControl.ascx
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<input name="prev" type="submit" value="prev" />
<input name="next" type="submit" value="next" />
//...
Everything is submitted to the controller fine but the params for the submit button that was clicked are absent from the Request. In otherwords Request["next"] and Request["prev"] are always null.
I looked in to the JavaScript in Microsoft.MvcAjax.js and it looks like the function Sys_Mvc_MvcHelpers$_serializeForm completely skips over the inputs that are of type 'submit'.
This doesn't seem logical at all. How else can you find out what button has been clicked?
It looks like a bug to me. Is there any logical reason to skip these form parameters?
UPDATE: 2009-11-21
I downloaded MVC Release 2 Preview 2 and looked to see if this problem was fixed.
I did a quick test and found similar results to MVC Release 2 Preview 1.
I don't believe it is fixed yet.
UPDATE: 2009-08-07
I downloaded MVC Release 2 Preview 1 and looked to see if this problem was fixed.
I see a new function in the script MicrosoftMvcAjax.debug.js called _serializeSubmitButton and I see that when Ajax.BeginForm() renders the output there is a onclick event but when this event fires it generates an error "Microsoft JScript runtime error: 'Sys.Mvc.AsyncForm' is null or not an object".
In short it looks like a fix was attempted but it isn't working yet or I need to do something more. The bad news is if it isn't the later then Ajax Forms will be broken for everyone until the fix is complete.
UPDATE: 2009-05-07
I received feedback today from Microsoft confirming that this is a bug. They have logged the defect and said they hope to have it fixed in a future release.
For reference I'm leaving the details of my investigation that I submitted to Microsoft. Appologies for the long post but perhaps it will be useful for anyone trying to create a work around..
There are a couple problems in the Ajax support in MVC. To illustrate, consider the pattern illustrated in several examples on the web:
//===========
// View.aspx
//===========
<% using (Ajax.BeginForm("Action", "Controller",
new AjaxOptions { UpdateTargetId = "MyControl", HttpMethod = "POST"}))
{ %>
<span id="MyControl">
<% Html.RenderPartial("MyControl"); %>
</span>
<% } %>
//================
// MyControl.ascx
//================
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<input name="startIndex" type="hidden" value="0" />
<%= Ajax.ActionLink("Prev", "PrevAction",
new AjaxOptions() { UpdateTargetId="MyControl", HttpMethod="POST"}) %>
<%= Ajax.ActionLink("Next", "NextAction",
new AjaxOptions() { UpdateTargetId="MyControl", HttpMethod="POST"}) %>
//...
Expected:
It is just a list that can the user can page forward and back without updating the entire page.
Given this setup. I expect 2 links labeled "Prev" and "Next". Clicking on "Prev" should fire the PrevAction method in the controller as a post and the value in the hidden field named "startIndex" should be available in the request parameters. I expect similar results when clicking the Next link.
Actual:
The reality is that the request object contains NONE of the form parameters even though it shows that it came in as a POST.
In order to get any of the parameters using action link they must be explicitly supplied through the variation of ActionLink that includes parameters. When this is used the parameters become part of the URL of the link which defeats the purpose of having a POST.
So why is the javascript wrong?
I dug into the javascript code that is used to handle the submit for the example I posted with my question and I now better understand why it doesn't handle it. The reason appears to be related to the way they have wired up events and what I believe is a shortcoming in Internet Explorer.
The way it currently works is that the Ajax.BeginForm() helper class generates a form tag with an onsubmit() function to intercept the form submit event. When the user clicks on a submit button the onsubmit() function fires and recieves parameters, one of which is the event.
The MicrosoftMvcAjax scripts look at the event, bundle up the form properties that are supposed to be submitted and sends the request off to the server. The problem is that per WC3 standards only the successful controls are supposed to be posted. In the case of submit buttons this is the button that was actually clicked. Under internet explorer there is no way to determine which button actually caused the submit event to fire so the script just skips all submit buttons.
(In Firefox the event contains a property called "explictOriginalTarget" which points to the button that actually caused the event in the first place)
Whats the fix?
Microsoft should be fixing it. However if we need something sooner I believe the only option is to hack the MicrosoftMvcAjax scripts to wire up events differently. I have found that the form can be wired to a handle a mousedown event where the button clicked can be saved in a global variable where the onsubmit handler can insert it into the post parameters.
Here is some code that I was testing to illustrate this technique. I have confirmed it works in both IE8 and FireFox but I haven't tried to hack it into the MVC Ajax scripts yet... If I get more time. I may post the results here.
<script type="text/javascript">
var _clicked = "";
function onSubmit(e) {
var targ;
if (!e) var e = window.event;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ.nodeType == 3) //defeat Safari bug
targ = targ.parentNode;
alert("OnSubmit:" + _clicked + " was clicked.");
return false;
}
function Click(e) {
var targ;
if (!e) var e = window.event;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ.nodeType == 3) //defeat Safari bug
targ = targ.parentNode;
_clicked = targ.name;
return true;
}
<form action="/Home/StandardForm" method="post"
onsubmit="onSubmit(event)" onmousedown="Click(event)">
<input type="submit" name="StdPrev" value="StdPrev" />
<input type="submit" name="StdNext" value="StdNext" />
</form>
In order for your submit buttons to be "successfull" controls as per the specification, they must be defined within the form element:
http://www.w3.org/TR/html401/interact/forms.html#successful-controls
If you can't nest your submit buttons inside your form, you'll probably need to use javascript (or jquery) to submit your form and pass in an additional paramater to indicate which button was clicked.
I suppose this has been fixed in MVC 2 (or it was never broken). Just make sure your HTML markup validates. The following example should show it works.
Vote.aspx:
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Vote</title>
</head>
<body>
<%using (Ajax.BeginForm("Vote", "Voting", new AjaxOptions { UpdateTargetId = "message" }))
{ %>
<%= Html.Hidden("itemId", "1")%>
<p>I love ASP.NET MVC!</p>
<input type="submit" name="voteValue" value="+" />
<input type="submit" name="voteValue" value="-" />
<%} %>
<p id="message"><%= TempData["message"] %></p>
<script type="text/javascript" src="<%= Url.Content("~/Scripts/MicrosoftAjax.js")%>"></script>
<script type="text/javascript" src="<%= Url.Content("~/Scripts/MicrosoftMvcAjax.js")%>"></script>
</body>
</html>
VotingController.aspx:
using System.Web.Mvc;
namespace Examples.FormWithMultipleSubmitButtons.Controllers
{
public class VotingController : Controller
{
public ViewResult Vote()
{
return View();
}
[HttpPost]
public ActionResult Vote(int itemId, string voteValue)
{
switch(voteValue)
{
case "+":
TempData["message"] = "You voted up.";
break;
case "-":
TempData["message"] = "You voted down.";
break;
default:
TempData["message"] = "Your vote was not recognized.";
break;
}
if(Request.IsAjaxRequest())
{
return Content(TempData["message"].ToString());
}
else
{
return View();
}
}
}
}
I had the same issue today (Oct 8, 2010) with my form with multiple submit buttons. The HTML didn't validate. I cleaned it up. It's still doesn't validate (but less error than the original) and now the value of clicked button is submitted.
A possible workaround could be to have each button in a seperate form routed to different actions on your controller.
Not ideal but could work.
I did the following:
<input id="btnSubmit" name="btnSubmit" type="hidden" value="" />
<input type="submit" name="btnSubmit" value="Delete" id = "btnDelete" onclick="$('#btnSubmit').attr('value','Delete');"/>
<input type="submit" name="btnSubmit" value="Save New" id = "btnSaveNew" onclick="$('#btnSubmit').attr('value','Save New');"/>
<input type="submit" name="btnSubmit" value="Save" id = "btnSave" onclick="$('#btnSubmit').attr('value','Save');"/>
i.e. defined a hidden input type with id of "btnSubmit" and on each button added the onclick event as onclick="$('#btnSubmit').attr('value','Delete');". this seems to work
as I was able to get the value of the button clicked in the controller:
public ActionResult SaveCreateBlot(string btnSubmit)
{
}

How to prevent auto filling posted values in asp.net mvc ajax form

Inside of an asp.net mvc partial view, I have an Ajax form that posts a value and replaces the contents of its parent container with another instance of the form.
Index.aspx view:
<div id="tags">
<% Html.RenderPartial("Tags", Model); %>
</div>
Tags.ascx partial view:
<% using(Ajax.BeginForm("tag", new AjaxOptions { UpdateTargetId = "tags" }))
{ %>
Add tag: <%= Html.TextBox("tagName")%>
<input type="submit" value="Add" />
<% } %>
The controller:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Tag(string tagName) {
// do stuff
return PartialView("Tags", ...);
}
The problem is when the new instance of the form returns, the posted value is already stored in the input field. As in, whatever I posted as the 'tagName' will stay in the textbox. Firebug shows that the value is hardcoded in the response.
Is there any way to clear the input textbox's value when returning the partial view?
I've tried:
<%= Html.TextBox("tagName", string.Empty)%>
and
<%= Html.TextBox("tagName", string.Empty, new { value = "" })%>`
neither of which do anything.
EDIT:
I realize there are js solutions, which I may end up having to use, but I was wondering if there were any ways of doing it in the backend?
I'm not sure if this solution is "good enough" for you, but couldn't you just empty the form in a JS callback function from your ajax call? If you're using jQuery on your site, the callback function could look something like this:
function emptyFormOnReturn() {
$(':input').val();
}
I am not entirely sure if it will, but in case the above code also removes the text on your submit button, change the selector to ':input[type!=submit]'.
yes you should use jquery to set values on response
if you change your code to use jquery for ajax operations, you can call you settingvalues function on success callback...example:
http://docs.jquery.com/Ajax/jQuery.ajax#options

Resources