I have a simple Asp.Net MVC app. I have a form, which I'm trying to gather data for, and then submit. However, within that form is a list of selections - each time a selection is made, I go to the server to add that data:
function addSelection(item) {
fetch("/test/selection/" + item,
{
method: "POST"
})
.then(response => {
const name = document.getElementById('Name').value;
localStorage.setItem("name", name);
if (response.ok) {
location.reload();
} else {
console.error("Unable to add");
}
});
}
The server then stores the list in a HttpContext.Session variable.
The target is to keep the name property in place across calls. The code above works great - I set the control on load:
window.onload = function() {
var getName = localStorage.getItem('name');
document.getElementById('Name').setAttribute('value', getName);
}
However, the form itself is eventually submitted, and the entire form, with the selected items, is submitted to the server:
<div>
<input type="submit" value="Submit"
asp-controller="My" asp-action="Create"/>
</div>
The problem that I have is that the local storage still retains the value of name, and so the next time the form is loaded, it's still there. Does anyone have any techniques for achieving the same result without using local storage?
The only solution that I can think of so far is to replace the submit button with a manually coded JS script that resets the value, but that doesn't account for situations where the user just moves away from the form. I feel like I'm heading down a rabbit hole of my own making, and there must be a simpler way to do the same thing.
One solution is to use hidden form fields to persist the data between requests instead of local storage. On each item selection, add the data to a hidden form field on the client-side instead of saving it to local storage. Then, when the form is submitted, the hidden form field value will be included in the form data and can be retrieved on the server-side.
On the server-side, you can retrieve the NameValue from the form data in your action method.
[HttpPost]
public IActionResult Create(string NameValue, ...)
{
...
}
Related
I am trying to set ViewBag.OrderId to the value of the data attribute data-orderId, but I am getting a syntax error on the =:
#foreach (var order in Model.Orders)
{
<a class="btn-add-note" data-orderId="#order.db_OrderNo">Add</a>
}
JS:
$(".btn-add-note").click(function(){
#ViewBag.OrderId = $(this).attr("data-orderId");
});
Anyone know why I am getting this syntax error?
Explanation:
The code shown here is in a partial view. Once clicked, it opens up a modal in it's parent view. The modal has a form in it that requires the selected orderId from the partial view. The orderId is then passed as a parameter into the controller on form submit. I have been having trouble figuring out the best way to do this so I was trying to just set ViewBag.OrderId to the value so I wouldn't have to try to pass it to the form first.
Let me know if that's confusing at all or if more details are needed.
Thanks!
What you are trying to do will not work; #ViewBag.OrderID will have already rendered before that JS code works. You have to evaluate everything on the client, and if you need to access it on the server, store the value in a hidden field or send it to the server using AJAX.
Please provide some more info on what you are trying to do and we can help further.
You can't mix server side and client side code.
What you can do however, is have a hidden field that you store your OrderId in, and then retrieve once you load your modal.
In your view add a hidden field
<input type="hidden" id="orderId" value="" />
Then just set it as you were trying to do with ViewBag
$(".btn-add-note").click(function(){
$('#orderId').val($(this).attr("data-orderId"));
});
Now you can grab the OrderId from the hidden wherever you need it.
If you need the OrderId on the controller to load the form, just add a controller action for setting the ViewBag property
[HttpPost]
public void SetOrderId(string orderId)
{
ViewBag.OrderId = orderId;
}
Then make your click event call this action instead
$(".btn-add-note").click(function(){
$.ajax({
url: '#Url.Action("SetOrderId", "ControllerName")',
type: 'POST',
data: { orderId = $(this).attr("data-orderId") }
});
});
I'm actually running into little problems with my current project. Following case:
I've got a model called "Posting" with relations:
public function subscribers(){
return $this->belongsToMany('User');
}
In my view-file there is a table containing all Postings and also a checkbox for subscribing/unsubscribing with the matching value to the posting-id:
<input class="click" type="checkbox" name="mobileos" value="{{{$posting->id}}}"
#if($posting->subscribers->find(Auth::User()->id))
checked="checked"
#endif
>
Now the thing I want to archive:
A JavaScript is going to watch if the checkbox is checked or not. According to that, the current user subscribes/unsubscribes to the posting. Something like:
$('.click').on('click',function() {
// $posting->find(---$(this).prop('checked')---)->subscribers()->attach(---Auth::user()->id---);
// $posting->find(---$(this).prop('checked')---)->subscribers()->detach(---Auth::user()->id---);
});
Is there any possibility to archieve that or any other ways? I couldn't get my head around this so far.
Cheers,
Chris
If you want to use Ajax to achieve this, you will need a REST endpoint in Laravel for the subscriptions, e.g.:
http://localhost/subscribe/{{userid}}
When this Endpoint is called, the database can be updated. The function could also return a JSON showing, if the saving database in the database successful.
Use this endpoint to make an Ajax Call on click:
var user = {
id: 0 // retrieve the correct ID from wherever it is stored
}
$('.click').on('click',function() {
$.GET('http://localhost/subscribe/' + user.id,
function () { // this is the success callback, that is called, if the Ajax GET did not return any errors
alert('You are subsribed')
});
});
Ideally you won't be using the GET method, but instead use POST and send the user ID as data. Also you would need to retrieve the user ID from session or wherever it is stored.
Take care that as you are using Ajax it can easily be manipulated from the client side. So on the server you should check, if the user ID that was sent is the same as in the Session. Maybe you don't need to send the user id at all, but that depends on how your backend is built.
I have a form that I'm submitting using javascript. However, one of the checks it does uses a php script that queries an API and gets a user's password. This is for the purposes of form validation (i.e. if password doesn't match what we have on file..)
I'm using a php script to decode the password like this
function submitForm() {
var options = {
decoded_password: '<?php echo abc_decode($contactInfo['Password'])?>',
}
if (jQuery('#current_password').val() != options.decoded_password && $psc('#current_password').val()) {
render_alert('Your current password does not match what we have on file.');
return false;
} else {
$psc('#account-information').submit();
document.getElementById("account-information").reset();
}
Page loads, great, submit form, great. However, the variable is remembered from the first page load, so if I try to change the password again, it says my password doesn't match what is on file. If I reload the page, no problem.
Is there any way to change the value of $contactInfo['Password'] in javascript without a page reload?
You could try making an AJAX call instead. This won't require a page reload, but will still give you the opportunity to send the data back to the server. If you store the data in the $_SESSION variable it will persist across multiple calls.
I have an HTML form to update the address in the account that submits to a Java servlet.
The problem is that, the form should not accept free flowing address text. Instead the user should enter the zip code/house number/street name, and hit a search button.
This search needs to go to a webservice, perform authentication and get a list of valid addresses that match the search criteria.
This list of addresses should be displayed to the user in the same form (either unhide a hidden element or use a modal dialog), so the user can pick his address.
Only after the valid address is picked, the user should be able to hit the form submit button which sends the data back to the servlet.
I am not sure how to have these 2 buttons do different actions in the form. I am very new to JavaScript and any pointers or examples are much appreciated.
For your webservice build an output of the values based on a search result (a basic string). Put this data in a JSON statement or just a javascript array.
Return something that looks like this.
['SearchResult1', 'SearchResult2', 'SearchREsult3']
On your search box. Bind a function on change or blur.
$('#SearchBox').bind('change', function(){
var val = $(this).val();
//Please reference the Jquery Ajax function as im typing this from memory and i always mix one or two things up :).
$.ajax({
"type" : "post",
"url" : "yoururlhere",
"data" : { "search":val },
success : function(dataset){
//When it comes back here check to see if its valid data etc etc
//After you validate you can populate a picklist on the page with the values. Or do anything you want with the values like this
for(x in dataset){
$('#DocumentElement').append('<p>'+ dataset[x] +'</p>');
}
}
});
});
This should start you out. After that you can just do more things on the callback, or modify the dom in a way which suits you better :).
I have two list boxes. One is populated on Page_Load and the other remains empty.
The user has buttons for adding users from the first list to the second list and back.
When the form is submitted, the second list is empty, like it was when it was sent to the client. Here is the JS code:
function add() {
$('#AvailableUsers option:selected').appendTo('#SelectedUsers');
}
function addall() {
$('#AvailableUsers option').appendTo('#SelectedUsers');
}
function remove() {
$('#SelectedUsers option:selected').appendTo('#AvailableUsers');
}
function removeall() {
$('#SelectedUsers option').appendTo('#AvailableUsers');
}
How do I bring the client-side changes back to the server side?
Edit: Code for server-side:
bool canDismiss = chkCanDismiss.Checked;
string messageText = tbMessageText.Text;
PaymentsDataContext db = new PaymentsDataContext();
foreach (ListItem li in SelectedUsers.Items)
{
UserMessages newMessage = new UserMessages();
newMessage.userName = li.Text;
newMessage.messageText = messageText;
newMessage.dismissed = false;
newMessage.canDismiss = canDismiss;
db.UserMessages.InsertOnSubmit(newMessage);
}
db.SubmitChanges();
You have to append/store those items in the hidden field as well, then you can get the items from the hidden field on the server side.
This is because the changes you made at client side are not available on the server side.
If I read correctly you are trying to use the Users in "Selected Users" Server side. I would have an on form submit client side event that selects all the users in the SelectedUsers list. This eliminates the need for a hidden variable. NOTE use the following in conjunction with your existing jQuery
$(document).ready(function(){
$(form).submit(function(){
$('#SelectedUsers option').attr("selected","selected");
return true;
});
});
EDIT In response to comment: When the selected users control is originally loaded on the page there are no items and nothing selected. With your current code, options are added to the selected users list, on the client side. Currently when the form is submitted these values are not selected and therefore not posted back to the server. To post the values back to the server they need to be selected first. What the above code should do is select the users options in the SelectedUsers list and post the selected values, with the rest of the form, back to the server when the form is submitted.
Edit 2, Server Side Code: You may need to access the values via the Request.Form object. With multiple controls like multiple select boxes, multiple values are passed as a comma separated string.
string rawSelUsers = Request.Form[SelectedUsers.ClientID];
You can the perform a split on this string to break it into an array if needed.