Value of element created in JS required in Spring MVC controller - javascript

I created an input tag inside the javascript, and I also provide the attribute name to it,
var tdTotalEmployees = row.insertCell(k++);
tdTotalEmployees.innerHTML = rowData.totEmployees !== null ? '<h4>' + rowData.totEmployees + '</h4><input type="hidden" name="migrationRef" value=' + rowData.migrationReference + '>' : ' ------ ';
Now as usual, I need this variable value in my controller, I used #RequestParam("migrationRef")String migrationRef
it didn't work,
I used SOUT on request.getParameter("migrationRef"), it displays null. means no value supplied from, but when I inspect the element, I clearly see the value of this element
#RequestMapping(value = "/employee_details")
private ModelAndView getEmployeeList(HttpServletRequest request) {
ModelAndView mav = new ModelAndView("migrate_salary_hr/pre_migration_emp_list");
HttpSession session = request.getSession();
Userdetail loginUser = (Userdetail) session.getAttribute("loginUser");
System.out.println("migration ref no" +request.getParameter("migrationRef") );
try {
mav.addObject("yearMonth", request.getParameter("ym"));
mav.addObject("status", request.getParameter("s"));
mav.addObject("historyList", request.getParameter("h"));
if (loginUser.getEmployee().getRegion().getRegionId() != null && loginUser.getEmployee().getCircle() != null) {
mav.addObject("Region", loginUser.getEmployee().getRegion().getRegionId());
mav.addObject("circle", loginUser.getEmployee().getCircle().getCircleId());
} else {
mav.addObject("Region", loginUser.getEmployee().getRegion().getRegionId());
}
mav.addObject("orderBy", OrderByMap.PREMIGRATIONEMPLIST_ORDERBY);
} catch (Exception e) {
e.printStackTrace();
}
return mav;
}
kindly suggest me the best solution.

The value of the hidden input migrationRef is not sent to the server when one click on the link. That's why you don't see it server side.
I can see two ways to solve this :
Either add the parameter migrationRef into the href attribute of your link, and remove the useless <input type="hidden" ...
Or, if you really don't want to see the parameter migrationRef in the URL, you have to POST it using a form. In this scenario, the action attribute of the form should be of the like action="../emp_list_sm/employee_details?ym=...&s=...&h=...". Then in the Spring MVC controller you will have to use #ModelAttribute in place of #RequestParam on a Java Bean that has a migrationRef attribute.

I think workaround will be create form element and onclick of anchor trigger form submit. This will enable you to post all the information.
<form action="/{you-url}">
<a id="go" href="#" target="_blank"/>click here</a>
<input type="hidden" name= "ym" value = "+rowData.yyyymm+"/>
<input type="hidden" name="s" value="false"/>
<input type="hidden" name="h" value = "true"/>
<input type="hidden" name="migrationRef" value=' + rowData.migrationReference + '/>
<input type="submit"style="display:none"/>
<script>
document.querySelector("#go").onclick = function(){document.querySelector("input[type='submit']").click()};
</script>
</form>

Related

Calling jQuery code in razor block of code

