Sending a variable back to Express on click? - javascript

Let's say I have a list of 10 elements each with a unique id as their name and the user can add to the list whenever.
When I click an element, I want Express to get the id of the element I clicked. If it was just one element with a fixed id I could just use req.body.idname, but there can potentially be 100.
Is there a way to do this?
So far I have:
$( "li" ).click(function() {
var x = $(this).attr('name');
console.log(x);
});
which does get the correct name of the element but that's it.
What I'm trying to do is pass in the id as a parameter for a function like
exports.somePage = function(req, res){
var id = //id from clicked element goes here
//getElement finds the foo with the id
databaseTable.getFoo(id, function (err, foo){
if(err)
console.log("error");
else {
res.render('page', { title: 'Page',
foo : foo
});
}
});
};

You could use AJAX to POST the data.
$("li").click(function()
{
var ajaxData = {};
ajaxData.name = $(this).attr('name');
var request = $.ajax({
type: 'POST',
data: ajaxData,
url: 'http://localhost:3000/handleName'
});
request.success(function(data)
{
console.log("Success.");
for(var i = 0 ; i < data.length ; i++)
{
// Optional to pass some data back.
}
});
request.error(function(request, status, error)
{
console.log(request.responseText);
});
});
Wherea your handleName looks something like this:
app.post("/handleName", function(request, response)
{
response.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1'); // Sometimes required.
var name= request.body.name;
});
Maybe this isn't 100% copy/paste working for you but using AJAX and fetching the name in the request should work.

This is a two step process. First on express you need the proper routing set:
Server Side
//app = express();
app.get('/api/:paramID1/:paramID2',function(req, res){
//your code req.params.paramID1 or req.params.paramID2
});
On the client side you need a link that invokes the url or ajax like: http://yourdomain/api/1/abc where 1 and abc are param1 and param2 respectively.
So something as simple as: Some Demo on click could send the information you need to the server. Or using a little bit more complex example with JQuery/Ajax:
$.get( "/api/1/abc", function( data ) {
alert( "Load was performed. " + data );
});
Please note that when using rest there are different type of "methods" that can be invoke depending on your needs, such as POST, DELETE, UPDATE or the one just mentioned in the example GET.

Related

jQuery error in client post response - POST HTTP/1.1" 400

