ajax requesting sending in second click in knockout js - javascript

i have the below knockout js code..
Design Code
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js"></script>
<div class="acmenu">
<ul id="accordion" data-bind="foreach: CategoryList">
<li data-bind="click$parent.categorySelected),attr: {iddata.CategoryId},htmldata.CategoryName">
</li>
</ul>
</div>
self.categorySelected = function (selectedCategory, event) {
$('#newproducttitle').hide();
event.preventDefault();
selectCategoryId = selectedCategory.CategoryId();
var refurbishedUrl = "/services/ShopService.asmx/XGetRefurbishedproducts";
$.ajax({
url: refurbishedUrl,
data: JSON.stringify({ ItemID: itemid, categoryid: selectCategoryId, language: lang }),
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (data) {
/******Lines of code**********/
}});
}
This function is calling for every click but ajax requesting is sending for second click only. i need to send ajax request for first click, is there any solution for that....
here i am proving one drive link for js file https://onedrive.live.com/redir?resid=143242b617ba6be2!6684&authkey=!AAJQbpV8ZQ7fnGI&ithint=file%2ctxt

Though we don't have enough to work on still I think it is calling on first request as well (unless you have verified in developer tools etc.). The reason it seems to work on second click is that ajax call has not returned and on second click it appears to work.
Try this to disable button until ajax returns:
$.ajax({
url: refurbishedUrl,
data: ...,
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
beforeSend:function(){ $(event.target).prop('disabled', true);},
}).done(function(data){
/*USE THIS INSTEAD OF success*/
}).fail(function(data){
/*USE THIS INSTEAD OF error*/
}).always(function(){
$(event.target).prop('disabled', false);
});

You are using knockout against its design.
The viewmodel manages data and state - and nothing else. It is not supposed to contain any code that does HTML or DOM manipulation, at all.
In this case your data is a list of category objects. You want to inform the server when one of them becomes the selected category. Additionally you want to keep track of whether the viewmodel is busy talking with the server.
Therefore we need categoryList, selectedCategory and busy observables, as well as a subscription to changes in the selected category:
function ViewModel() {
var self = this;
self.categoryList = ko.observableArray([/* category objects ... */]);
self.selectedCategory = ko.observable();
self.busy = ko.observable(false);
self.selectedCategory.subscribe(function (newCategory) {
self.busy(true);
API.post("XGetRefurbishedproducts", {
ItemID: itemid, // wherever that comes from
categoryid: newCategory.CategoryId(),
language: lang // wherever that comes from
}).done(function (data) {
/******** Lines of code ********/
}).always(function () {
self.busy(false);
});
});
}
The view displays the category list, provides a way of changing the selected category, and reacts to whether the viewmodel is busy.
Therefore we need foreach, text, click and disable bindings:
<div class="acmenu">
<ul id="accordion" data-bind="foreach: categoryList">
<li>
<span data-bind="text: CategoryName"></span>
<button data-bind="
click: $parent.selectedCategory,
disable: $parent.busy
">Select</button>
</li>
</ul>
</div>
Note that you can use an observable as a click handler.
Finally, to keep the viewmodel tidy, here's a helper that concentrates all Ajax handling in a central spot.
var API = {
ajax: function (httpMethod, apiMethod, data) {
return $.ajax({
type: httpMethod,
url: "/services/ShopService.asmx/" + apiMethod,
data: data,
dataType: "json"
}).fail(function (jqXhr, status, error) {
console.error("Could not call " + method + ", error: " + error, data);
});
},
get: function (apiMethod, data) {
return this.ajax("get", apiMethod, data);
},
post: function (apiMethod, data) {
return this.ajax("post", apiMethod, data);
}
};

Related

How to pass the id of the element user clicked on back to Flask using AJAX