I have a problem where I need to call jQuery code to fetch a value from an HTML element like following:
#using (Html.BeginForm("Login", "Home",new { Checked = $('#checkbox5').checked }, FormMethod.Post,new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
}
Note that besides passing the entire model into my Login action I'm trying to pass an optional parameter named "Checked". This parameter basically states whether the "remember me" checkbox has been checked on the form or not.
The checkbox itself is not the one that .NET uses by default like:
#Html.CheckboxFor(somepropertyhere);
But instead a regular checkbox like this:
<input id="checkbox5" type="checkbox">
<label for="checkbox5">
Remember me?
</label>
How can I fetch this checkbox's value when passing it as an extra parameter besides my model?
So that my method in the end would look like:
Public ActionResult Login(bool Checked, LoginViewModel model)
{
// To have the checked value here now...
}
P.S. And I can't use Html.CheckboxFor for some reasons, but I don't wanna get too much into details since the question wouldn't make sense then (maybe it doensn't even now I'm not sure if this is doable what I'm trying to achieve).
Can someone help me out?
You can get checkbox value in Controller using Checkbox Field name like this :
bool isRememberMe=Request.Form["CheckBoxName"];
if you want to send any variable, you should set name for field, and on serverside you can call it with name
<input id="checkbox5" type="checkbox" **name="checkbox_name"** value="true">
<label for="checkbox5">
Remember me?
</label>
on server side
Public ActionResult Login(bool checkbox_name = false, LoginViewModel model){
// To have the checked value here now...
}
You can't use JavaScript within a Razor block, because they run at entirely different times. The Razor code runs server-side, long before the response is ever sent to the client. JavaScript runs client-side, only after the server has sent its response to the client, and Razor has already done its work.
On first load, the value of your checkbox will always be the default, which in your case is false. That's why none of the other answers help you. The user would have to interact with the checkbox and submit the form first, and then the checkbox would have that user-set value within the post action that handles the form. If you returned to the form, because of an error, then you could utilize the checkbox value.
To actually alter the form action without posting first, you'd have to handle the click event of the checkbox and manually change it via JavaScript. However, that's extremely brittle. If you want the value of the checkbox on post, then just bind it to something your action accepts. For example:
#Html.CheckBox("checked", Request["checked"] as bool? ?? false)
Then:
[HttpPost]
public ActionResult MyPostAction(MyClass model, bool checked)
I really don't understand why you don't want to use a new property model for the RememberMe value, but I think this might work for you:
Assuming your View looks like this:
#using (Html.BeginForm("Login", "Home", FormMethod.Post, new { #class = "form-horizontal", role = "form", id = "login-form" }))
{
#Html.AntiForgeryToken()
<div class="form-group">
#Html.LabelFor(x => x.Username, new { #class = "form-control" })
#Html.TextBoxFor(x => x.Username, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(x => x.Password, new { #class = "form-control" })
#Html.PasswordFor(x => x.Password, new { #class = "form-control" })
</div>
<div class="form-group">
<input id="checkbox5" type="checkbox">
<label for="checkbox5">Remember me?</label>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Login</button>
</div>
}
And assuming your Controller looks like this:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginViewModel model, bool rememberMe)
{
// Do something with 'rememberMe'
// Do something with 'model'
return RedirectToAction("Index");
}
Then you must need a Javascript like this in your login view to replace the form action before the submit event was completed:
$(function () {
var form = $("#login-form");
var checkbox5 = $("#checkbox5");
form.submit(function () {
var checked = checkbox5.is(":checked") ? "true" : "false";
var action = updateQueryStringParameter(form.action || '', "rememberme", checked);
form.attr('action', action);
});
// stolen from http://stackoverflow.com/a/6021027/1605778
function updateQueryStringParameter(uri, key, value) {
var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
if (uri.match(re)) {
return uri.replace(re, '$1' + key + "=" + value + '$2');
}
else {
return uri + separator + key + "=" + value;
}
}
});
Let me know if this works for you.
Just to give more context: when you have a parameter of a primitive type (like bool or int) in your action, MVC expects this parameter in the Url; but the values of the Complex Types (like LoginViewModel) should pass as a Request Body in the HTTP POST. So if you want to pass both (complex and primitive) you need to be careful to pass all primitive types in the url and the values of complex types in the request body.
The POST of the Login Form could looks like:
POST /Home/Login?rememberMe=false
username=admin&password=secret

How to pass a value to razor variable from javascript variable?