I can't figure out what is wrong with my code and I'm not really good with jQuery.
I'm trying to build HTML form will hold cars data. It's based on this form:
HTML source code is here.
Form data is sent on button click on the end back to program.
I upgraded that form with cascading manufacturer (proizvodjac in code) and car models droplist based on this code. But it's not working.
I keep receiving HTTP 400 which would mean that my POST call from client is malformed.
Here is my jQuery functions:
$(function () {
var carsdata = {"alfaromeo":["mito","156","147","giulietta","159","166","146"],"audi":["a3","a4","a6","a5","80","a1","q3","a8","q5"],"bmw":["320","116","x3","316","318","118","530","x1","520","x5","525","330","120","323","serija 1"],"chevrolet":["spark","lacetti","captiva","aveo","cruze"],"citroen":["c4","c4 grand picasso","c3","c5","c4 picasso","xsara","berlingo","c2","xsara picasso","saxo","ds5","c1"],"fiat":["brava","bravo","panda","grande punto","stilo","punto","punto evo","doblo","500","tipo","uno","coupe"],"ford":["c-max","fiesta","focus","mondeo","fusion","ka","escort"],"honda":["civic","accord","cr-v"],"hyundai":["getz","i10","i20","atos","i30","coupe","elantra","accent","santa fe","ix35","tucson"],"kia":["rio","pro_cee'd","sportage","cee'd","pride","sorento"],"mazda":["3","2","323 f","626","6","cx-5","323","premacy","5"],"mercedes":["a-klasa","c-klasa","e-klasa","b-klasa","124"],"mercedes-benz":["e-klasa","clk-klasa","c-klasa","s-klasa","190","a-klasa","b-klasa","c t-model","ml-klasa","w 124","124"],"nissan":["qashqai","x-trail","note","primera","micra","juke","almera"],"opel":["corsa","astra","zafira","meriva","vectra","insignia","mokka","tigra","combo","astra gtc","kadett"],"peugeot":["308","207","206","306","106","307","208","406","508","407","partner","3008","405"],"renault":["thalia","clio","scenic","grand scenic","kangoo","captur","megane grandtour","megane","laguna","5","megane break","twingo","modus","kadjar","megane classic","espace","megane scenic","megane coupe","megane sedan"],"seat":["toledo","leon","ibiza","altea","cordoba"],"skoda":["fabia","octavia","120","superb","felicia","rapid"],"smart":["fortwo"],"toyota":["corolla","yaris","auris","avensis","rav 4","land cruiser"],"vw":["polo","golf v","golf iv","golf vii","passat","golf vi","jetta","passat variant","caddy","sharan","tiguan","golf variant","golf ii","vento","golfplus","golf iii","bora","touran","touareg","up!"]};
var proizvodjac = $('<select id="proizvodjac"></select>');
var model = $('<select id="model"> </select>');
$.each(carsdata, function(item, key) {
proizvodjac.append('<option >' + item + '</option>');
});
$("#containerProizModel").html(proizvodjac);
$("#proizvodjac").on("change", function(e) {
var item;
var selected = $(this).val();
if (selected === "alfaromeo") {
item = carsdata[selected];
} else {
item = carsdata[selected];
}
$(model).html('');
$.each(item, function(item, key) {
model.append('<option >' + key + '</option>');
});
});
$("#containerProizModel").append(model);
$("button#predict").click(function(e){
e.preventDefault();
/*Get for variabes*/
var kilometraza = $("#kilometraza").val(), godina_proizvodnje = $("#godina_proizvodnje").val();
var snaga_motora = $("#snaga_motora").val(), vrsta_goriva = $("#vrsta_goriva").val();
/*create the JSON object*/
var data = {"kilometraza":kilometraza, "godina_proizvodnje":godina_proizvodnje, "proizvodjac":proizvodjac, "model":model, "snaga_motora":snaga_motora, "vrsta_goriva":vrsta_goriva}
/*send the ajax request*/
$.ajax({
method : "POST",
url : window.location.href + 'api',
data : $('form').serialize(),
success : function(result){
var json_result = JSON.parse(result);
var price = json_result['price'];
swal('Predviđena cijena auta je '+price+' kn', '','success')
},
error : function(){
console.log("error")
}
})
})
})
Comments and explanations are in the code.
On server side:
Server is expecting user_input dictionary which is built from variables returned by POST request. Here is how API method looks:
#app.route('/api',methods=['POST'])
def get_delay():
result=request.form
proizvodjac = result['proizvodjac']
model = result['model']
godina_proizvodnje = result['godina_proizvodnje']
snaga_motora = result['snaga_motora']
vrsta_goriva = result['vrsta_goriva']
kilometraza = result['kilometraza']
user_input = {'proizvodjac':proizvodjac,
'model':model,
'godina_proizvodnje':godina_proizvodnje,
'snaga_motora':snaga_motora,
'vrsta_goriva':vrsta_goriva,
'kilometraza':kilometraza
}
print(user_input)
a = input_to_one_hot(result)
price_pred = gbr.predict([a])[0]
price_pred = round(price_pred, 2)
return json.dumps({'price':price_pred});
Error from Google Chrome Developer Console:
which is pointing to:
EDIT 1:
I don' know how to pass proizvodjac and model to onClick function. See what happens on breakpoint:
XHR on Network tab:
HTML form is being filled with data OK only manufacturer and model are not passed to onClick:
EDIT 2:
Getting closer to solution. I've added :
var proizvodjac = $("#proizvodjac").val()
var model = $("#model").val()
as suggested and now all variables are successfully passed!
But I still get error 400 as final ajax POST call is getting stuck somwhere..
EDIT 3:
changed from
data : $('form').serialize()
to
data = data
AJAX method receives everything ok:
Still it doesn't work.
There are two main issues here:
1) you aren't getting the values from two of your fields correctly. You need to add
var proizvodjac = $("#proizvodjac").val()
var model = $("#model").val()
inside the $("button#predict").click(function(e){ function.
2) You're collecting all these values and putting them into your data variable...but then you aren't doing anything with it. Your AJAX request is configured as follows in respect of what data to send:
data : $('form').serialize()
The serialize() function automatically scoops up all the raw data from fields within your <form> tags. In your scenario, if you want to send a custom set of data (rather than just the as-is contents of the form) as per your data object, then you simply need to change this to
data: data
so it sends the information from that object in the POST request instead.

AJAX query not always updating information consistently

I am experiecing some issues with AJAX updating the page. The actual data in the database is updated but this is not always reflecting in real time on the web page.
For example, I have the following event:
$("#add_note").click(function(e) {
//e.preventDefault();
$("#add_note_form").validate({
rules: {
contact_note: {
required: true
}
},
submitHandler: function(form) {
contact.modal_update({
'obj' : $('#add_note_form'),
'uri' : '/contact/add_note/'
});
}
});
});
This function when a new note is created calls a callback to validate the form fields first and then if successful calls a callback inside a seperate class to conduct the update. See the modal_update class below:
// Update modal
this.modal_update = function(data)
{//
// Declare a few variables for the data object we've received
obj = data.obj // The form element to serialize
uri = data.uri;
// Get the form ID from the data-target attribute
id = obj.attr('data-target');
// URL to send to
url = this.site_url + uri + id;
// The form object
this.post_data(obj.serialize(),url);
// Hide Modal
obj.closest('.modal').modal('hide');
// Refresh
this.refresh();
}
This then figures out the correct route to ajax and calls a ajax call back inside the same class:
// AJAX post
this.post_data = function(obj,uri)
{
$.ajax({
data: obj,
dataType: 'json',
type: 'post',
url: uri,
headers: { "cache-control": "no-cache" },
cache: false,
success: function (response) {
if (response.success == true)
{
$("#alert_success .msg").html(response.message);
$("#alert_success").fadeIn(200).delay(2000).fadeOut(200);
}
else
{
$("#alert_error .msg").html(response.error);
$("#alert_error").fadeIn(200).delay(2000).fadeOut(200);
console.log(response.error);
}
}
});
}
I am then running another class callback to "refresh" the data in all the elements on the page:
this.refresh = function()
{
// Refresh the ajax requests
this.get_contact_data();
this.get_notes();
this.get_contact_log();
this.get_contact_tasks();
}
This class re loads the functions which run on page load to get the inial data into the tables/fields on the page. See "get_notes" below:
// Get notes
this.get_notes = function()
{
// Get all notes and populate table
var log_uri = this.site_url + "/contact/get_notes/" + this.contact_id;
this.get_data(log_uri,function(data) {
notes = $("#contact_notes ul");
notes.empty("");
// Populate the contact fields, assuming there is a result to play with
if (data != false) {
//alert(JSON.stringify(data));
$("#notes-tab .count").html("(" + data.length + ")");
$.each( data, function( key, value ) {
notes.append("<li class='list-group-item' modal-id='editNoteModal' data-target='" + value.ID + "'><div class='row'><div class='col-lg-3'><i class='fa fa-sticky-note mr-3'></i>" + value.timestamp + "</div><div class='col-lg-7'>" + value.note + "</div><div class='col-lg-2'><a href='#' class='edit mr-3'><i class='fa fa-edit mr-1'></i>Edit</a><a href='#' class='delete'><i class='fa fa-times mr-1'></i>Remove</a></div></div></li>");
});
console.log('Notes loaded');
} else {
notes.append("<li>There are currently no notes for this contact</li>");
}
});
}
Now the problem:
For some reason this does not update consistently in real time. The data is updated fine on the server side but on the client side the update/refresh does not always update. I might add a note and get a correct update response but the refresh method seems to be receiving the old data and always be one note behind. So the next time I add a note, the one I added before then appears and so forth.
Another problem I am experiencing is the methods seem to stack on each event so if I add one note (or one of the other methods) I will see the console say "notes loaded" but on the second note it says "notes loaded" twice, then on the 3rd note added 3 times and so forth.
I am sure there must be something fatal flaw in the design of my code here but I am not experienced enough with javascript/jquery to notice what direction I am going wrong so I can fix it.
I thought that this was an issue with ajax caching and not refreshing the result so I have adjusted the ajax request as cache none and also to send no cache headers. I am running in wamp.
In your case, your refresh code will always run before your data got updated. Because ajax is asynchronous so the code behind and below ajax will always execute nearly the time your ajax running.
At the time you run your post_data function to call the API, the refresh function got run too. So it's done before your data got updated.
You should run refresh function inside ajax callback. For example:
this.post_data = function(obj,uri, callback)
{
$.ajax({
data: obj,
dataType: 'json',
type: 'post',
url: uri,
headers: { "cache-control": "no-cache" },
cache: false,
success: function (response) {
if (response.success == true)
{
$("#alert_success .msg").html(response.message);
$("#alert_success").fadeIn(200).delay(2000).fadeOut(200);
}
else
{
$("#alert_error .msg").html(response.error);
$("#alert_error").fadeIn(200).delay(2000).fadeOut(200);
console.log(response.error);
}
callback();
}
});
}
And in modal_update, you pass refresh function to post_data as a callback:
this.modal_update = function(data)
{//
// Declare a few variables for the data object we've received
obj = data.obj // The form element to serialize
uri = data.uri;
// Get the form ID from the data-target attribute
id = obj.attr('data-target');
// URL to send to
url = this.site_url + uri + id;
// The form object
this.post_data(obj.serialize(),url, this.refresh);
// Hide Modal
obj.closest('.modal').modal('hide');
}
You should read more about asynchronous ajax. You can use other tricky solution is setTimeout to run this.refresh but I do not recommend that because you not sure when the update is done.

Laravel 5 attach with Ajax?

I have this laravel code in my controller detach function.
$input = Input::all();
$product= Products::findOrFail($input['product_id']);
$product->tags()->detach($input['tag_id']);
$product= Products::where('customer_id', Auth::user()->customers_id)->get();
return view('products.tagsdelete', [
'products' => $product,
]);
This works fine, it deletes the tag realation from my pivot table. The only thing that bugs me it that I don't want to reload the page everytime I press the delete button on my view.
( Of course I could make a selection of all tags the user want to delete, but I want to to this live with Ajax )
My problem is, I couldn't find anything that helps me with detachment from laravel + Ajax. I'm quite okay with Javascript and Jquery but Ajax is still a new thing for me..
So can anybody help me there? I'm really stuck.
Thanks for taking your time :)
#Wiriya Rungruang
current controller code:
public function detach()
{
$input = Input::all();
$product= Products::findOrFail($input['product_id']);
$product->tags()->detach($input['tag_id']);
$product= Products::where('customer_id', Auth::user()->customers_id)->get();
}
my button:
<button type="submit" class="delete-tag-btn" data-product_id="{{ $product->id }}" data-tag_id="{{ $tag->id }}"><i class="glyphicon glyphicon-trash"></i></button>
at the bottom of the code the JS:
<script>
$(".delete-tag-btn").on('click', function(){
var url = "{{ route('detach') }}"; // Url to deleteTag function
url += "product_id=" + $(this).data('product_id');
url += "&tag_id=" + $(this).data('tag_id');
// Now url should look like this 'http://localhost/deletetag?product_id=2&tag_id=5
// Send get request with url to your server
$.get(url, function(response){
alert("success");
});
});
</script>
First : You should create function detach tag from product in your controller and return status success or failure(or nothing)
In your controller
function detachTag(){
$input = Input::all();
$product= Products::findOrFail($input['product_id']);
$product->tags()->detach($input['tag_id']);
$product= Products::where('customer_id', Auth::user()->customers_id)->get();
return "Some state for checking it a success or not";
}
Second : Create javascript function for checking when you click on delete button send request with parameter to function that we created in the first step and rerender or remove that tag from your HTML page
**Parameter is mean product_id and tag_id that your want to detach it
In your js
$(".delete-tag-btn").on('click', function(){
var url = "localhost/deletetag?"; // Url to deleteTag function
url += "product_id=" + $(this).data('product_id');
url += "&tag_id=" + $(this).data('tag_id');
// Now url should look like this 'http://localhost/deletetag?product_id=2&tag_id=5
// Send get request with url to your server
$.get(url, function(response){
// Do what you want
});
});
So when you click on .delete-tag-btn It will send request for detach it
While you can right a simple ajax call, send data and return html and replace it with the old html
lets begin :)
first step is to write ajax, and send it when form is submit or any button is clicked (as per your code)
this one is sample ajax, just fill in your data in it.
var BASEURL = window.location.origin + "/your_domain_name/";
$.ajax({
url: BASEURL + "your_route",
type: "POST/GET", //any_one
data: {
// Your data comes here (object)
},
beforeSend: function () {
},
success: function (response) {
console.log(response); // your html in return
},
complete: function (response) {
}
});
now a call will be send with your data to controller respective to specified route you mentioned, processing will be normal.
It will return only html. You can do whatever you want with this html.
One important problem you might face if considering these instructions is, right now the view you are returning is probably of whole page (because the page is been refresh every time), but if you are thinking to replace it with new html, your will only have to return that part of the page may be a single row or something like that. So break your view in many sub views. Php #include(//path) (blade) might come handy. Thats how I use to work. :)

