NodeJS Pass data from current page to another - javascript

I want to make a User management system in Node. I have a page where all users are listed in a table. After I press the edit button, it should go to the user page with all the information of that user. But I don't know how to pass the username into my Node function.
This is my table for the users. the Benutzerverwaltung_Mitareiter is the page where the information from the user is getting shown
<tbody>
<%for (var i = 0; i < users.length; i++) { %>
<tr>
<td><%=users[i].username%></td>
<td><%=users[i].admin%></td>
<td>
<form action="/users/Benutzerverwaltung_Mitarbeiter">
<button id="buttonAnzeigen"
type="submit"
name="username"
href=""
value="<%users[i].username%>"
data-toggle="tooltip"
title="Anzeigen">
<i class="fas fa-search"></i>
</button>
</form>
</td>
</tr>
<%}%>
</tbody>
I passed the username of the user into the value of the button.
And this is how I get the data for the table
router.route ('/Benutzerverwaltung_Mitarbeiter').get(function (req, res) {
const username = req.body;
User.find(function (err, users) {
if (err)
return res.send(err);
res.render('Benutzerverwaltung_Mitarbeiter',{
users: users || [],
});
});
});
If someone can help me to get the function, I would be very thankful!

I suggest you to use some template engine, like ejs or jade. This form, you can use res.render and send json information for view. For more details consult the engine docs and res.render doc too.

Related

Making a sort by and load more system (NodeJS routes + MySQL)