How to pass a value to razor variable from javascript variable, is it possible asp.net mvc razor view engine?
#{
int a = 0;
}
<script>
var b = ...
#a = b;
</script>
You can't. and the reason is that they do not "live" in the same time.
The Razor variables are "Server side variables" and they don't exist anymore after the page was sent to the "Client side".
When the server get a request for a view, it creates the view with only HTML, CSS and Javascript code. No C# code is left, it's all get "translated" to the client side languages.
The Javascript code DOES exist when the view is still on the server, but it's meaningless and will be executed by the browser only (Client side again).
This is why you can use Razor variables to change the HTML and Javascript but not vice versa. Try to look at your page source code (CTRL+U in most browsers), there will be no sign of C# code there.
In short:
The server gets a request.
The server creates or "takes" the view, then computes and translates all the C# code that was embedded in the view to CSS, Javascript, and HTML.
The server returns the client side version of the view to the browser as a response to the request. (there is no C# at this point anymore)
the browser renders the page and executes all the Javascript
But it would be possible if one were used in place of the variable in #html.Hidden field.
As in this example.
#Html.Hidden("myVar", 0);
set the field per script:
<script>
function setMyValue(value) {
$('#myVar').val(value);
}
</script>
I hope I can at least offer no small Workaround.
Okay, so this question is old... but I wanted to do something similar and I found a solution that works for me. Maybe it might help someone else.
I have a List<QuestionType> that I fill a drop down with. I want to put that selection into the QuestionType property on the Question object that I'm creating in the form. I'm using Knockout.js for the select binding. This sets the self.QuestionType knockout observable property to a QuestionType object when the user selects one.
<select class="form-control form-control-sm"
data-bind="options: QuestionTypes, optionsText: 'QuestionTypeText', value: QuestionType, optionsCaption: 'Choose...'">
</select>
I have a hidden field that will hold this object:
#Html.Hidden("NewQuestion.QuestionTypeJson", Model.NewQuestion.QuestionTypeJson)
In the subscription for the observable, I set the hidden field to a JSON.stringify-ed version of the object.
self.QuestionType.subscribe(function(newValue) {
if (newValue !== null && newValue !== undefined) {
document.getElementById('NewQuestion_QuestionTypeJson').value = JSON.stringify(newValue);
}
});
In the Question object, I have a field called QuestionTypeJson that is filled when the user selects a question type. I use this field to get the QuestionType in the Question object like this:
public string QuestionTypeJson { get; set; }
private QuestionType _questionType = new QuestionType();
public QuestionType QuestionType
{
get => string.IsNullOrEmpty(QuestionTypeJson) ? _questionType : JsonConvert.DeserializeObject<QuestionType>(QuestionTypeJson);
set => _questionType = value;
}
So if the QuestionTypeJson field contains something, it will deserialize that and use it for QuestionType, otherwise it'll just use what is in the backing field.
I have essentially 'passed' a JavaScript object to my model without using Razor or an Ajax call. You can probably do something similar to this without using Knockout.js, but that's what I'm using so...
I see that this problem was discussed some time ago, but if anyone 'll meet with this again, here is my solution:
In your *.cshtml View file:
<script>
var data = JsFunction("#Html.Raw(Model.Path)");
$(function () {
$("#btn").click(function () {
var model = { Id: '#Html.Raw(Model.Id)', Data: data }
$.ajax({
type: "POST",
url: "/Controller/Action",
data: model,
datatype: "html",
success: function() {
console.log('Success');
}
});
});
});
</script>
JavaScript variable model is something that I need to pass to Razor ViewModel.
It can be done with ajax request.
You just need to have proper argument/s in your action, that matches Json object created in JavaScript.
Hope it'll help someone!
Step: 1 Your Html,
First Store the value in your localstorage using javascript then add the line like below ,this is where you going to display the value in your html, my example is based on boostrap :
<label for="stringName" class="cols-sm-2 control-
label">#Html.Hidden("stringName", "")</label>
Step:2 Javascript
$('#stringName').replaceWith(localStorage.getItem("itemName"));
here is my solution that works:
in my form i use:
#using (Html.BeginForm("RegisterOrder", "Account", FormMethod.Post, new { #class = "form", role = "form" }))
{
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
#Html.HiddenFor(m => m.quantity, new { id = "quantity", Value = 0 })
}
in my file.js I get the quantity from a GET request and pass the variable as follows to the form:
$http({
method: 'Get',
url: "https://xxxxxxx.azurewebsites.net/api/quantity/" + usr
})
.success(function (data){
setQuantity(data.number);
function setQuantity(number) {
$('#quantity').val(number);
}
});
Yes You Can
Asp.net MVC razor
I have 2 Input
<input id="TXTCount" type="number" readonly="readonly" class="form-control text-center text-bold" step="1" min="0" max="10000" value="1" inputmode="numeric" />
<input id="TXTTOTal" type="number" readonly="readonly" class="form-control text-center text-bold" step="1" min="0" max="10000" value="1" inputmode="numeric" />
C# In view
#{string WatsMSG = "xxx";}
And WhatsApp Link
<a class="btn btn-success" id="WatsSendApi" href="https://api.whatsapp.com/send?phone=0000&text=#WatsMSG">
<b class="text-black" style="font-size:small"> whatsapp </b><i class="fa fa-whatsapp" style="color:white"></i> </a>
And In jQuery
<script>
$("#WatsSendApi").click(function () {
var StringMSG;
StringMSG=("Ineed : ");
StringMSG += (" Item Name : ");
StringMSG +='#item.ITName' ;
StringMSG += (" Count: ");
StringMSG += $('#TXTCount').val();
StringMSG += (" Price: ");
StringMSG += '#item.ITPrice';
StringMSG += (" Total: ");
StringMSG += $('#TXTTOTal').val();
alert(StringMSG);
this.href = this.href.replace("xxx", StringMSG);
});
</script>
I am passing script value And Model value to C# string
Razor View Server Side variable can be read to Client Side JavaScript using #
While
and JavaScript client side variable can read to Razor View using #:

Passing additional value to Controller method - Razor/MVC 5

Hello I am having some trouble figuring out how to pass an additional value to my Controller's Delete method.
I have a form with a Delete button (auto-generated MVC).
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-sm btn-danger" />
<button onclick="location.href='#Url.Action("Index", "Admin")';return false;" class="btn btn-sm btn-primary" style="font-size:10px">Admin</button>
</div>
}
But I want to send along an additional value, this value would be the result of getCookie("username");
I have tried making another input and calling it.
<input type="text" name="userid" value="getCookie('username')" />
The problem is that this always shows "null" within my Controller method.
The method is
// GET: /Admin/Delete/5
public ActionResult Delete(int? id, string userid)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
User user = db.Users.Find(id);
if (user == null)
{
return HttpNotFound();
}
return View(user);
}
and
// POST: /Admin/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id, string userid)
{
User user = db.Users.Find(id);
db.Users.Remove(user);
db.SaveChanges();
var time = new DateTime();
string text = time + ": User " + user.name + " was deleted.";
System.IO.File.AppendAllText(pathway, text + Environment.NewLine);
return RedirectToAction("Index");
}
All I want is to have the value of getCookie('username'); passed on to a method as userID.
Any help appreciated!
What you would want to do is have getcookie() set the value (using jQuery, or whatever) of the userId instead of returning it. You'd need to call this on page load. That would put the value in the DOM/form, so it posts to your controller action.
That said, can't you just access the cookies in your action from the Request object?