Ajax POST with function

I was using this code for get function and It works perfectly. Im getting data with this function.
function getdata(getdatafrom, resultclass){
$.get(getdatafrom, function(data) {
$(resultclass).html(data);
});
}
But I need this for post method. Im getting inputs with this get method I have to post it. It has to look like this.
function postdata(postdatafrom, inputnamesvaluelist){
$.post(postdatafrom, function(data) {
$(resultclass).html(data);
});
}
I will enter input names on this code like :
onclick="postdata(post.php,input1-input2-input3)"
And it ll post this inputs.. How can I do this?
If you would do this using inline-event you should add single quotes :
onclick="postdata('post.php', '#input1-#input2-#input3')"
Then your js should be :
function postdata(postdatafrom, inputnamesvaluelist){
var inputs_ids = inputnamesvaluelist.split('-');//split string passed into array of ids
var parameters={};
//construct obejct of {name: value,..} that you could pass it in post request
$.each(inputs_ids, function(index, input_id){
var input_name = $(input_id).attr("name");
var input_value = $(input_id).val();
parameters[input_name]=input_value;
})
//post parameters to given "postdatafrom"
$.post(postdatafrom, parameters, function(data) {
//Your code here
});
}
Hope this helps.

How to request a web page in JavaScript

In my site, there's a pervasive search bar that is a typeahead widget. The widget has a 'selected' callback that I am currently trying to implement.
In the callback, it determines whether or not it needs to make an AJAX request on the existing page or whether it needs to go to another page. My problem is that I cannot find anywhere a way to do a redirect with POSTed variables, like in a jQuery AJAX request. Is there any way to attain a page request with posted variables that will totally refresh the page, like clicking on a normal hyperlink?
Here is my code:
function getData(event, datum, dataset) {
event.preventDefault();
// get controller action portion of current url
var Controller = '<?= preg_replace('/\/.*/', '', preg_replace('/\/.*\/web\//', '', Yii::$app->request->url)) ?>';
var Key;
// get key out of key-value pair - will either be 'game', 'developer' or 'publisher'
for (var k in datum) {
Key = k;
}
// if the controller action is the same as key, then the request is ajax
// this works fine
if (Key === Controller) {
var req = $.ajax( {
type: 'POST',
url: 'getchilddata',
data: { data: datum[Key] },
})
.done(function(data) {
$('#display-div').html(data);
})
.fail(function() {
console.log("Failed");
})
} else { // else we need to go to a page on a different controller action according to Key
// this is the best i've got so far but want it to be better
window.location.href = Key + '/datastream?q=' + datum[Key];
}
}
The only way to achieve this is creating a form with hidden inputs, because you can't send post variables via Javascript, fortunately there is a Jquery plugin who will save you some code, but at the end the plugin just create a hidden form and simulate the redirect sending the form via POST, this is how to use it:
if (Key === Controller) {
$.ajax( {...})
} else {
$().redirect(Key + '/datastream, {'q': 'datum[Key]'});
}
Note: You can pass the method (GET or POST) as an optional third parameter, POST is the default

Categories

Resources