I am trying to work on this website that shows a list of records, and when a user clicks on one of them, he will be navigated to another page that shows the details of the record. The logic behind it is, each 'li' tag has an "id" attribute that is unique, and I can use that id to call API and fetch the detailed info for that record. However, it seems that nothing was passed back to Flask...
HTML code:
<ul class="list-group list-group-flush">
{%for i in range(0,length)%}
<li class="list-group-item" id={{res.value[i].id}}>
<h4 class="itemName">Name:{{res.value[i].name}}</h4>
<p class="itemAssetType">{{res.value[i].assetTypes[0]}}</p>
<p class="itemQualifiedName">{{res.value[i].qualifiedName}}</p>
</li>
{%endfor%}
</ul>
JavaScript code:
$(function(){
$('li').click(function(){
var elementID = this.id
var datatosend = JSON.stringify({"guid":elementID})
$.ajax({
url: '/details',
data: datatosend,
type: 'POST',
success: function(response){
window.location.href = '/details'
console.log(response); //for stackoverflow: this shows None in console
},
error: function(ts) { alert(ts.responseText) }
});
});
});
Flask code:
#app.route('/details',methods=['POST','GET'])
def details():
print (request.json) #this gives: None
print (request.data) #this gives: b''
print (request.args.get("guid")) #this gives: None
return str(request.json)
Just wondering how am I supposed to pass that id into flask?? Why is it always empty???
I am kinda new to the front end, any help is greatly appreciated.
i think you remove this part
success: function(response){
window.location.href = '/details'
console.log(response);
}
because you get some data from server and then you go another page? but your data still stands in previous page!
You need to keep stay in current page and use your data like this:
success: function(response){
console.log(response);
}
$(function () {
$('li').click(function () {
var elementID = this.id;
console.log(this.id)//for stackoverflow: this shows the id as I expected
$.ajax({
url: '/details',
data: { guid: this.id },
type: 'POST',
success: function (response) {
console.log(response);
},
error: function (error) {
console.log('failed');
console.log(error);
console.log('element id =======>',elementID)//it is work now!!!
}
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li id="xyz">##click me##</li>
<script src="app.js"></script>

Data passing error from javascript to controller

I'm working on ASP.NET MVC project , I want to get location dropdown selected value and according to that i need to load values to City dropdown , i implemented following code and location dropdown onselect event call the javascript function and javascript function call the controller method but when executing controller method locationId is null ,and i debug javascript and locationID is there till the this line data: JSON.stringify({ locationId: +locationId }), after that javascript returns error.but controller method get hit but locationId null
code for dropddowns
<div class="row">
<div class="col-sm-4">
#Localizer["Locations"]
<select id="locationDropDown" class="selectpicker form-control" asp-for="selectedLocation" onchange="getCityList()">
<option value="0"><None></option>
#foreach (var item in Model.LocationList)
{
<option value="#item.Id">#item.Name</option>
}
</select>
</div>
</div>
<div class="row">
<div class="col-sm-4">
#Localizer["KioskGroup"]
<select id="cityDropDown" class="selectpicker form-control">
<option>---Select City---</option>
</select>
</div>
</div>
Javascript code
function getCityList()
{
debugger;
var locationId = $("#locationDropDown").val();
console.log(locationId)
$.ajax({
url: '/Kiosk/GetZoneListBYlocationID',
type: 'POST',
datatype: 'application/json',
contentType: 'application/json',
data: JSON.stringify({ locationId: +locationId }),
success: function (result) {
$("#cityDropDown").html("");
$("#cityDropDown").append
($('<option></option>').val(null).html("---Select City---"));
$.each($.parseJSON(result), function (i, zone)
{ $("#cityDropDown").append($('<option></option>').val(zone.Id).html(zone.Name)) })
},
error: function(){alert("Whooaaa! Something went wrong..")},
});
controller method
public ActionResult GetZoneListBYlocationID(string locationID)
{
List<Zone> lstZone = new List<Zone>();
long locationId = long.Parse(locationID);
var zones = _zoneRepository.GetZonesByLocationId(locationId);
return Json(JsonConvert.SerializeObject(zones));
}
Your current code is sending the json string {"locationId":101} in the request body because you specified the contentType as application/json. This is useful when you want to send an object with multiple properties and your action method parameter is a DTO/POCO class type. Model binder will be reading from the request body and map it to the parameter.
In your case, all you are sending is a single value. So do not send the JSON string. simply create a js object and use that as the data attribute value. Also remove the contentType: application/json as we are not sending a complex js object as json string.
Also application/json is not a valid option for the dataType property. You may use json. But jQuery is smart enough to guess the value needed here from the response headers coming back from server. So you may remove it.
function getCityList() {
var locationId = $("#locationDropDown").val();
$.ajax({
url: '/Kiosk/GetZoneListBYlocationID',
type: 'POST',
data: { locationID: locationId },
success: function (result) {
console.log(result);
// populate dropdown
},
error: function () { alert("Whooaaa! Something went wrong..") },
});
}
Now this data will be send in Form Data as locationID=101 with Content-Type header value as application/x-www-form-urlencoded and will be properly mapped to your action method parameter.
You should use the correct types. In your action method, you are using string as your parameter and later trying to convert it to long. Why not use long as the parameter type ? Also if zones variable is a list of Zone object, you can pass that directly to the Json method. No need to create a string version in between.
public ActionResult GetZoneListBYlocationID(long locationId)
{
var zones = _zoneRepository.GetZonesByLocationId(locationId);
return Json(zones);
}
Why you are stringify the data.Below one should work without stringify
data: { locationId: +locationId },
I was facing the same problem. and after that, I have tried below solution.
Hope it will help you.
ajax call is as follows:
$.ajax({
type: 'POST',
url: "/Account/GetCities",
dataType: 'json',
data: { id: $("#StateID").val() },
success: function (states) {
$.each(states, function (i, state) {
$("#CityID").append('<option value="' + state.Value + '">' + state.Text + '</option>');
});
},
error: function (ex) {
alert('Failed to retrieve cities.' + ex);
}
});
The controller code is as follows:
public List<CityModel> GetCities(int id)
{
//your code
}
You can do in your application like this:
function getCityList()
{
var locationId = $("#locationDropDown").val();
console.log(locationId)
$.ajax({
url: '/Kiosk/GetZoneListBYlocationID',
type: 'POST',
dataType: 'json',
data: { locationId: locationId },
success: function (result) {
$("#cityDropDown").html("");
$("#cityDropDown").append
($('<option></option>').val(null).html("---Select City---"));
$.each($.parseJSON(result), function (i, zone)
{ $("#cityDropDown").append($('<option></option>').val(zone.Id).html(zone.Name)) })
},
error: function(){alert("Whooaaa! Something went wrong..")},
});
}
And your controller will be same as you have done.

How can I ajax only html table rows instead of sending the entire form inputs?

I have tried to ajax using post to jsp script my html table rows for weeks now with no success.Can anyone please guide me on this?Below is what I have done so far.
window.addEventListener("DOMContentLoaded", function () {
var form = document.getElementById("updateDealPmtForm");
document.getElementById("btn").addEventListener("click", function () {
$('#notSoCoolGrid > tr').each(function(event) {
event.preventDefault();
var postData = {
paymentId:$('#paymentId').text(),
id:$('#deald').text(),
pType:$('#pType').text(),
pAmt:$('#pAmt').text(),
currency:$('#currency').text(),
pInvDate:$('#pInvDate').text(),
pRecDate:$('#pRecDate').text(),
comments:$('#comments').text()
};
console.log(postData);
$.ajax({
async: false,
type: "POST",
cache: false,
url: "/update_deal_pmt_script.jsp",
data: postData.$('input, select').serialize() ,
success: function(msg){
alert("submitted");
}
});
});
});
If I correctly understand your need, you want to transmit the content of your rows, each in the form showed in your current postData.
So this can be made at once for all rows (instead of ajaxing successively each of them).
It might be something like this:
window.addEventListener("DOMContentLoaded", function () {
var form = document.getElementById("updateDealPmtForm");
document.getElementById("btn").addEventListener("click", function () {
event.preventDefault();
var postData = [];
$('#notSoCoolGrid > tr').each(function(event) {
postData.push(
paymentId:$('#paymentId').text(),
id:$('#deald').text(),
pType:$('#pType').text(),
pAmt:$('#pAmt').text(),
currency:$('#currency').text(),
pInvDate:$('#pInvDate').text(),
pRecDate:$('#pRecDate').text(),
comments:$('#comments').text()
);
});
console.log(postData);
$.ajax({
async: false,
type: "POST",
cache: false,
url: "/update_deal_pmt_script.jsp",
data: postData,
success: function(msg){
alert("submitted");
}
});
});
});
Note that I choosed (the simplest way, IMO) to make a simple array of rows, where each one is an object like you already structured them.
Last point: I notice you specified async: false.
I don't know why you did that, and so I kept it unchanged.
But note that it's not recommended, and is being on the road to become deprecated.
I finally was able to solve this issue,for that I want to post my answer it might be helpful for someone out there.My previous code was submitting a form before even ajax call being triggered and I have to use Classes instead of IDs to identify my rows.I had to change the code completely to be able to submit the form
$('#btn').click(function(e) {
e.preventDefault();
$('#notSoCoolGrid tr').each(function(i, tr) {
var postData = {
paymentId : $('.paymentId', tr).val(),
id : $('.deald', tr).val(),
pType:$('.pType', tr).val(),
pAmt:$('.pAmt',tr).val(),
currency:$('.currency',tr).val(),
pInvDate:$('.pInvDate',tr).val(),
pRecDate:$('.pRecDate',tr).val(),
comments:$('.comments',tr).val()
}
$.ajax({
async: false,
type: "post",
url: "/update_deal_pmt_script.jsp",
data: postData
})
.done(function(response) {
console.log(response);
})
.fail(function(x, status, error) {
alert("Error: " + error);
});
});
});

JSON data into array with Ajax request

I have a following HTML:
<div id="main">
<div id="blogcont">
<p></p>
</div>
<button class="nvgt" id="prev" >Previous</button>
<button class="nvgt" id="next" >Next</button>
By clicking on either the Previous or Next button, I want to load the data from a JSON file - articles content. My JSON at the moment looks like below and it is located in separated folder (it is only a test version):
var = articles [
{
"Title":"test1",
"Content":"test1",
"related":"test1"
},
{
"Title":"test2",
"Content":"test2",
"related":"test2"
}
]
_(I am not sure if the syntax is correct)
function (){
$ajax({
type: "GET",
url: "../Content/test.txt",
dataType: "json"
}).done(function (data){
$.each(data, function (key, val){
});
});
}
It's supposed to be done via an AJAX request. Any ideas how to do it?
First of all, if JSON, it needs to be like:
[
{
"Title":"test1",
"Content":"test1",
"related":"test1"
},
{
"Title":"test2",
"Content":"test2",
"related":"test2"
}
]
Then, do not load data everytime you click on prev, next buttons. Load it once and use it later, as and when you need. Irrespective of that, here are the click/ajax calls:
$('#main').on('click', 'button', function(){
//OR $('#main').on('click', '#prev,#next', function(){
$ajax({
type: "GET",
url: "../Content/test.txt",
dataType: "json"
}).done(function (data) {
$.each(data, function (key, val){
//Do your stuff here;
});
});
});

How to render MVC 4 view on slickgrid double click via Javascript

I am using MVC4 along with slickgrid to display data to the user. I am trying to implement the ability to double click on a slickgrid row and have the page go to another view, but all I am able to get is the HTML returned to the client, but not rendered.
I am doing,
grid.onDblClick.subscribe(function (e, args) {
$.get(
"MapSetEdit/Edit/",
{ 'mapSetId': 1 }
);
});
and I have also tried:
grid.onDblClick.subscribe(function (e, args) {
$.ajax({
type: "GET",
url: "MapSetEdit/Edit/",
dataType: 'text',
data: {'mapSetId': 1}
})
.fail(function () {
console.log("Error retreiving map list.");
});
});
All this does is return the html to the browser but never renders it. How do I make a javascript request so that I am able to actually render the view. I think I am missing something obvious here as I am new to javascript and mvc.
You should render the returned HTML with jQuery. For example:
grid.onDblClick.subscribe(function (e, args) {
$.ajax({
type: "GET",
url: "MapSetEdit/Edit/",
dataType: 'text',
data: {'mapSetId': 1}
})
.succes(function(data){
var someemptydiv = $("#myEmptyDiv");
someemptydiv.html(data);
})
.fail(function () {
console.log("Error retreiving map list.");
});
});
I was able to do what I needed with:
grid.onDblClick.subscribe(function (e, args) {
window.location = '/MapSetEdit/Edit/?mapSetId=1'
});

Categories

Resources