woocommerce POSTing data before javascript (jQuery) finishes

i have a custom gateway (which works perfectly), the problem is when a customer buys something for the first time, there is some token than needs to be generated with the card info, the thing is that just before that token is generated, the form tries to submit, but an error is displayed saying that "the object could not be found", so, no refresh and nothing, if i press again the submit button (or "place order" button) everything works!.
i believe that by that second time, the token is generated and in the corresponding hidden field:
here is my code, hope somebody could help me :S
HTML (from the chrome inspector):
<input type="hidden" name="card-name" data-conekta="card[name]">
<input type="hidden" name="exp-month" data-conekta="card[exp_month]">
<input type="hidden" name="exp-year" data-conekta="card[exp_year]">
<input type="hidden" name="conektaTokenId" value="">
<input type="hidden" name="conektaCustId" value="false">
Javascript
jQuery(window).load(function() {
var form;
var first_name;
var last_name;
var cvc;
jQuery('form[name="checkout"]').submit(function(event) {
jQueryform = jQuery(this);
Conekta.setPublishableKey(jQuery('input[name="pbkey"]').val());
console.log('entro');
if( jQuery('input[name="conektaCustId"]').val()=="true" && jQuery('input[name="conektaTokenId"]').val().substr(0,4)!="tok_"){
console.log('entro');
first_name = jQuery('#billing_first_name').val();
last_name = ' ' + jQuery('#billing_last_name').val();
expiry = jQuery('#conekta_card-card-expiry').val().replace(/ /g, '').split("/");
jQuery('input[name="card-name"]').val( first_name + last_name );
jQuery('input[name="exp-month"]').val( Number(expiry[0]));
jQuery('input[name="exp-year"]').val( Number(expiry[1]));
jQueryform.prepend('<span class="card-errors"></span>');
Conekta.token.create(jQueryform, conektaSuccessResponseHandler, conektaErrorResponseHandler);
woocommerce_order_button_html
return false;
}
else{
return;
}
});
var conektaSuccessResponseHandler= function(response){
var token_id = response.id;
jQuery('input[name="conektaTokenId"]').val(token_id);
}
var conektaErrorResponseHandler= function(response){
jQueryform.find('.card-errors').text(response.message);
}
});
i have found the solution, you have to add the class processing to the checkout form and just when you finished procesing your data to be send to wherever you need to (usually wordpress/woocommerce), remove that class so the form can submit the new data.

