currently I have the following:
$.ajax({
type: 'POST',
url: this.action,
data: $(this).serialize(),
});
This works fine, however I would like to add a value to data, so I tried
$.ajax({
type: 'POST',
url: this.action,
data: $(this).serialize() + '&=NonFormValue' + NonFormValue,
});
But that didn't post correctly. Any ideas on how you can add an item to the serialize string? This is a global page variable that isn't form specific.
While matt b's answer will work, you can also use .serializeArray() to get an array from the form data, modify it, and use jQuery.param() to convert it to a url-encoded form. This way, jQuery handles the serialisation of your extra data for you.
var data = $(this).serializeArray(); // convert form to array
data.push({name: "NonFormValue", value: NonFormValue});
$.ajax({
type: 'POST',
url: this.action,
data: $.param(data),
});
Instead of
data: $(this).serialize() + '&=NonFormValue' + NonFormValue,
you probably want
data: $(this).serialize() + '&NonFormValue=' + NonFormValue,
You should be careful to URL-encode the value of NonFormValue if it might contain any special characters.
Don't forget you can always do:
<input type="hidden" name="NonFormName" value="NonFormValue" />
in your actual form, which may be better for your code depending on the case.
firstly shouldn't
data: $(this).serialize() + '&=NonFormValue' + NonFormValue,
be
data: $(this).serialize() + '&NonFormValue=' + NonFormValue,
and secondly you can use
url: this.action + '?NonFormValue=' + NonFormValue,
or if the action already contains any parameters
url: this.action + '&NonFormValue=' + NonFormValue,
Add the item first and then serialize:
$.ajax({
type: 'POST',
url: this.action,
data: $.extend($(this), {'NonFormValue': NonFormValue}).serialize()
});
We can do like:
data = $form.serialize() + "&foo=bar";
For example:
var userData = localStorage.getItem("userFormSerializeData");
var userId = localStorage.getItem("userId");
$.ajax({
type: "POST",
url: postUrl,
data: $(form).serialize() + "&" + userData + "&userId=" + userId,
dataType: 'json',
success: function (response) {
//do something
}
});
this better:
data: [$(this).serialize(),$.param({NonFormValue: NonFormValue})].join('&')
You can write an extra function to process form data and you should add your nonform data as the data valu in the form.seethe example :
<form method="POST" id="add-form">
<div class="form-group required ">
<label for="key">Enter key</label>
<input type="text" name="key" id="key" data-nonformdata="hai"/>
</div>
<div class="form-group required ">
<label for="name">Ente Name</label>
<input type="text" name="name" id="name" data-nonformdata="hello"/>
</div>
<input type="submit" id="add-formdata-btn" value="submit">
</form>
Then add this jquery for form processing
<script>
$(document).onready(function(){
$('#add-form').submit(function(event){
event.preventDefault();
var formData = $("form").serializeArray();
formData = processFormData(formData);
// write further code here---->
});
});
processFormData(formData)
{
var data = formData;
data.forEach(function(object){
$('#add-form input').each(function(){
if(this.name == object.name){
var nonformData = $(this).data("nonformdata");
formData.push({name:this.name,value:nonformData});
}
});
});
return formData;
}
Related
I have + and - buttons in the cart layout that are changing the value of the quantity input using jQuery.
It works perfectly on the page and in the source code (quantity values changes) but it doesn't work after page refresh and doesn't get reflected on the checkout page.
Changing the quantity manually (with built-in input arrows or by typing the new amount into the field) works normally.
$(".qty-button").on("click", function() {
var $button = $(this);
var oldValue = $button.parent().find("input").val();
var newVal;
if ($button.text() === "+") {
newVal = parseFloat(oldValue) + 1;
} else {
if (oldValue > 0) {
newVal = parseFloat(oldValue) - 1;
} else {
newVal = 0;
}
}
$button.parent().find("input").attr('value', newVal).trigger('change');
});
It changes the value in the page source and is reflected on the cart page but does nothing in terms of functionality as it gets back to the original value on page refresh or checkout.
Any ideas?
Didn't know I need to fire the Shopify Cart API.
In case anyone needs it in the future, fixed with:
<div class="cart-item-block qty-selector">
<div class="qty-button increase" onclick="Shopify.addItem({{ item.variant.id }}, this.parentNode.querySelector('input[type=number]').value)">+</div>
<input id="updates_{{ item.key }}" class="cart-qty-input" type="number"
name="updates[]" value="{{ item.quantity }}" min="1" pattern="[0-9]*"
>
<div class="qty-button decrease" onclick="Shopify.removeItem({{ item.variant.id }}, this.parentNode.querySelector('input[type=number]').value)">-</div>
</div>
<script>
Shopify.addItem = async function(id,quantity){
await $.ajax({
method:'POST',
url:'/cart/change.js',
data:{ id:id, quantity:(++quantity) },
dataType: 'json'
})
};
Shopify.removeItem = async function(id,quantity){
await $.ajax({
method:'POST',
url:'/cart/change.js',
data:{ id:id, quantity:(--quantity) },
dataType: 'json'
})
};
</script>
I have a problem with my controller - it doesn't return a view. I am sending some data to the same controller, creating a new object with this data and I would like to send this object to the Create view but for some kind of reason I am staying on the same page.
View name: Create.cshtml
Controller name: ReservationController
Here is my controller action:
public IActionResult Create(int selectedTime, string selectedDate, int selectedRoomId)
{
TimeSpan time = TimeSpan.Parse($"{selectedTime}:00:00");
DateTime date = DateTime.ParseExact(selectedDate, "MM/dd/yyyy", System.Globalization.CultureInfo.InvariantCulture);
DateTime combine = date + time;
Reservation reservation = new Reservation();
reservation.RoomId = selectedRoomId;
reservation.ReservationTime = combine;
return View(reservation);
}
And my view:
#model Escape.Models.Reservation
#{
ViewBag.Title = "title";
}
<h2>My create reservation view</h2>
This is the original view I am coming from:
#using Escape.Controllers
#model Escape.Models.Room
#{
ViewData["Title"] = "Details";
}
<h4 class="title">Booking for room: #Model.Name</h4>
<div>
<p>#Model.Description</p>
<a class="btn btn-link" asp-action="Index">Back to all rooms</a>
<hr />
</div>
<div>
<input id="datepicker" type="text" name="datepicker"
onchange="onDateChange(#Model.Id)" />
</div>
<div>
<div id="displayTimes"></div>
<a id="btn-create" class="btn btn-sm"></a>
</div>
#section Scripts {
<script>
var dateToday = new Date();
$(function () {
$("#datepicker").datepicker({
minDate: dateToday
});
});
</script>
}
Ajax function on my btn-create:
function onButtonClick(val, date, room) {
var btnBack = document.getElementById("btn-create");
btnBack.innerHTML = "Create reservation";
$(btnBack).addClass('btn-outline-primary');
btnBack.addEventListener("click",
function () {
$.ajax({
type: "GET",
data: { selectedTime: val, selectedDate: date, selectedRoomId: room },
url: "/Reservation/Create",
contentType: "application/json",
dataType: "json"
});
});
}
If the link <a id="btn-create" class="btn btn-sm"></a> is supposed to make a call to the Create method of the ReservationController, then it is incomplete, and this is what you would need to change it to:
<a asp-controller="Reservation"
asp-action="Create"
id="btn-create" class="btn btn-sm">Create</a>
Update:
Your click handler does seem to send a request to the Controller, but nothing happens after that request, and the response (which contains the HTML from the View) is discarded.
Since you want to show the HTML, maybe you shouldn't even be using AJAX, and use my original answer above instead.
If for some reason you need the AJAX, then you need to create a success handler that displays the HTML:
btnBack.addEventListener("click",
function () {
$.ajax({
type: "GET",
data: { selectedTime: val, selectedDate: date, selectedRoomId: room },
url: "/Reservation/Create",
contentType: "application/json",
dataType: "json",
success: function (data) {
// ... put processing here
}
});
}
);
I have successfully designed and implemented Google reCaptcha Version 2 but now my Manager wants that to be of version 1 with numbers to be entered and validated. Is there a way to switch from later to former i.e.- from 2 to 1. I am using following library for reCaptcha:
<script src='https://www.google.com/recaptcha/api.js'></script>
Update..
To implement Captcha inside form i am using following HTML..
<form class="contact_form" action="#" method="post" name="contact_form">
<div class="frm_row">
<label id="lblmsg" />
<div class="clear">
</div>
</div>
<div class="g-recaptcha" data-sitekey="6Lduiw8TAAAAAOZRYAWFUHgFw9_ny5K4-Ti94cY9"></div>
<div class="login-b">
<span class="button-l">
<input type="button" id="Captcha" name="Submit" value="Submit" />
</span>
<div class="clear"> </div>
</div>
</form>
As i need to get the Captcha inside the above form to Validate and get the response on button click but as now i am using <script src="http://www.google.com/recaptcha/api/challenge?k=6Lduiw8TAAAAAOZRYAWFUHgFw9_ny5K4-Ti94cY9"></script> , so not getting the Captcha inside the form ..Please help me to get that ..Also here is the Jquery Ajax code to send the request on Server side code..
$(document).ready(function () {
alert("hii1");
$('#Captcha').click(function () {
alert("Hii2");
if ($("#g-recaptcha-response").val()) {
alert("Hii3");
var responseValue = $("#g-recaptcha-response").val();
alert(responseValue);
$.ajax({
type: 'POST',
url: 'http://localhost:64132/ValidateCaptcha',
data: JSON.stringify({ "CaptchaResponse": responseValue }),
contentType: "application/json; charset=utf-8",
dataType: 'json', // Set response datatype as JSON
success: function (data) {
console.log(data);
if (data = true) {
$("#lblmsg").text("Validation Success!!");
} else {
$("#lblmsg").text("Oops!! Validation Failed!! Please Try Again");
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("Error");
}
});
}
});
});
Please help me ..Thanks..
You have to verify the reCaptcha at "http://www.google.com/recaptcha/api/verify" on Server side.
The parameters of this are:
privatekey: Your Private Key
remoteip: User's IP Address
challenge: Value of input[name=recaptcha_response_field]
response: Value of input[name=recaptcha_challenge_field]
Therefore, you have to post them on your server-side method like this:
cshtml file:
var recaptchaResponseField=$("input[name=recaptcha_response_field]").val();
var recaptchaChallengeField=$("input[name=recaptcha_challenge_field]").val();
// ajax block
$.ajax({
url: '/api/VerifyReCaptcha/', // your Server-side method
type: 'POST',
data: {
ipAddress: '#Request.ServerVariables["REMOTE_ADDR"]',
challengeField: recaptchaChallengeField,
responseField: recaptchaResponseField
},
dataType: 'text',
success: function (data) {
// Do something
},
Since you are using .NET so an example of C# code is as follows:
cs file:
using System.Net;
using System.Collections.Specialized;
[HttpPost]
public bool VerifyReCaptcha(string ipAddress, string challengeField, string responseField)
{
string result = "";
using (WebClient client = new WebClient())
{
byte[] response =
client.UploadValues("http://www.google.com/recaptcha/api/verify", new NameValueCollection()
{
{ "privatekey", "{Your private key}" },
{ "remoteip", ipAddress },
{ "challenge", challengeField },
{ "response", responseField },
});
result = System.Text.Encoding.UTF8.GetString(response);
}
return result.StartsWith("true");
}
I am new in knockoutjs, i am trying to bind the view, but cannot. Data from server is fetching fine, ajax is working fine, but not binding issue.
Here is my js code:
var UserViewModel = function () {
var self = this;
//Declare observable which will be bind with UI
self.Id = ko.observable("0");
self.FirstName = ko.observable("");
self.LastName = ko.observable("");
//The Object which stored data entered in the observables
var UserData = {
Id: self.Id || 0,
FirstName: self.FirstName || '',
LastName: self.LastName || ''
};
//Declare an ObservableArray for Storing the JSON Response
self.Users = ko.observableArray([]);
GetUser(12); //This is server side method.
function GetUser(userId) {
//Ajax Call Get All Employee Records
$.ajax({
type: "GET",
url: "/api/Users/" + userId,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
//alert("success");
UserData = response.data.UserData;
alert(UserData.FirstName); //This is showing me correct name.
self.Users(response.data.UserData); //Put the response in ObservableArray
},
error: function (error) {
alert(error.status);
}
});
//Ends Here
}
}
ko.applyBindings(new UserViewModel());
Here is my view:
<form class="form-horizontal" data-bind="with: UserData">
<div class="row">
<div class="control-group">
<label class="control-label">First Name</label>
<label class="control-label" data-bind="text: FirstName"></label>
</div>
</div>
<div class="row">
<div class="control-group">
<label class="control-label">Last Name</label>
<input type="text" placeholder="Last Name" data-bind="value: LastName">
</div>
</div>
Your problem is that you are trying to two-way data-bind against a non-observable property, so when you update it it isn't notifying the UI. Make your user an observable and set it to an instance of an object or create a model to derive your properties from.
function userModel(user) {
var self = this;
self.Id = ko.observable(user.Id);
self.FirstName = ko.observable(user.FirstName);
self.LastName = ko.observable(user.LastName);
}
var viewModel = function () {
var self = this;
//The Object which stored data entered in the observables
var UserData = ko.observable();
GetUser(12);
function GetUser(userId) {
//Ajax Call Get All Employee Records
$.ajax({
type: "GET",
url: "/api/Users/" + userId,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
//alert("success");
UserData(new userModel(response.data.UserData));
alert(UserData().FirstName()); //This is showing me correct name.
self.Users.push(UserData()); //Put the response in ObservableArray
},
error: function (error) {
alert(error.status);
}
});
}
}
ko.applyBindings(new viewModel());
Here, take from the following fiddle ::
http://jsfiddle.net/9ZCBw/
where you have a container model which owns the collection of users and has the function (ajax stripped for usability under fiddle)
function ViewModel () {
var self = this;
self.Users = ko.observableArray();
self.GetUser = function (userId) {
var UserData = {
Id: userId,
FirstName: 'Bob',
LastName: 'Ross'
};
self.Users.push(new UserModel(UserData));
}
}
Here, you have instances of Users which can then be bound to you model...as also shown.
I am consuming web services. I am making GET call to get all the questions -> user will answer that question and post it using the post call. This part is working as expected right now. Now, I would like make another GET call as soon as POST call is successful. I am able to make a GET call after POST call is complete but view is still showing data from my old GET call. How can I update the view with information from new GET call.
GET -> POST -> New GET (Data is not updated in this call.)
JSON
{
"Respondent_ID":"hello111",
"Group_Name":"",
"Product_ID":80,
"Language_ID":1,
"First_Name":"hello",
"Last_Name":"111",
"Respondent_EMail":"",
"Gender":"M",
"AllQuestions":[
{
"Question_Number":76,
"Question_Text":"I think ",
"Definition":"",
"Answer":0
},
{
"Question_Number":77,
"Question_Text":"I am ",
"Definition":"",
"Answer":0
},
{
"Question_Number":78,
"Question_Text":"I am mild mannered",
"Definition":"",
"Answer":0
},
{
"Question_Number":79,
"Question_Text":"I am strong",
"Definition":"",
"Answer":0
},
{
"Question_Number":80,
"Question_Text":"I am a risk taker",
"Definition":"",
"Answer":0
}
],
"AnswerChoice":[
{
"Answer_Choice":"Strongly disagree",
"Answer_Choice_Value":1
},
{
"Answer_Choice":"Disagree",
"Answer_Choice_Value":2
},
{
"Answer_Choice":"Neutral",
"Answer_Choice_Value":3
},
{
"Answer_Choice":"Agree",
"Answer_Choice_Value":4
},
{
"Answer_Choice":"Strongly agree",
"Answer_Choice_Value":5
}
]
}
--
#{
ViewBag.Title = "Questions";
}
<html>
<body>
<script src="~/Scripts/knockout.mapping-latest.js"></script>
<script>
function GetAllEmployees() {
$.ajax({
url: '/api/Questions?respondent_id=hello111',
type: 'GET',
dataType: 'json',
success: function (data) {
var data2 = data.AllQuestions;
var viewModel = {
data: ko.mapping.fromJS(data2),
Question_Number: ko.observable(data.AllQuestions[0].Question_Number),
Question_Text: ko.observable(data.AllQuestions[0].Question_Text),
save: function () {
$.ajax({
url: '/api/lms',
type: 'POST',
data: data,
dataType: 'json',
success: function (data) {
$.ajax({
url: '/api/Questions?respondent_id=hello111',
type: 'GET',
dataType: 'json',
success: function (data) {
//How can update the view with the new data I got from the get call.
}
ko.applyBindings(viewModel);
}
});
},
error: function (x, y, z) {
alert(x + '\n' + y + '\n' + z);
}
});
}
}
ko.applyBindings(viewModel);
},
error: function (x, y, z) {
alert(x + '\n' + y + '\n' + z);
}
});
}
</script>
</body>
</html>
Get Questions
<form data-bind="submit: save">
<table>
<thead>
<tr><th>#</th>Question<th>Strongly disagree</th><th>Strongly disagree</th><th>Disagree</th><th>Neutral</th><th>Agree</th><th>Strongly agree</th></tr>
</thead>
<tbody data-bind="foreach: $data">
<tr>
<td>
<span data-bind="text: Question_Number"></span>
</td>
<td>
<span data-bind="text: Question_Text"></span>
</td>
<td><input type="radio" class="radio" value="1" data-bind="attr: { name: Question_Number}"></td>
<td><input type="radio" class="radio" value="2" data-bind="attr: { name: Question_Number }"></td>
<td><input type="radio" class="radio" value="3" data-bind="attr: { name: Question_Number }"></td>
<td><input type="radio" class="radio" value="4" data-bind="attr: { name: Question_Number }"></td>
<td><input type="radio" class="radio" value="5" data-bind="attr: { name: Question_Number }"></td>
</tr>
</tbody>
</table>
<button type="submit">Go</button>
</form>
You must un-nest your code.
And you should start to use jQuery's native .get() and .post() calls and deferred callbacks (.then(), .done(), .fail(), .always()) for Ajax handling.
I rewrote your JS code:
function showAjaxError(x, y, z) {
alert(x + '\n' + y + '\n' + z);
}
function QuestionViewModel(respondentId) {
var self = this;
self.data = ko.observableArray();
self.currentQuestionId = ko.observable();
self.currentQuestion = ko.computed(function () {
return self.data()[self.currentQuestionId()];
});
self.mapQuestions = function (rawData) {
return ko.mapping.fromJS(rawData.AllQuestions);
};
self.rewind = function () {
self.currentQuestionId(0);
};
self.updateFromServer = function () {
$.get('/api/Questions', { respondent_id: respondentId })
.then(self.mapQuestions)
.done(self.data)
.done(self.rewind)
.fail(showAjaxError);
};
self.save = function () {
$.post('/api/lms', { data: ko.mapping.toJS(self.data) })
.done(self.updateFromServer)
.fail(showAjaxError);
};
self.updateFromServer();
}
ko.applyBindings(new QuestionViewModel('hello111'));
Notes
'/api/Questions?respondent_id=hello111' should not be hard-coded. Make it a variable.
View models work best when they are built with a constructor, because otherwise it's very hard to make them refer to themselves internally.
Don't repeat yourself. Make small, re-usable functions (like showAjaxError()) and re-use them. If your code nests more than 3 levels deep you are doing it wrong.
By commonly accepted coding style conventions, everything that is not a constructor starts with a lowercase letter and names don't have underscores (i.g. questionText instead of Question_Text).