Pass parameters without using QueryString - javascript

I have an MVC application. On one page I have a partial view that displays a bootstrap-table. I have some javascript code that is triggered when a table row is double clicked. This code retrieves some values from the double clicked row and constructs a url then navigates to that url.
This works fine but the way I have created the url means that I have data visible as querystrings in the url. How can I achieve navigating without using querystrings. Oh and I need the navigation to a new window/tab if possible.
My javascript code for the double click is:
$mTable.on('dbl-click-row.bs.table', function (e, row, $element) {
var cod = $('#hdCOD').val();
var mv = mGetSelectedRow().CMonth;
var yv = mGetSelectedRow().CYear;
var diff_cv = moment.utc(cod).diff(moment.utc(yv + '-' + pad(mv, 2) + '-' + '24'), 'months', true);
var plcf = '';
switch(true) {
case (diff_cv >= 2):
plcf = 'past';
break;
case (diff_cv >= 1 && diff_cv < 2):
plcf = 'last';
break;
case (diff_cv >= 0 && diff_cv < 1):
plcf = 'current';
break;
case (diff_cv < 0):
plcf = 'future';
}
var url = 'ClaimMonth/ViewMonth?pn=' + mGetSelectedRow().Cpid + '&cm=' + mv + '&cy=' + yv + '&mt=' + plcf + '&cod=' + cod;
window.open(url, '_blank');
})
The partial view is called using razor syntax:
Html.RenderAction("GetSummaryForAdmin", New With {Key .pn = Model.PersonelNo})
I can't seem to find an equivalent function in javaScript that mimics the New With {Key .pn = Model.PersonelNo} I'm also unsure if this is the way to do this. I've thought about ajax call but I don't think I can make this open as a new window/tab.
Any help appreciated.
UPDATE
I've found the following ajax.post method that gives me the document I want... In Developer Tools (F12 in Chrome/IE) using the network tab I can see the call for the document and if I preview it, it displays the data. But the page is not displayed in the browser.
Opening in a new window/tab is not a requirement but would be nice to have.
My new code replaces...
//var url = 'ClaimMonth/ViewMonth?pn=' + mGetSelectedRow().Cpid + '&cm=' + mv + '&cy=' + yv + '&mt=' + plcf + '&cod=' + cod;
//window.open(url, '_blank');
with...
$.ajax({
type : "post",
url : "ClaimMonth/ViewMonth",
data : {pn: mGetSelectedRow().Cpid, cm: mv, cy: yv, mt: plcf, cod: cod },
success : function(response) {
window.open();
},
error : function(xhr) {
console.log("error"+xhr.status);
},
complete : function() {
}
});
and I changed my controller function to accept parameters instead of reading request.querystring

You will have to use a combination of postback and Session.
AJAX Post (as you have already) to send values back to the server.
In the MVC action method which handles that postback, save the values to Session:
Public Function ViewMonth(...) As JsonResult
Session("SavedMonth") = New MonthObj(pn, cm, cy, mt, cod)
Return Json(True)
End Function
When the AJAX Post returns successfully, open a new window with a different URL:
success : function(response) {
window.open('/ClaimMonth/AfterSave');
},
The MVC action method for that URL loads the saved data from session, then displays it.
Public Function AfterSave() As ViewResult
Dim model As MonthObj = TryCast(Session("SavedMonth"), ModelObj)
Return View(model)
End Function

Related

Select2 local pagination/infinite scrolling

