Updating page through ajax and url without reloading the page (node.js) - javascript

What would be the correct way to make the inventory update without refreshing the page and accessible through both the button event and url. So that when url param id is based to the route it will update it to the specific page. Like a products page on a shopping site. Below works through the ajax request but not through the url (inventory/2) it just takes me to the posted data and not with the rendered view. I require it to be able to go to a specific page by the url so I can link to it. It also needs to be able to fall back to just standard page loading when javascript is not enabled.
View (inventory)
extends layout
block content
div.row
div.col-md-offset-2.col-md-8#inventory
a(class='btn', href='#') Get More!
script.
$(function(){
$("a.btn").on("click", function(e) {
e.preventDefault();
$.get( '/inventory/2', function(data) {
$('#inventory').html(data);
});
});
});
Routes
router.get('/inventory/:id?', function (req, res) {
if(req.params.id){
var id = req.params.id;
var data = "Updated and now on page " + id
res.send(data);
}else{
res.render('inventory');
}
});

Would recommend to have two separate sets of paths: one for the human users and one for the scripts (API). In your routes file above, you mix the two - res.send(data) is intended for the AJAX script, and res.render('inventory') for direct display in the browser in response to the user's request - that is, basically, why you don't get the result you expected.
Please see a below a simple example how the app files can be structured (extend it as you see reasonable):
View:
extends layout
block content
div.row
div.col-md-offset-2.col-md-8#inventory
= content
a(class='btn', href='#') Get More!
script.
$(function(){
$("a.btn").on("click", function(e) {
e.preventDefault();
$.get( '/api/inventory/2', function(data) {
$('#inventory').html(data);
});
});
});
Routes:
var getData = function(id) {
return "Updated and now on page " + id;
}
router.get('/api/inventory/:id', function (req, res) {
res.send(getData(req.params.id);
}
router.get('/inventory/:id?', function (req, res) {
var data;
if (req.params.id) {
data = getData(req.params.id);
} else {
data = null;
}
res.render('inventory', {content: data});
});
(note: you may have to use != content instead of = content in the Jade template if your data contains HTML.)
Now, the user can access different states of the page via urls /inventory and /inventory/2, while the AJAX call will be done using a third url, /api/inventory/2.
On top of that, you can dynamically update the url field in the user's browser as may be needed - see the answers to this question for more details.

Related

jQuery on click not working with express to load a handlebars page

jQuery on click function not working to work with express to route to a handlebars page to display passed information.
I've tried changing the get to post. Not using handlebars and just having in html file and using path.sendFile or chaning res.render to be res.send
Heres the on click function
$("#song").on("click", function(){
var songArtist = $(this).text();
$.get("/results/:" + songArtist);
});
Heres the express route
app.get("/results/:songArtist", function(req, res) {
res.render("songResult");
//res.sendFile(path.join(__dirname + "./../views/result.html"));
});
I expect that when the divs with the song id is clicked to load to a new page.
Get rid of the : in the $.get() in the front-end JS. The : is only used on the back-end to represent variable URL parameters.
So on the back-end, when you listen for get requests at "/results/:songArtist", whatever comes after "/results/" will now be referred to in the function as req.params.songArtist.
For example, if I send a get request to "/results/pinkfloyd", inside the listener function you provided above, req.params.songArtist === pinkfloyd.

Displaying ajax data in template page - Framework7

Am playing with Framework7 to do hybrid mobile app development. I have three tabs (bottom fixed), which are Home, Contacts and Settings/Profile
My app.js file looks somewhat like this:
var $$ = Dom7;
var app = new Framework7({
//.....
data: function () {
return {
user_profile : ''
}
},
on: {
tabShow( tab ) //-- when a bottom tab is clicked
{
if( $$(tab).attr('id') == 'view-settings' )
{
//.. do ajax call and get the response data in "resp"
app.data.user_profile = resp.response.profile; //setting the info to app's data
}
}
},
routes: routes
});
var settingsView = app.views.create('#view-settings', {
url: '/settings/'
});
And in routes.js:
routes = [
{
path: '/',
url: './index.html',
},
{
path: '/contacts/',
componentUrl: './pages/contacts.html',
},
{
path: '/settings/',
componentUrl: './pages/settings.html',
}
];
This Contacts page contains static content. For the Home page, am doing the AJAX API call during the deviceready state. Because am setting up some headers for authentication and stuff(for all the AJAX api calls) in there.
The problem am facing is, am unable to display the content in Settings page. It is always empty!
Am using this in that template page:
<div class="item-title item-label">Full Name - {{$root.user_profile.full_name}}</div>
I want to compile that template only when clicking the respective tab button.
Maybe that's the problem.
Any suggestions?
After going through the documentations again and again, I got another way to do this.
So, during the tabShow event, I check whether the user is accessing the Settings/Profile tab. If so, I check whether an object in app.data (eg: app.data.user_profile is empty or not(am storing the profile details there). If empty, I would do an AJAX API call to get the profile details. When the profile details is obtained, I would use app.form.fillFromData() method to fill the form. Documentation here: https://framework7.io/docs/form.html#form-data-app-methods
Make sure to name the form as well as the input elements in that form, and the same name should be use in the object(key name) when calling the fillFromData() function.
And one more thing, for the routes, /settings/ path, I used url instead of the componentUrl property to pass the url of the page.
This may not be the best solution, but am still learning. And it seems to have solved by current problem.
Thank you

Sending a var with file, accessing it in script & Displaying a hidden div

Currently there is a form in home.html page which allows us to submit data. After data is saved, displaying the same .html page but different div (message like - Congrts, your poll is created ....).
For this I am sending a boolean var dataSaved while sending file so that i can retrieve the boolean var & display the div.
I am submitting form like this -
<form class="" action="/home/newPoll" method="post">
<form>
My server.js looks like this -
app.post('/home/newPoll', function (req, res) {
const newPoll = new PollModel({
............//something here
});
PollModel(newPoll).save(function(error, data){
if (error) {
throw error;
console.error("User Data is not saved."+error);
} else {
console.log("User data saved successfully");// working fine
res.sendFile(__dirname+'/views/home.html', {dataSaved: true}); // this page is displayed also
}
});
});
if this var dataSaved is true, I want to display the div.
$(document).ready(function(){
............// some more code here, are working fine.
const dataSaved = <%= dataSaved %>;
console.log(dataSaved); // not getting this
if (dataSaved ) {
$("#newPollDiv").hide();
$("#myPollDiv").hide();
$("#pollCreated").show();
}
}
I am not using any view template.
kindly suggest, also if any other way to do this.
You need to send the form data in an AJAX request. Right now it looks like the client isn't receiving your response at all, because you are refreshing the page after POSTing the form data.
Since you're using jQuery, I suggest you read: https://api.jquery.com/jquery.post/
Basically, you use the function $.post with the URL to send the form data to and a callback to display the divs as inputs.
Example:
$.post("/your/api/endpoint", function(response) {
$("#newPollDiv").hide();
//...
});

Processing variables send with nodejs inside jade

I have a script sending a matrix, something like [[1,2,3,4], [7,6,5,4], [2,3,4,5]]. When I send it using res.send(JSON.stringify(dataArray)); and display it in jade using h1#results I do indeed see the format is correct.
However I would like to use this data inside the google charts. My intuition would say to present the data like this: data.addRows = results;. This is however not the case because jade doesn't understand that I mean the variable send.
I suspect I do not understand some basic principle behind jade. I understand that most of jade/html is fixed and that only code within "script" tags get executed but as far as I can see all code inside google's function drawChart() {) is within a script tag.
EDIT
My new ajax script:
$(function() {
$('#search').on('keyup', function(e){
if(e.keyCode === 13) {
var parameters = { search: $(this).val()};
$.get('/seraching', parameters, function(data) {
$('#results').html(data);
console.log('parsing json');
var chartData = (data);
console.log(chartData[0])
drawChart(chartData, parameters.search);
});
}
});
});
So, there several issues at play here. First, using Express and Jade to deliver a processed template, using AJAX with a search parameter to get some data, and using an Express route to send some data based on the search parameter you send it.
Initially you want Express and Jade to set up the main page:
main.jade
html
head
script(src='googlechart.js')
script(src='myJS.js')
body
title Title
h1 Heading
input("type='text', id='search'")
button("id='submit'")
So here we ensure that Google chart is loaded as well as the JS that will contain your AJAX call. I've also included the text box for the search parameter.
In your Express app you would render the page like this:
app.get('/', function (req, res) {
res.render("main.jade");
});
myJS.js
First set up the chart object. Then, when the submit button is clicked, use the value of the search field in the ajax data property. Once the promise is resolved, display the results.
var chart = new google.visualization.DataTable();
$('#submit').click(function () {
var param = $('#search').val();
$.ajax({
url: '/getdata',
dataType: 'JSON',
data: { search: param }
}).done(function (data) {
// note that jQuery automatically parses JSON for you
chart.addRows(data);
});
});
But! In order to do this you need to set up a route in Express to handle the AJAX call which would look like:
app.get('/getdata', function (req, res) {
var param = req.param('search');
// filter data by search param
res.send(JSON.stringify(data));
});
So, you only need Jade once to set up the main template. It's the Express routes that you need to deliver the JSON data when you submit an AJAX request.
Hope that's a better answer :) Oh, there might be a couple of typos in here because I've not used Express for a while, but I'm pretty sure it's correct.

How to Make a Feed From User Submitted Posts

I'm trying to figure out how to use AJAX to create a Twitter-like feed that displays user's posts on the same page immediately after they push the submit button. It would be an infinite-feed site that would have a "more" button at the bottom.
All I'm trying to make is a simple page containing a textarea box with a submit button and to have user submissions appear below the box as they are submitted.
If possible, a walk through or discussion of the script needed to do this would be great.
Thanks so much
All you need is a server-side script with an SQL query that would return newer posts.
have your javascript store a variable of the date or of the last post id (used PHP for clarification):
result = mysql_query("SELECT ID,POST FROM POSTS WHERE DATE>" . $_GET['date']); //or use WHERE ID> $_GET['id']
while(rows[] = mysq_fetch_array(query));
print json_encode(rows);
now you have a server-side script that will return new posts, so all you have to do is write javascript function for the more button:
updatePosts = function () {
$.ajax({
url: 'serversiderUrl?lastId=' + last_id, //last_id is global variable for the id of the last post on the page
success: function(data){
data = JSON.parse(data);
for(i in data){
$('#posts_container').append(data[i].post); //do your appending functions here
last_id = data[i].id;
}
}
}
now for posting new entries create a server-side script of your favorite language that handles new posts:
result = mysql_query("INSERT INTO POSTS VALUES(''," . urldecode($_POST['POST']) . ")");
now for the client side:
submit_post = function(){
$.ajax({
type: 'POST',
url:'yourposturl',
data: "post=" + encodeURIComponent($('#textArea').text()),
success: function(){
updatePosts(); // call the function that update the posts so the new entry is now added to the page
}
});
}
Now bind the functions to the appropriate buttons when the document is fully loaded:
$(document).ready(function (){
$('#moreButtonId').click(updatePosts);
$('#submitButtonId').click(submitPost);
});
There are many ways such as the submit button kept sending it to the database while we'd append text to a container underneath. Or we can update the container underneath to create a container (page) that are similar, after the ajax response is successful then we append the data to the container beneath
$.post(url,function(data){
//Here you can append the data responsed by the ajax request to the container underneath
});
But you have to have a exactly same view with a conatiner (feed container) existing in the currently page

Categories