Debugger not reaching select statement in jQuery.autocomplete - javascript

I have a Dynamic Grid in the ASP.NET page. When I click Add User, it creates an empty record with Textbox controls and when the user types something in the first Textbox - UserName, it should pull the UserNames from the Database and autocomplete should work for that Textbox control.
I have implemented jQuery.autocomplete function as below.
jQuery("#" + e.id).autocomplete({
source: function (request, response) {
var txtSearch = jQuery("#" + e.id).attr("id");
var t = jQuery("#" + txtSearch).val();
var URL = "../Users.aspx?UserName=" + t;
jQuery.ajax({
url: URL,
success: function (data) {
switch (data) {
case 'NOVALUESFOUND':
var rftspanID = e.id.replace("txt", "span");
break;
default:
var rftspanID = e.id.replace("txt", "span");
var rows = data.split("|");
var jsStr = "var datalist=[";
for (i = 0; i < rows.length - 1; i++) {
var s = rows[i].toString();
s = s.replace("'", "\\'");
s = s.replace('"', "\\'");
var row = s.split("~");
jsStr += "{id:'" + row[0].toString() + "'";
jsStr += ",name:'" + row[1].toString() + "'},";
}
jsStr = jsStr.slice(0, jsStr.length - 1);
jsStr += "];";
eval(jsStr);
if (typeof (datalist) != 'undefined') {
response(jQuery.map(datalist, function (items) {
if (items.id != undefined) {
return {
value: items.name,
id: items.id
}
}
}));
}
}
}
});
},
minlength: 1,
select: function (event, ui) {
if (Type == 1) {
document.getElementById("txtUser" + MemCount).value = ui.item.value;
}
else if (Type == 2) {
document.getElementById("txtRole" + MemCount).value = ui.item.value;
}
},
open: function () {
jQuery(this).removeClass("ui-corner-all").addClass("ui-corner-top");
},
close: function (event) {
jQuery(this).removeClass("ui-corner-top").addClass("ui-corner-all");
}
});
When I try to Debug this autocomplete, the data is coming at the end of response(jQuery.map(datalist, function (items) statement. But the select: option is not firing.
EDIT
The below screenshot shows how the data is formed.
And this is what is present in the Server-Side Users.aspx.vb Page_Load Event
Response.Clear()
Response.Write(GetUserName(Request.QueryString("UserName")))
Response.End()
What could be the problem?

First. In the response, you check the data variable in swith. And you get it as a string.
Second. the best way to work with ajax is JSON.
jQuery.ajax({
url: url,
dataType: 'json'
On successful response:
Make parsing.
json = JSON.parse(data)
And then you already apply your logic, I work with individual object variables.
swith(json.string){ .... }
And it will be easier to fill Textbox controls with the necessary parameters: json.user - the variable will contain an array of data about users.
Update code:
jQuery("#" + e.id).autocomplete({
source: function (request, response) {
var txtSearch = jQuery("#" + e.id).attr("id");
var t = jQuery("#" + txtSearch).val();
var URL = "../Users.aspx?UserName=" + t;
jQuery.ajax({
url: URL,
dataType: 'json',
/*
* format respone data (string!!!) -> {"result": [{"id": 1,"item": 2},{"id": 1,"item": 2}],"found": "VALUESFOUND"}
*/
success: function (data) {
let json = JSON.parse(data);
switch (json.found) {
case 'NOVALUESFOUND':
var rftspanID = e.id.replace("txt", "span");
break;
default:
var rftspanID = e.id.replace("txt", "span");
response(jQuery.map(json.result, function (items) {
if (items.id != undefined) {
return {
value: items.name,
id: items.id
}
}
}));
}
}
});
},
minlength: 1,
select: function (event, ui) {
if (Type == 1) {
document.getElementById("txtUser" + MemCount).value = ui.item.value;
}
else if (Type == 2) {
document.getElementById("txtRole" + MemCount).value = ui.item.value;
}
},
open: function () {
jQuery(this).removeClass("ui-corner-all").addClass("ui-corner-top");
},
close: function (event) {
jQuery(this).removeClass("ui-corner-top").addClass("ui-corner-all");
}
});

Related

How to deal with asynchronous problems in javascript

I want to display data stored in ch ! But my problem is that ch is displayed before the data is stored !
I think this is an Asynchronous Problems! How can I solve this problem.
When I try to get length of ch, I get always 0. Even if I store data statically in ch, I get the length 0.
I think this is an Asynchronous Problems! How can I solve this problem.
function RechercheFiltrée() {
var nom = document.getElementById('nompre').value;
var matricule = document.getElementById('matcle').value;
$.ajax({
url: "myWebServiceURL",
type: "GET",
dataType: "xml",
success: function(xml) {
var stock = [];
$(xml).find('Population').each(function() {
var table = document.getElementById("myTable");
$(this).find("directories").each(function()
{
dossier = $(this).attr('dossier');
stock.push(dossier);
});
});
var ch = [];
for (var i = 0; i < stock.length; i++) {
$.ajax({
url: "/mySecondWebServiceURL" + stock[i],
type: "GET",
dataType: "xml",
success: function(xml) {
var NMPRES = "";
var jsonObj = JSON.parse(xml2json(xml, ""));
var nom = jsonObj.SubmitResponse.occurrences.occurrence.filter(x => x["#datasection"] === "TS")[0].data.filter(x => x.item === "NMPRES")[0].value;
var matcle = jsonObj.SubmitResponse.occurrences.occurrence.filter(function(x) {
return x["#datasection"] === "LM"
})[0].data.filter(x => x.item === "MATCLE")[0].value;
var dossier = jsonObj.SubmitResponse.occurrences.occurrence.filter(function(x) {
return x["#datasection"] === "LM"
})[0]["#dossier"];
ch.push({
"nom": nom,
"matcle": matcle,
"dossier": dossier
});
if ($('#population').val() != null && firstIter == false) {
}
},
error: function(request, error) {
console.log('error Connexion : ' + error + ' request Connexion : ' + request);
}
});
}
var txt = "";
var firstIter = true;
for (var key in ch) {
if (ch[key].matcle === matricule) {
txt += "<option value='" + ch[key].dossier + "'" + firstSelect(firstIter) + ">" + ch[key].nom + "</option>";
firstIter = false;
}
}
$('#population').html(txt)
},
error: function(request, error) {
console.log('error Connexion : ' + error + ' request Connexion : ' + request);
}
});
}
The problem is that you are not waiting for the second service to respond.
It should be something like this:
const deferreds = stock.map((stockItem) => {
//... your logic with ch.push here
return $.ajax({
// your call to the second service
});
});
$.when(...deferreds).then(() => {
// your code
// for (var key in ch) {
});
The approach I'd rather take is to break the code down and use Promises. You really should take your time to learn Promises. It's a JavaScript standard and what jQuery uses under the hood.
function RechercheFiltrée() {
var nom = document.getElementById('nompre').value;
var matricule = document.getElementById('matcle').value;
return $.ajax({
url: "myWebServiceURL",
type: "GET",
dataType: "xml"
});
}
function getStockArray(xml) {
var stocks = [];
$(xml).find('Population').each(function() {
var table = document.getElementById("myTable");
$(this).find("directories").each(function() {
{
dossier = $(this).attr('dossier');
stocks.push(dossier);
});
});
});
return stocks;
}
function getStocks(stocks) {
return Promise.all(stocks.map(fetchStock));
}
function fetchStock (stock) {
return $.ajax({
url: "/mySecondWebServiceURL" + stock,
type: "GET",
dataType: "xml"
})
.then(formatStockInfo)
}
function formatStockInfo (xml) {
var NMPRES = "";
var jsonObj = JSON.parse(xml2json(xml, ""));
var nom = jsonObj.SubmitResponse.occurrences.occurrence.filter(x => x["#datasection"] === "TS")[0].data.filter(x => x.item === "NMPRES")[0].value;
var matcle = jsonObj.SubmitResponse.occurrences.occurrence.filter(function(x) {
return x["#datasection"] === "LM"
})[0].data.filter(x => x.item === "MATCLE")[0].value;
var dossier = jsonObj.SubmitResponse.occurrences.occurrence.filter(function(x) {
return x["#datasection"] === "LM"
})[0]["#dossier"];
if ($('#population').val() != null && firstIter == false) {
}
return {
"nom": nom,
"matcle": matcle,
"dossier": dossier
};
}
function updateSelectMenu (ch) {
var txt = "";
var firstIter = true;
for (var key in ch) {
if (ch[key].matcle === matricule) {
txt += "<option value='" + ch[key].dossier + "'" + firstSelect(firstIter) + ">" + ch[key].nom + "</option>";
firstIter = false;
}
}
$('#population').html(txt)
}
RechercheFiltrée()
.then(getStockArray)
.then(getStocks)
.done(updateSelectMenu);

Sending Array with Jquery

$('[data-toggle="mftapproveCheck"]').click(function () {
var selected = $("#checkboxes input:checked").map(function (i, el) { return el.value; }).get();
//alert("selected = [" + selected + "]\nas int = \"" + selected.join(";") + "\"");
var url = $(this).data("url") + "/" + selected;
var title = $(this).data("title");
callback: function (result) {
if (result) {
$("#preLoader").fadeIn('fast');
$.post(url, function (json) {
if (json.IsComplete) {
$("#" + id).remove();
BSToastr.show("success", "Başarılı", "İşleminiz Başarıyla Gerçekleştirildi.");
}
else {
BSToastr.show("error", "Hata", "İşleminiz Gerçekleştirilemedi.");
}
$("#preLoader").fadeOut('fast');
});
}
}
});
});
Here I am trying to send selected to controller. this works when only 1 Id comes but doesnt work when several comes. but alert always working. How can I send Array from here ?
public ActionResult ApproveSelected(int[] selected)
{
var itema = selected;
var itemb = itema;
try
{
var AllParticipants = Db.Participants
.Where(m => selected.Contains(m.Id))
.OrderBy(m => m.Id)
.ToList();
for (int i = 0; i < AllParticipants.Count; i++)
{
var item = AllParticipants.First();
item.Approval = true;
var itemRemove = AllParticipants.First();
AllParticipants.Remove(item);
}
Db.SaveChanges();
}
catch
{
return Json(new { IsComplete = false });
}
return Json(new { IsComplete = true });
}
You're not sending a list because of this line:
var url = $(this).data("url") + "/" + selected;
which just concats selected without actually converting it. If you take a look at your alert, you actually convert it to a string via the join function which is why you see all the items.
selected.join(";"); // <-- used in your alert()
So what I'd suggest is using that same join call when setting your url variable:
var url = $(this).data("url") + "/" + selected.join(";");

Iterate over array items and check property value

function GetViewModelData() {
var RDcViewModel = [];
var recordId = $.trim($("#recordId").val());
for (i = 1; i <= rowCount; i++) {
var item1 = $.trim($("#item1" + i).val()) == '' ? 0 : parseInt($("#item1" + i).val());
var item2 = $.trim($("#item2" + i).val()) == '' ? 0 : parseInt($("#item2" + i).val());
var GrandTotal = (item1 + item2);
var rdtCViewModel = new ItemDetailsViewModel(0, item1, item2, GrandTotal);
RDcViewModel.push(rdtCViewModel);
}
var obj = new ReportViewModel(recordId, RDcViewModel);
var viewmodel = JSON.stringify(obj);
return viewmodel;
}
I have the above sample function that i'm using to iterate over html table rows and storing the row values in an array.
Once i have my array populated, i'm using below code snippet to post the data to my controller.
var PostData = function () {
$(".btnSubmit").click(function () {
var viewmodel = GetViewModelData();
//i want to check from here if viewmodel has any item(row) where GrandTotal is 0 (zero)
$.ajax({
async: true,
cache: false,
contentType: 'application/json; charset=utf-8',
data: viewmodel,
headers: GetRequestVerificationToken(),
type: 'POST',
url: '/' + virtualDirectory + '/Item/DataSave',
success: function (data) {
if (data == true) {
window.location.href = '/' + virtualDirectory + '/Destination/Index';
}
},
error: function (e) {
return false;
}
});
});
}
What i now want to do in my PostData function is to check if my "viewmodel" object contains any item(row) where "GrandTotal" is 0.
using JSON.parse(viewmodel), prepare object of type ReportViewModel with RDcViewModel JS array of type ItemDetailsViewModel and iterate over it to find if any grandtotal == 0 for ItemDetailsViewModel instances
var viewmodel = GetViewModelData(),
var obj = JSON.parse(viewmodel);
var bFoundZero=false;
$.each(obj.RDcViewModelArray, function(idx, elem){
if( elem.GrandTotal === 0 ) bFoundZero=true;
})
if( bFoundZero ) return 0;
As you have stringified it, now you have to parse it back if you want to access its keys and values:
var PostData = function() {
$(".btnSubmit").click(function() {
var viewmodel = GetViewModelData(),
viewObj = JSON.parse(viewmodel),
flag = false; // <-----parse it back here
viewObj.forEach(function(i, el){
flag = el.GrandTotal === 0;
return flag;
});
if(flag){ return false; } // <------ and stop it here.
$.ajax({
async: true,
cache: false,
contentType: 'application/json; charset=utf-8',
data: viewmodel,
headers: GetRequestVerificationToken(),
type: 'POST',
url: '/' + virtualDirectory + '/Item/DataSave',
success: function(data) {
if (data == true) {
window.location.href = '/' + virtualDirectory + '/Destination/Index';
}
},
error: function(e) {
return false;
}
});
});
}
There is no point iterating array again. Break the loop in GetViewModelData() and return false from that function. Then test it in PostData
Inside existing for loop:
var GrandTotal = (item1 + item2);
if(!GrandTotal){
return false;
}
Then in PostData()
var PostData = function () {
$(".btnSubmit").click(function () {
var viewmodel = GetViewModelData();
if(viewmodel === false){
alert('Missing total');
return; //don't proceed
}
/* your ajax */

post data using ajax and js

Every time i try to use my classes below to post the array i made (also below) the ajax request doesn't pass the input as $_POST values but as $_REQUEST values seen in the web address bar at the top of the screen. I'm very new to Ajax and javascript (only been working with it about a month) so any tips and trick to fix anything below is greatly appreciated.
var formErrors=["Passage","FirstName","Zip"];
var formInput=["EventID","Passage","FirstName","LastName","Email","Organization","Location","Zip"];
Head of HTML
$(function () {
$("#signUp").click(function() {
if(formArrayValidation(formErrors) != false) {
formPostAjax(formInput, 'join-event.php');
}
return false;
});
});
Basics.js
formArrayValidation = function(errorArray) {
for(var i = 0; i < errorArray.length; i++) {
$('.error').hide();
var name = $("input#" + errorArray[i]).val();
if (name == "") {
$("label#" + errorArray[i] + "_error").show();
$("input#" + errorArray[i]).focus();
return false;
}
}
}
formPostAjax = function(inputArray, form) {
var dataString = "";
for(var i = 0; i < inputArray.length; i++)
{
var data = inputArray[i];
var dataInput = $("input#" + data).val();
if(i = 0) {
dataString = dataString + data + '=' + dataInput;
}
else {
dataString = dataString + '&' + data + '=' + dataInput;
}
}
$.ajax ({
type: "POST",
url: form,
data: dataString,
success: function() {
}
});
}
Your event listener should be on the form and it should be:
$('#form_identifier').submit(...);
Additionally, jQuery provides a nice shortcut method for serializing form data:
$('#form_identifier').submit(function(){
var post_data = $(this).serialize()
// ....
return false;
});

Function as a KnockoutJS observable

I have the following script (see below). I have two questions regarding it:
1.What does the following line mean in the context of Knockoutjs?
ko.observable(null);
2.How can I invoke a function not yet defined as in here:
that.activePollingXhr(...
Here is the full script:
$(document).ready(function() {
function ChatViewModel() {
var that = this;
that.userName = ko.observable('');
that.chatContent = ko.observable('');
that.message = ko.observable('');
that.messageIndex = ko.observable(0);
that.activePollingXhr = ko.observable(null);
var keepPolling = false;
that.joinChat = function() {
if (that.userName().trim() != '') {
keepPolling = true;
pollForMessages();
}
}
function pollForMessages() {
if (!keepPolling) {
return;
}
var form = $("#joinChatForm");
that.activePollingXhr($.ajax({url: form.attr("action"), type: "GET", data: form.serialize(), cache: false,
success: function(messages) {
console.log(messages);
for (var i = 0; i < messages.length; i++) {
that.chatContent(that.chatContent() + messages[i] + "\n");
that.messageIndex(that.messageIndex() + 1);
}
},
error: function(xhr) {
if (xhr.statusText != "abort" && xhr.status != 503) {
resetUI();
console.error("Unable to retrieve chat messages. Chat ended.");
}
},
complete: pollForMessages
}));
$('#message').focus();
}
that.postMessage = function() {
if (that.message().trim() != '') {
var form = $("#postMessageForm");
$.ajax({url: form.attr("action"), type: "POST",
data: "message=[" + that.userName() + "] " + $("#postMessageForm input[name=message]").val(),
error: function(xhr) {
console.error("Error posting chat message: status=" + xhr.status + ", statusText=" + xhr.statusText);
}
});
that.message('');
}
}
that.leaveChat = function() {
that.activePollingXhr(null);
resetUI();
this.userName('');
}
function resetUI() {
keepPolling = false;
that.activePollingXhr(null);
that.message('');
that.messageIndex(0);
that.chatContent('');
}
}
//Activate knockout.js
ko.applyBindings(new ChatViewModel());
});
ko.observable(null); creates an observable with a value of null. Nothing different than ko.observable(5);, where the value would be 5.
I see that you're using the that.activePollingXhr observable by passing it the result of an ajax call. However, this call is asynchronous and $.ajax doesn't return the data it got from the server, but rather a jquery deferred. You need to use that.activePollingXhr insude the success callback. Here's is how your code might look like:
$.ajax({url: form.attr("action"), type: "GET", data: form.serialize(), cache: false,
success: function(messages) {
console.log(messages);
for (var i = 0; i < messages.length; i++) {
that.chatContent(that.chatContent() + messages[i] + "\n");
that.messageIndex(that.messageIndex() + 1);
}
that.activePollingXhr(messages); // <-- Note where the call to activePollingXhr is
},
error: function(xhr) {
if (xhr.statusText != "abort" && xhr.status != 503) {
resetUI();
console.error("Unable to retrieve chat messages. Chat ended.");
}
},
complete: pollForMessages
});
As for the comment under your question: that.activePollingXhr is defined as that.activePollingXhr = ko.observable(null); - an observable with value of null.
That just initializes an observable with null as the initial value.
If you need to invoke a function that is an observable, just add a second set of parenthesis.
that.activePollingXhr()()

Categories

Resources