Dynamically duplicated forms disappear on CodeIgniter reload

I have the following code that needs to be duplicated:
<form method="post">
<div id="field-row-container">
<div id="field-row-1" class="field-row">
<div class="field-element">
<label for="Name[1]">Name</label>
<input type="text" id="Name[1]" name="Name[]" />
</div>
<div class="field-element">
<label for="Email[1]">Email</label>
<input type="text" id="Email[1]" name="Email[]" />
</div>
<hr/>
</div>
</div>
<div class="form-element">
<input type="button" class="confirm add-field-row" value="Add" />
<input type="button" class="danger delete-field-row" value="Delete" />
<input type="submit" />
</div>
The duplicated / dynamically added elements will have the same names of Name[] and Email[] but their ID's will be incremented.
The JavaScript is below, based from Josiah Ruddell's form duplication script.
var template = $('#field-row-container #field-row-1').clone();
window.addForm = function () {
var parent = $(this).closest('.dynamic-rows').attr('id');
var fieldRowCount = countRows(parent) + 1;
var newFieldRow = template.clone().find(':input').each(function () {
var newId = this.id.substring(0, this.id.length - 3) + "[" + fieldRowCount + "]";
$(this).prev().attr('for', newId); // update label for
this.id = newId; // update id and name (assume the same)
$(this).closest('.field-row').addClass('new-row');
}).end()
.attr('id', 'field-row-' + fieldRowCount)
.appendTo('#field-row-container');
}
$('.add-field-row').click(addForm);
Whenever I submit the form to CodeIgniter and if there is a validation error, once the controller reloads the multi-part form, the dynamically added elements disappear as well as the values in the initial fields.
How do I go around this problem? I'm at a loss on how to solve this...
Other notes that might help:
This is a component multi-part form with only one form controller
I have multiple instances of this - Addresses, Education Degrees and such
I use CodeIgniter's form_validation library to check server-side each array of posts
When the page with the form on reloads after the controllers redirects back to it after failing validation, it will only reload the original page, with no DOM manipulations applied.
I would perform the POST request which submits the form via ajax, so you can handle the response without leaving the page. Something like this:
$.post('/locationOfController.php', $('#yourForm').serialize(), function(response){
if(response.valid){
window.location.href = '/somewhereAfterFormPosted.php';
} else {
$('#yourForm').append("<p>"+response.error+"</p>");
}
}, 'json');
and change the controller to return a JSON object based on whether validation passed or not. To match up with my example above, you would return something like below when an error occurs:
{valid: false, error: 'Please fill out the whole form'}
Try something like that as a basic example. You could do much more, such as returning several errors if multiple fields are invalid.

Categories

Resources