I want to make a system that limits the number of posts that get displayed and a load more button that loads them from where the limit stoped previously WITH the capability to change the ordering of those same posts.
Right now I have:
html/ejs:
<main>
<div class="container">
<%
if(results.lenght != 0){
var i = 1;
results.forEach(function(results){
%>
<div class="post">
<div class="op"><%= results.username %></div>
<h2 class="post-title"><%= results.title %></h2>
<div class="content"><p class="post-content"><%= results.content %></p></div>
</div>
<% i++; }) %>
<% } else { %>
locals.message1 = 'No posts found :(';
<% } %>
</div>
<div class="load-container"><a class="load" href="">Load more</a></div>
</main>
dropdown to select sorting:
<div class="drop">
<button onclick="drop()" class="drop-btn">Sort by</button>
<form id="dropdown-content" class="dropdown-content" method="POST">
<button type="submit" formaction="/" value="1">Newest</button>
<button type="submit" formaction="/" value="2">Oldest</button>
<button type="submit" formaction="/" value="3">Popular</button>
</form>
</div>
routes:
router.get('/', authController.isLoggedIn, (req, res, next) => {
sql = 'SELECT posts.username, time, title, content, user_file, audio FROM posts JOIN user on posts.user_id = user.id';
db.query(sql, function(err, results, fields){
if(err) throw err;
else if(results.length!=0){
res.render('index', {
user: results: results, time: moment.utc(new Date(results.time)).fromNow()
});
}
else {
res.render('index', {
user: message: 'Sorry, we don\'t have any posts :(', message1: 'Very sad...', results: results
});
}
})
});
I was thinking of having two variables in the route that would store the limit. Sort of like this:
var limit1: 0; // where to start displaying posts
var limit2: 8; // how many to display before stopping
// ADD 8 to both when button is clicked
var limit = 'LIMIT ' + limit1 + ', ' + limit2 + ';' //combining it for LIMIT in MySQL
db.query(sql + limit, function(err, results, fields)...
The problem is that I don't know how to keep track of how many I've already loaded and how to pass that data from the load more button in the EJS file to the router. The only way I currently know how to do is with a post form but I'm guessing that wouldn't be good at all.
For the sorting I would want to do basically the same thing:
// when new sorting is selected
var sorting = sorting; //selecting a sorting algorithm based on the button clicked
// reset the limits when new sorting is selected
limit1 = 0; limit 2 = 8;
db.query(sql + sorting + limit, function(err, results, fields)...
But again I don't know how I would tell the route about the changes and how I would store the limits... I've tried some things but I couldn't get the variable from the EJS on button click to the route('/'... So if I only got one thing out of this I would want it to be the variable passing.
I'm assuming you are brining back some results with the page load first correct?
With that assumption you have your main loop to display the posts
<main>
<div class="container">
<%
if(results.lenght !== 0){
results.forEach(results =>{
%>
<div class="post">
<div class="op"><%= results.username %></div>
<h2 class="post-title"><%= results.title %></h2>
<div class="content"><p class="post-content"><%= results.content%>
</p></div>
</div>
<%}) %>
<% } else { %>
No posts found :(
<% } %>
</div>
<input type="hidden" id="postCount" value="<%=results.length%>">
<div class="load-container"><a class="load" href="">Load more</a></div>
</main>
(slight edits made to use arrow function, also not sure what the count was for? But its not really needed from what I can tell, if you needed the count you could always just use the length of the results as they would be the same.)
Now, you need an api route of some kind to pass the update variables to so you can make the request. It will be similar to the original route, so in the same route file you would have something like
router.get('/update/:sort/:start', authController.isLoggedIn, (req, res, next) => {
// place relevent SQL code here that uses the passed params
// then send back JSON object back to the browser
res.json(jsonresponse)
});
So, in this sample, you would be passing the sort and start argument as part of an XHR/Fetch request, as you can see above, we have placed a hidden variable with the length of the original request so we know how many were returned, we will pass that as the 'start' value to the update endpoint and tell SQL to start at that record
(Note, you could extend that route to have other limits passed etc, Also doing dynamic queries like this can open you up for a SQLinjection so you will need to sanities those before passing them to the SQL Query)
From here you will have a change event handler on your page, that will listen for change events on the dropdown, from there you will take the value of that and pass that to an XHR request that hits the api endpoint with the passed variables, ones it returns the JSON object you will simply loop over it and append to the screen, once the loop is done, grab the total from the hidden object and add the total from the returned object so the next request knows where you left off (more for the load more option assuming)

how to handle multiple parameters in express routes

I am developing a website using express and routing to handle http requests.
I am populating my html div elements using handlebars:
<div class="popup center" style="height: 15em;">
<h3 name="name" id="name">{{ active_name }}</h3>
<p name="description" id='description'>{{ active_desc }}</p>
</div>
Now I let the user to modify that elements using contenteditable="true".
With a button I would like to call a route passing all the fields that has been modified.
For now I was able to pass only one element (i.e. {{session.recipe}} that is the id of the recipe) but I would like to handle the modified name and description too.
<a href="/save-recipe/{{session.recipe}}" style="color: black;">
<button name="button" class="greyishBackground width45 right">
<p>Save</p>
</button>
</a>
In the index.js I'm doing this:
router.get('/save-recipe/:id/', function(req, res, next) {
var recipe_id = req.params.id;
console.log(req.body.name); // doesn't work - undefined
}
Since req.body.name is not working (it is undefined) I'm trying to find a way to pass to the route more parameters in order to handle them in the same way as I handled the recipe_id (i.e. req.params.id).
Can someone explain me how to do it?
Can I creat an object with name and description fields and pass only the object? How can I do it?
Or there is a way to make that req.body.name work?
router.get('/save-recipe/:id/:name/:desc', function(req, res, next) {
var recipe_id = req.params.id;
var recipe_name = req.params.name;
var recipe_name = req.params.desc;
}
req.body.name is undefined because you are not posting anything to the server.

How to display query results from a database in HTML using node.js

I am currently creating a webpage with node.js that makes queries to a MySQL database and displays the results in a table.
I want the page to display all the data in the database upon initial loading, but I also want to implement a filter where the user can fill in some fields and when the submit button is pressed, a new query will be made using the inputs and the results displayed on the page.
Here is the code I have so far:
In "app.js", I make a connection to the database and render it to the page:
var connection = mysql.createConnection({
// make connection
host: ...,
user: ...,
password: ...,
database: ...
});
connection.connect();
//routes
app.get("/", function(req, res){
var cmd = `SELECT * FROM myTable`;
connection.query(cmd, function(err, result, fields) {
if (err) throw err;
res.render('home', {result: result});
});
});
And in home.ejs, I iterate over each entry in result to create a row in the table:
<table>
<tr>
<th> ... </th>
.
.
.
</tr>
<% result.forEach(function(entry) { %>
<tr>
<td><%= entry.column1 %></td>
.
.
.
</tr>
<% }) %>
</table>
So the first part seems to be working (displaying all the data in the DB upon initial loading), but I am struggling to do the second part as I have no prior web development experience.
I currently have a in the page to accept user input and a associated with the form. However, I am not sure how I can use the user input inside myFunction() to perform another query to the database, and how to replace the current content of the table with the result of the new query.
Any help would be appreciated!
Ok so what you want to do is make client side filter of the data you already have in the view.
The problem is that the table is rendered server side, so how will you mutate the data on the client side after initial load?
The solution: set the data to a string on the window/global on render
<table id="results-table">
<tr>
<th> ... </th>
.
.
.
</tr>
<% result.forEach(function(entry) { %>
<tr>
<td><%= entry.column1 %></td>
.
.
.
</tr>
<% }) %>
</table>
<script>
window.results = results;
</script>
after that lets make a search box and submit button inside your template:
<input type="search" id="filter-searchbar"/>
<button id="filter-submit-btn"> submit</button>
Let's add an event to listen to search and a handler to filter out the data:
const filterSearchBar = document.querySelector('#filter-searchbar');
const filterSubmitBtn = document.querySelector('#filter-submit-btn');
filterSubmitBtn.addEventListener('click', () => {
// Next step.
})
Let's lets filter the window.results from the user's search input:
const filterSearchBar = document.querySelector('#filter-searchbar');
const filterSubmitBtn = document.querySelector('#filter-submit-btn');
filterSubmitBtn.addEventListener('click', () => {
const filteredResults = window.results.filter(result => {
// Not sure what you wanna filter by but imagine that it's by a property name.
return result.name === filterSearchBar.value;
});
// Final step
});
Final step is to rerender that data client side inplace of the table template:
const filterSearchBar = document.querySelector('#filter-searchbar');
const filterSubmitBtn = document.querySelector('#filter-submit-btn');
filterSubmitBtn.addEventListener('click', () => {
const filteredResults = window.results.filter(result => {
// Not sure what you wanna filter by but imagine that it's by a property name.
return result.name === filterSearchBar.value;
});
const resultsTable = document.querySelector('#results-table');
results.innerHTML = `<pre>${JSON.stringify(resultsTable)}</pre>`
});
Hopefully you understand that I used JSON.stringify to just show you the output is filtered. You'll need to do your own table templating at this point.

Implement Search Functionality Node JS/MySQL

Having some trouble properly implementing a search filter by the Pokemon Name on my Node JS/MySQL DB. When I search I am getting "search/?key=undefined 404 (Not Found)" Any ideas? Here is my search route
router.get('/search', function(req, res){
var mysql = req.app.get('mysql');
var sql='SELECT pokemonname FROM pokemon WHERE pokemonname LIKE "%' + req.key.query + '%';
sql = mysql.pool.query(sql, function(error, results, fields) {
if(error) {
res.write(JSON.stringify(error));
res.end();
} else {
res.status(200);
res.end();
}
});
});
Here is my handlebars file to render the search bar/search button
<table id="table">
<thead>
<th>Pokemon Name </th>
<th>Evolution Level </th>
<th>Move Name </th>
</thead>
<input type="text" class="search form-control" id="searchinput" placeholder="Pokemon Name">
<input type="button" class="btn btn-primary" value="Search" onclick="getUsers({{id}})"/>
<br>
<tbody>
{{#each pokemon}}
<tr>
<td>{{pokemonname}}</td>
<td>{{evolutionlevel}}</td>
<td>{{movename}}</td>
<td><button onclick="deletePokemon({{id}})">Delete</td>
<td>Update</td>
</tr>
{{/each}}
</tbody>
And finally my search.js function in JQuery
function getUsers(searchinput){
$.ajax({
type: 'GET',
url: '/search/?key=' + searchinput,
success: function(result){
window.location.reload(true);
}
})
};
Thanks for the help
Most occurences of {{id}} are used inside #each loop suggesting id is property of pokemon object. Meanwhile your getUser({{id}}) is used outside of this loop leading to undefined passed to binding variable id. I think that you want to pass value of text input to your getUser function instead, hence your name of formal parameter e.g. searchinput. You could use {{input value=searchinput}} from Ember helper and then getUser({{searchinput}}) in your button. Also pay attenttion to encoding query params passed to called AJAX service.

Ajax request for a specific item in a list

I'm new to AngularJS and I don't know how to accomplish a task. In my system I have a database with two tables: "Customers" and "Offices". This is a 1:N relation. In my HTML page I have a list (actually is a table) that contains info about the customers (info extracted from the "Customers" table). For each row of the table, you can find a button. If you click on that button some infos about the offices of THAT customer are loaded from the database.
The first part is quite simple. This is the Angular service that loads customers info:
angular.module("app").factory("Customer", ["$resource",
function($resource){
return $resource("/customers/list",
{format:'json'},
{
find: {
method:'GET'
}
});
}]);
This is the Angular controller that exposes an array of customers:
angular.module("app").controller("customersController", ["Customer", "$scope",
function (Customer, $scope){
var customers = new Array();
var metacustomers = Customer.find(function(){
for(var i=0; i<metacustomers.results.length; i++){
customers[i] = new Object();
customers[i].customerName = metacustomers.results[i].customer_name;
customers[i].customerID = metacustomers.results[i].customer_ID;
}
$scope.customers = customers;
});
}]);
And this is the part of the view that shows info:
<table>
<thead>
<th></th>
<th></th>
<th></th>
</thead>
<tr data-ng-repeat="customer in customers | filter:query">
<td>
+
</td>
<td>
<strong>{{customer.customerName}}</strong>
</td>
<td>
<div>
<a title="Modify customer" href="/customers/post/{{customer.customerID}}">
</a>
<a title="Delete customer" href="/customers/delete/{{customer.customerID}}">
</a>
</div>
</td>
</tr>
</table>
All of this looks like:
The problem arrives with the second task. When I click on the "+" button I must load the offices infos about THAT customer (the customer on the same row of the button). I need the customerID to retrieve these infos and I have it. But, how can I say to Angular to load exactly the info belongs to the right customer? I don't know how to model this situation. I need your help. Thank you in advance.
You can pass the customer to the ng-click directive like so:
+
And then create an expand function in your controller which takes a customer as its input. Something like this:
$scope.expand = function(customer){
//fetch the customer
};

Categories

Resources