I'm using select2 version 4 and have a list with about 16,000 items. Predictably this is quite slow (take over 5 seconds to open sometimes) so I'm trying to find a way to speed this up.
Currently my data is being retrieved as an array using an ajax request and then inserted into the select2/dom using a for loop/appending.
$('#select').select2({
placeholder: "Select"
});
$.ajax("/Example/Data", {
type: 'GET'
})
.success(function (data, status, xhr) {
var option = '<option></option>';
for (var i = 0; i < data.length; i++) {
var curId = data[i].district_id;
var curDist = data[i].district_name;
var curState = data[i].state_short;
option += '<option value="' + curId + '">' + curDist + '('+ curState + ')' + ' - ' + curId + '</option>';
}
$('#select').append(option);
});
I've been trying to find a way to simply retrieve the data using the ajax request as I am doing now and then paginate/infinite scroll with the local but have been unable to do so
I've tried implementing this exactly: http://embed.plnkr.co/sUt9zi but I can't get it to work (maybe because it's using select2 v3.4.5) so if we could get that or something like it to work with v4 that would be great.
To prevent the 'slowness' you will need to mitigate creating and appending all 16k option elements at once. In order to do this the select2 library documents pagination using AJAX here: https://select2.org/data-sources/ajax#pagination
However, using the example you mentioned we can use a local dataset by doing something similar to:
var testData = [];
var dataSize = 1000;
// Instead of doing this use the AJAX call to poulate the data.
for (var i=0; i < dataSize; i++) {
testData.push({ text: `Data: ${i}`});
}
/*
Because you are sourcing your data via AJAX, this will
go in the success callback
*/
$("#testSelect").select2({
data: testData,
query: function(q) {
var pageLength = 50;
// Get a page sized slice of data from the results of filtering the data set.
var paged = this.data.slice((q.page - 1) * pageLength, q.page * pageLength);
q.callback({
results: paged,
more: this.data.length >= q.page * pageLength
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/select2/3.4.5/select2.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/select2/3.4.5/select2.min.js"></script>
<input type="text" id="testSelect" style="width: 200px"/>
Consider using server side to reduce the data instead
You are already using a remote data source, but you will need to pass some parameters to indicate which set of data is now necessary. The documentation shows doing this like:
$('#mySelect2').select2({
ajax: {
url: 'https://api.github.com/search/repositories',
data: function (params) {
var query = {
search: params.term,
page: params.page || 1
}
// Query parameters will be ?search=[term]&page=[page]
return query;
}
}
});
The query properties is important to pass the current page. This allows you to set an OFFSET in your sql query. Assuming you are using mysql your endpoint would be making a query similar to:
function getPageOfData(pageNum) {
var pageLength = 50;
var pageStart = (pageNum - 1) * pageLength;
var pageEnd = pageStart + pageLength;
var query = 'SELECT * FROM tbl LIMIT ' + pageStart + ',' + pageEnd;
}
Server side pagination is a bit complicated to set up as it requires the client to pass these parameters and the server to reply with a limited data set, but it will be the best option for handling large-ish datasets like yours.

How to Send Ajax Request After A Specific Time

How to Send Ajax Request in specific time and only that particular event
I m User Time Interval But it’s not Working.
i want get data in request 1 for use in request 2 but it get null data in request 2
setInterval()
it's not Working for me.
I want To send Request 2 After the some time of Request 1
Request 1:-
$(document).on("change", ".supplyItem", function (event) {
var id = $(this).attr("data-id");
var supplyItem = $(".supplyItem[data-id=" + id + "]").val();
var hospital = $("#hospital").val();
var physician = $("#physician").val();
var category = $("#category").val();
var manufacturer = $("#manufacturer").val();
var project = $("#project").val();
if (hospital != "" && physician != "" && category != "" && manufacturer != "" && project != "") {
$.ajax({
url: "{{ URL::to('admin/repcasetracker/getitemfile')}}",
data: {
supplyItem: supplyItem,
hospital: hospital,
project: project,
},
success: function (data) {
console.log(id);
if (data.status) {
var html_data = '';
var item = data.value;
console.log(item);
$('.hospitalPart[data-id=' + id + ']').val(item.hospitalNumber);
$('.mfgPartNumber[data-id=' + id + ']').val(item.mfgPartNumber);
// $('.mfgPartNumber[data-id='+id+']').text('something');
} else {
$('.hospitalPart[data-id=' + id + ']').val('');
$('.mfgPartNumber[data-id=' + id + ']').val('');
}
$('.quantity[data-id=' + id + ']').val('');
$('.purchaseType[data-id=' + id + ']').val('');
$('#serial-text' + id).val('');
$('#serial-drop' + id).val('');
$('#serial-drop' + id).empty();
}
});
}
});
Request 2:-
$(document).on('change', '.supplyItem', function (event) {
var timer, delay = 2000;
var id = $(this).attr("data-id");
var client = $("#hospital").val();
timer = setInterval(function(){
var supplyItem = $(".supplyItem[data-id=" + id + "]").val();
var hospitalPart = $(".hospitalPart[data-id=" + id + "]").val();
var mfgPartNumber = $(".mfgPartNumber[data-id=" + id + "]").val();
alert(supplyItem);
alert(hospitalPart);
alert(mfgPartNumber);
$.ajax({
url: "{{ URL::to('admin/repcasetracker/getdevicedata')}}",
data: {
supplyItem: supplyItem,
hospitalPart: hospitalPart,
mfgPartNumber: mfgPartNumber,
client: client,
},
success: function (data) {
if (data.status) {
var html_data = '';
var check = data.value;
if (check == 'True') {
html_data += "<option value=''>Purchase Type</option><option value='Bulk'>Bulk</option><option value='Consignment'>Consignment</option>";
$('.purchaseType[data-id=' + id + ']').html(html_data);
} else {
html_data += "<option value=''>Purchase Type</option><option value='Consignment'>Consignment</option>";
$('.purchaseType[data-id=' + id + ']').html(html_data);
}
}
}
});
}, delay);
clearInterval(timer);
});
You can move Request 2 into a function and this JS code will call the Request2 function after given interval of time (milliseconds), I have set it to 5 seconds for now.
setInterval(function () { Request2(); }, 5000);
function Request2(){
console.log("Request 2 called");
//add request 2 code here
}
jQuery's $.ajax method returns a promise, which is passed the result of the server-side call. You can chain these calls together so that you can build the result of multiple ajax calls. When you use it this way you do away with success callbacks as they are no longer necessary.
Applied to your code it might looks something like this:
$(document).on("change", ".supplyItem", function (event) {
var id = $(this).attr("data-id");
var supplyItem = $(".supplyItem[data-id=" + id + "]").val();
var hospital = $("#hospital").val();
var physician = $("#physician").val();
var category = $("#category").val();
var manufacturer = $("#manufacturer").val();
var project = $("#project").val();
if (hospital != "" && physician != "" && category != "" && manufacturer != "" && project != "") {
$.ajax({
url: "{{ URL::to('admin/repcasetracker/getitemfile')}}",
data: {
supplyItem: supplyItem,
hospital: hospital,
project: project,
})
.then(function(data1){
// process result of call1 and make call2
var item = data1.value;
return $.ajax({
url: "{{ URL::to('admin/repcasetracker/getdevicedata')}}",
data: {
supplyItem: supplyItem,
hospitalPart: value.hospitalPart, // note using result from 1 directly
mfgPartNumber: value.mfgPartNumber,
client: hospital
}
});
})
.then(function(data2){
// process result of call2
});
};
});
The point here is that you don't need to stash the result of call1 into some elements and re-read them before making call2, and trying to wait enough time before making call2. You just chain it all together with then.
Ok first though: Instead of using setInterval and then clearing the interval after it has run a single time, why not just use
setTimeout(function, delay);
Then personally I prefer to use XMLHttpRequest instead of Jquery AJAX, Jquery uses XMLHttpRequest at its base anyway,I just prefer it so I dont have to use Jquery, but if your already using Jquery in your site then it should be no more heavy. Here is a quick example of XMLHttpRequest so u can use it if you prefer.
var xhr = new XMLHttpRequest();
xhr.open("POST", 'URL::to("admin/repcasetracker/getdevicedata")', true);
xhr.setRequestHeader("Content-Type", "application/json charset=utf8");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
// content is loaded...
if (xhr.responseText) {
//Some code to run after the server responds and it was successfull
}
}
};
xhr.send(JSON.stringify({test:'test'})); //This is the data you are handing to the server
Notice the use of xhr.responseText, JQuery uses the same variable and this is usually the response from the server. One sure way to know is use your browser's debugging engine (F12 on Chrome and Firefox, have no idea on other browsers) to inspect the variables, it is very easy to ascertain the correct variable to use.
And then one last thought: I see you are not declaring the content-type and not JSON.stringify'ing() your data when you send it to the server.
Best way to debug a situation like this is 'proccess of elimation' so find out if the server is receiving the data then if the server is proccessing the data correctly and then check if the server is sending the data correctly.
If you are using Nginx use the /var/log/nginx/error.log to see if it throws any errors ( tip: tail -f /var/log/nginx/error.log | Apache uses /var/log/http/error.log on most distros ) and if you are using .NET just debug it in Visual Studio.
And read up on the Jquery success event there is 2 more arguments that gets passed - String textStatus and jqXHR jqXHR
http://api.jquery.com/jquery.ajax/
So to summarize:
Make sure to declare the dataType: 'json'
Use the correct variable, should be responseText
when passing the server data and using 'json' make sure to JSON.stringify() it
And I don't quite see why you want to use setTimeout in the first place.
If you are simply waiting for the server to respond then using any type of delay will be a terrible idea, instead use the events that gets fired after the server responds.
So in Jquery that is success: function() {} and error: function() {}
and in XMLHttpRequest its the xhr.onreadystatechange = function () { }

How can I POST JSON to another page and get to that page?

Can we only use javascript (jQuery, AnjularJS, anyhow, but do not use form) to get to another page with some JSON as the POST request body?
It means, I hope to write a segment of javascript code act as a submit button's action code. It will lead me to another page using POST request with some JSON data.
You can dynamically create a hidden form with inputs containing your data inside, and submit it to desired address
Example using jQuery:
var url = 'index.html';
var data = {
a: 1,
b: { a: 1, b: 2},
c: [1, 2, 3]
};
function appendData($form, prefix, data) {
function append(k, data) {
if (prefix !== '') {
appendData($form, prefix + '[' + k + ']', data[k]);
} else {
appendData($form, k, data[k]);
}
}
if (data instanceof Object) {
if ($.isArray(data)) {
for (var i = 0, l = data.length; i < l; i++) {
append(i, data);
}
} else {
for (var k in data) {
append(k, data);
}
}
} else {
var inp = $('<input type="hidden" name="' + prefix + '">').val(data);
$form.append(inp);
}
}
var $form = $('<form style="display:none;" action="' + url + '" method="post"/>');
appendData($form, '', data);
$('body').append($form);
$form[0].submit();
http://plnkr.co/edit/bM4oAj7TZNWfjkLVWMrY
If you want to change the phyiscal page in the browser, then you have to get the browser to do it. You can have an AJAX in the background, but it's not going to affect the browser page.
The simpliest way to get the browser to change the page is to set the window.location property to the url of the new page. Note, however, you can only do a GET this way.
I'd suggest doing an AJAX POST, and have that return a URL which you can have the borowser get to display the page you want.
Have a Read at this . Hope it helps ...
http://aspsnippets.com/Articles/Send-Pass-Data-Values-from-one-page-to-another-using-jQuery.aspx
If your trying to get to a predefined page and transfer a data packet you can encode the data into the query string if it's only a small amount.
Alternatively you can store it with HTML 5 local storage, change window.location to load the new page and then get the info back from the local storage.

jquery while loop running too fast - how to add a wait

I have jquery code that loops based on a counter, and inserts a record to a database and then opens a series of 4 reports for each new record it inserts.
The loop runs based on the number that is supplied by the user in the form dropdown called dropdownSection. For each Section; 1,2, or 3 the same number of records need to be inserted by ajax.
When the loop runs in the browser I get an error that I cannot track down. When I set a breakpoint in FireBug and step through the code it works fine. This leads me to think my loop might be running too fast?
Here is my code for the loop:
function InsertSheeter()
{
var textDate = $('#textDate').val()
var Workorder = $('#textWorkorder').val()
var Material = $('#dropdownMaterial').val()
var Shift = $('#dropdownShift').val()
var Sheeter = $('#dropdownSheeter').val()
var FoilNum1 = $('#textFoilNum1').val()
var FoilNum2 = $('#textFoilNum2').val()
var FoilNum3 = $('#textFoilNum3').val()
var Printline = $('#dropdownPrintline').val()
var Section = $('#dropdownSection').val()
var Comments = $('#textComments').val()
var Employee = $('#dropdownEmployees').val()
var a = 0
while (a < Section)
{
switch (a)
{
case 0:
blockSection = "1"
break;
case 1:
blockSection = "2"
break;
case 2:
blockSection = "3"
break;
}
var str = "{pDate:'" + textDate + "', pSheeter:'" + Sheeter + "', pShift:'"
+ Shift + "', pEmployee:'" + Employee + "', pWorkorder:'"
+ Workorder + "', pBlockSection:'" + blockSection + "', pComments:'"
+ Comments + "', pFoilNum1:'" + FoilNum1 + "', pFoilNum2:'"
+ FoilNum2 + "', pFoilNum3:'" + FoilNum3 + "', pPrintline:'"
+ Printline + "', pMaterial:'" + Material + "'}"
$.ajax(
{
type: "POST",
//contentType: "application/text; charset=utf-8",
url: "insertsheeter",
data: str,
dataType: "html",
success: function (data) {
OpenReports(Workorder, data);
},
error: function (xhr, errorType, exception)
{
var errorMessage = exception || xhr.statusText;
alert(errorMessage);
}
});
a++;
}
}
Do I need to put a delay in my loop to allow the other stuff to happen before continuing the loop?
Thx
In your case, I suspect you need the loop to wait for one AJAX insertion and set of reports to complete before starting the next one. You can do this with a recursive function instead of your while loop:
function myFunc() {
$.ajax({
/* ...options... */,
success: function(data) {
OpenReports(Workorder, data);
if (some_Boolean_test) {
myFunc();
};
}
});
}
myFunc();
Adding a fixed delay isn't going to be a consistent solution--that is if timing is even your problem. You should try setting async: false as Dave suggested. If that fixes your issue then timing might be part of your problem. The problem with fixed time delays is that they work under current conditions, but if for some reason the "slow" part takes even longer, your delay might not be enough--that's an antipattern.
As an aside, the one thing that sticks out to me is that you made a string that looks like a JSON object for your HTTP-POST data instead of just making a JSON object--was there a particular reason you did so? I would have done this:
var postData = {
pDate: textDate,
pSheeter: Sheeter,
pShift: Shift,
pEmployee: Employee,
pWorkorder: Workorder,
pBlockSection: blockSection,
pComments: Comments,
pFoilNum1: FoilNum1,
pFoilNum2: FoilNum2,
pFoilNum3: FoilNum3,
pPrintline: Printline,
pMaterial: Material
}
and then set data: postData in the $.ajax() call. Maybe your server code expects such an odd string though?
Hope this helps.
AJAX calls are by default Asynchronous, it looks like you might be looking for some synchronous behaviour here.
You can make an AJAX synchronous by setting
async: false

Using a value from a dropdown list in a handler

I could really use some help if anyone can spare some time. I am trying to access the value of a dropdownlist (dropdownlist1) on the master page from my content page and then use the variable in a hanlder in a .ashx code page. To test it I was trying to display the varialble in a message box. Any ideas would be appreciated.
Content Page (dropdownlist is on master page)
$(document).ready(function $("#DropDownList1").change(function () {
location.reload;
alert($(this).val());
strTrail = $(this).val();
alert(strTrail);
});
Handler
Case "SearchByLocation"
Dim firstTime As Integer = 0
Dim latitude As String = "42.9901009" 'context.Request("Latitude")
Dim longitude As String = "-81.146698" 'context.Request("Longitude")
'Dim fromdate As String = context.Request("#DropDownList1").val
Dim strTrail As String = context.Request("#DropDownList1")
MsgBox("now")
MsgBox(strTrail)
'strTrail = context.Request("strTrail")
If firstTime < 1 Then
strTrail = "Lookout"
End If
Dim objCBL As New JParkinsonLookUP.JPLookUp
Dim objDS As System.Data.DataSet = objCBL.SearchByTrail(strTrail, latitude, longitude, 10)
'result = "{""Locations"":[{""ID"":""1"",""Latitude"":""28.537"",""Longitude"":""-81.380""}]}"
result = "{""Locations"":["
For Each dr As System.Data.DataRow In objDS.Tables(0).Rows
result += "{""ID"":""" & dr("ID").ToString() & """,""Latitude"":""" & dr("Latitude").ToString() & """,""Longitude"":""" & dr("Longitude").ToString() & """},"
Next
result = result.Substring(0, result.LastIndexOf(","))
result += "]}"
firstTime = 1
Case "SearchByDescription"
End Select
'second command
'third command
context.Response.Write(result)
End Sub
firt of all avoid msgbox coz it will throw in exception (not valid in an aspnet page contest)
Second one when you will go through document.ready you will have to make a ajax request as per your code you will return json object then you need to parse within javascript the object ad read value from it.
$.ajax(
{
type: "GET", url: url, data: qry,
success: function (msg) {
lat = msg.Locations[0].Latitude;
lng = msg.Locations[0].Longitude;
alert(lat +' ' + lat);
},
error: function (msg) {
$("#coor").html("errore durante l'elaborazione");
}
});
Another important stuff use this directive to set your response:
context.Response.ContentType = "application/json";
Take care to check via Chrome or Firefox your response and call via network call so you will able to have more info.
this is code is not test i use some working code at my end and make some changes to let you an idea.

Categories

Resources