I have recently migrated from a codeigniter framework, to a nodejs with an express framework. Our codeigniter site had a lot of JS as it was, and we made a lot of AJAX calls because it is a single page app. We are messing around with node and express now, and I cannot get a simple AJAX call to function. It could be a lack of understanding of node, it could be something else. We are using openshift to host. We are using hogan-express as a template.
server.js
var express = require('express');
var fs = require('fs');
var http = require('http');
var path = require('path');
var SampleApp = function() {
var self = this;
self.initializeServer = function() {
self.app = module.exports = express();
self.app.configure(function() {
self.app.set('views', __dirname + '/views');
self.app.set('view engine', 'html');
self.app.engine('html', require('hogan-express'));
//self.app.set('layout', 'layout') # use layout.html as the default layout
self.app.use(express.favicon());
self.app.use(express.logger('dev'));
self.app.use(express.bodyParser());
self.app.use(express.methodOverride());
self.app.use(express.session());
self.app.use(self.app.router);
self.app.use(require('stylus').middleware(__dirname + '/public'));
self.app.use(express.static(path.join(__dirname, 'public')));
});
require('./routes');
}
There is more code in this file, I am only including the relevant code (I think).
Ajax.html
<div id="button">
<button id="testbutton">Push Me!</button>
</div>
<div id="populate">{{title}}</div>
<div id="null">{{>part}}</div>
<script type='text/javascript'>
$(function(){
$('#testbutton').click(function (){
$.ajax({
url:'/test',
type: 'POST',
success: function(result){
alert('success!');
},
error: function(){
alert("well this is embarassing... if the problem persists please let us know at facebook.com/stembuds");
}
});
});
});
</script>
index.js
app = require('../server');
app.get('/', function(req, res){
res.render('ajax');
});
app.post('/test', function(req, res){
console.log('get');
res.locals = {title: 'Horray'};
res.render('ajax', {partials:{part:'part'}});
});
part.html
<p> pass me in!!</p>
So basically what I am trying to do is when the button is clicked I want the ajax call to show a partial view. The way we are going to structure the site is to have one single page, and have the ajax calls render different views based on the buttons that the user clicks. So here is the interesting part: I get the success alert from the ajax call, but the {{title}} and the {{>part}} never show up. However, when I go to the console and click 'network', and then click 'test' (the url to my ajax call), the response shows the divs populated with "Horray" and "pass me in!!". Sorry for the length, and thank you for any information you can provide us.
If you are calling your resources with ajax (as you are doing) then you get the response to your ajax function. After successful call you need to render the view in your client side JS code.
What I mean is that your code works as expected, but your backend cannot update your browsers view. You need to do it client side or load the whole page again from the server.
Your success hander could be something like this:
success: function(result){
renderTheResults(result);
},
You can just send the JSON. You need to send the json via send not render. Because render is supposed to deliver the full HTML page. May be .ejs file.
For example:
res.send({partials:{part:'part'}});
res.send should be used to pass json to your page. And on your page you have to use the JSON to populate the HTML dynamically.
Related
I was searching for a similar issue for a while now, but none of the solutions worked for me (and I couldn't find exactly the same issue).
First of all, the website I'm working on is running on Zend Framework. I suspect that it has something to do with the issue.
I want to make a pretty basic AJAX functionality, but for some reason my response always equals the html of the current page. I don't need any of Zend's functionality, the functions I need to implement could (and I'd prefer them to) work separately from the framework.
For testing purposes I made it as simple as I could and yet I fail to find the error. I have a page "test.php" which only has a link that triggers the ajax call. Here's how this call looks:
$('.quiz-link').click(function(e){
e.preventDefault();
$.ajax({
URL: "/quiz_api.php",
type: "POST",
cache: false,
data: {
'test': 'test'
},
success: function(resp){
console.log(resp);
},
error: function(resp){
console.log("Error: " + reps);
}
});
});
And this quiz_api.php is just:
<?php
echo "This is a test";
?>
When I click on the link I get the entire HTML of the current page. "This is a test" can't be found there. I'm also getting an error: "Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check http://xhr.spec.whatwg.org/."
I reckon it has to do with the JS files that are included into this HTML response, but I've also tried setting "async: true" and it didn't help.
I would like to avoid using Zend Framework functions for this task, because I'm not well familiar with it and even making a simple controller sounds rather painful. Instead I want to find out what's causing such behavior and see if it can be changed.
PS: I've also tried moving quiz_api.php to another domain, but it didn't change anything.
I know that it might be an older code but it works, simple and very adaptable. Here's what I came up with. Hope it works for you.
//Here is the html
Link Test
<div id="test_div"></div>
function test(){
// Create our XMLHttpRequest object
var hr = new XMLHttpRequest();
// This is the php file link
var url = "quiz_api.php";
// Attaches the variables to the url ie:var1=1&var2=2 etc...
var vars = '';
hr.open("POST", url, true);
//Set content type header information for sending url encoded variables in the request
hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// Access the onreadystatechange event for the XMLHttpRequest object
hr.onreadystatechange =
function(){
if(hr.readyState == 4 && hr.status == 200){
var return_data = hr.responseText;
console.log(return_data);
document.getElementById('test_div').innerHTML = return_data;
}else{
document.getElementById('test_div').innerHTML = "XMLHttpRequest failed";
}
}
//Send the data to PHP now... and wait for response to update the login_error div
hr.send(vars); // Actually execute the request
}
you can change the whole page with a document.write instead of changing individual "div"s
I am developing an application with angular js
Question: When I have an ajax call to server and I need to change the views based on the result of ajax call, the views don't get affected by this call, I think it the page renders before ajax call is finished but I don't know how to resolve it
For example the following piece of code
$scope.addItem = function() {
$http({
method :'GET',
url : 'addItem',
headers : {'Content-Type': 'application/x-www-form-urlencoded'}
}).success( function(data) {
$scope.allItems = data;
});
}
the allItems changed after the ajax call but the view is not changed
how should I solve this?
I know it has been given some answers but I will go for it :). As the title says i want to add popover bootstrap but with ajax loaded content. my html, but i want a Loading message to appear first and then the content.
<p class='entry' data-adjaxload = '/calendar/entry/1'>Title1</p>
<p class='entry' data-adjaxload = '/calendar/entry/2'>Title2</p>
<p class='entry' data-adjaxload = '/calendar/entry/3'>Title3</p>
my django view is the following
def entry_details(request, entry_id):
entry = get_object_or_404(Entry, pk=entry_id)
args = dict(entry=entry, user=request.user)
if request.is_ajax():
return render_to_response('mycal/ajax/entry_details.html', args)
else:
entry_form = EntryForm(instance=entry)
args.update(entry_form=entry_form)
return render_to_response('mycal/entry_details.html', args)
Pretty simple. I am using the same view to either load html content via ajax in the popover, or a details page via normal get request
the ajax details page:
<div class="entry">
<p>{{entry.title}}</p>
<p>{{entry.date}}</p>
<p>{{entry.customer}}</p>
</div>
and the script
$(document).ready(function(){
$('p.entry').each(function (){
var i = $(this);
$(i).bind('mouseenter', function(){
i.popover({
html:True,
title:i.html(),
content:'Loading'
}).popover('show');
$.ajax({
url:i.data('ajaxload'),
dataType:'html',
success:function (data){
i.popover({content:data}).popover('show');
}
});
});
$(i).bind('mouseleave', function(){
i.popover('hide');
});
});
});
But whilst it does run tha ajx and fetches the html, it won't load them onto the popover. How can I change that?
Just fiddled what you are looking for with popover content being updated dynamically using echo/json.
Just roll over the p element and wait for the 3 second delay.
If as you say, the data is being loaded properly then the only change needed is:
var popover = i.data('popover');
popover.options.content = data.text;
i.popover('show');
I have an MVC view where I am doing some paging of data, using the PagedList component. My JavaScript to support this looks as follows:
$(function () {
var getPage = function () {
var $a = $(this);
var options = {
url: $a.attr("href"),
type: "get"
};
$.ajax(options).done(function (data) {
var target = $a.parents("div.pagedList").attr("data-ExchangeSite-target");
data: $("form").serialize(),
$(target).replaceWith(data);
});
return false;
};
$(".main-content").on("click", ".pagedList a", getPage);
});
My .cshtml file looks, in part, like this:
#model ExchangeSite.Entities.BicycleSearchSeller
<div id="itemList">
<div class="pagedList" data-ExchangeSite-target="#itemList">
#Html.PagedListPager(Model.BicycleSellerListingList, pageNumber => Url.Action("Index", new {pageNumber}),
PagedListRenderOptions.ClassicPlusFirstAndLast)
</div>
...
...
In IE9, this works perfectly. When I click on a specific page number, or the next/previous page, an asynch call is made to my controller to refresh the list of data ("itemList"). However, in Chrome, two calls are made to my controller. One is an Ajax call, the other is not. Can anyone tell me why, in Chrome, two calls are made to my controller? If you need to see more code, please let me know.
There seems to be some buggy line in your success callback:
data: $("form").serialize(),
It is terminated with a comma instead of semicolon. It also contains a colon after data. IE might be a little more tolerant towards broken javascript compared with Google Chrome.
I am doing a match "live timing" where an administrator sends to a database new inputs like: "Team A scores! 1-0". This is shown in a public website inside a <div /> and I want to get the new inputs and print it. I've never done something similar and I don't know what is the way to go.
I also have some doubts:
It's posible that the server sends the content to a X browser? So do the browser will only be on "idle"?
It's possible to only refresh when the user is active on the browser? Like Facebook does, if you're not present on the browser or moving your mouse over you don't get updates.
It's possible to append only to the <div /> the new items and not refresh all of it?
Thank you in advance!
You can use the ajax methods like this one:
$.getJSON('ajax/test.json', function(data) {
$('.result').html($('.result').html()+'<p>' + data.foo + '</p>'
+ '<p>' + data.baz[1] + '</p>');
});
or:
$.ajax({ url: "test.html", context: document.body, success: function(){
.......................................
}});
With a setTimeout call:
(function() {
$(document).ready(function() {update();});
function update() {
$.getJSON(.................);
setTimeout(update, 3000); }
}
)();
Then you could bind a mouseover event to the div that wraps your web, that would force an ajax call. You should use a control variable to know when the call is processing, so no to duplicate it.