Node.js Cheerio returning empty with no errors - node.js

i am trying to get data from table with structure like this:
<table id="ros_table" class="info" style="display: none;">
<tr>
<th>First</th>
<th>Second</th>
<th>Third</th>
<th>Forth</th>
<th>Fifth</th>
<th>Six</th>
</tr>
<tr>
<td style="white-space: nowrap;">120241</td>
<td style="white-space: nowrap;">69801:001:0255</td>
<td>Name</td>
<td>Name 2</td>
<td><span style="white-space: nowrap;">90400 m<sup>2</sup></span> <span style="white-space: nowrap;">(9.04 ha)</span></td>
<td style="white-space: nowrap;">jah</td>
</tr>
And the code im useing is this:
fetchData(url).then( (res) => {
const html = res.data;
const $ = cheerio.load(html);
const statsTable = $('.table#ros_table > tr');
statsTable.each(function() {
let title = $(this).find('td').text();
console.log(title);
});
})
async function fetchData(url){
console.log("Looking for stuff you need...")
// Make the call
let response = await axios(url).catch((err) => console.log(err));
if(response.status !== 200){
console.log("Blah, this did not work out");
return;
}
return response;
}
It works fine with just a simple que, but for some reason i can get it to work for this table.

You need to return something out of each .then() block, i assume you want something like this?:
fetchData(url).then( (res) => {
const html = res.data;
const $ = cheerio.load(html);
const statsTable = $('.table#ros_table > tr');
return statsTable.map(function() {
return $(this).find('td').text();
});
})

Related

Show detail Button in table not working(instead pages gets reload) and Not getting all the data properly of the table from mongodb

As I click on the Show detail button I should get an alert/more info of the user but instead of that the page gets reload. Basically on 'show details' button the 'OnClick' function is not getting executed.
Why am I getting no enteries found after clicking on 'show details'
Fetching data from Database and setting it in 'clientTable' variable:
React.useEffect(()=>{
window.onload=()=>{
const datatablesSimple = document.getElementById('datatablesSimple');
if (datatablesSimple) {
new DataTable(datatablesSimple);
}
const fetchClients = async ()=>{
const res = await axios.get("/users")
setClientTable((clientTable)=>{return clientTable=res.data;})
console.log(clientTable)
}
fetchClients()
}
},[]);
Nodejs code for fetching all the Clients
router.get("/", async(req, res) => {
try{
const allclients = await User.find();
res.status(200).json(allclients);
}catch(err){
res.status(500).json(err);
}
});
HTML code of rendering the table in frontend:
<tbody>
{clientTable.map((User, index)=>(<>
<tr key={index}>
<td>
<Link to="/details" state={User}
style={{textDecoration:'none',
color:'black'}} > {User.username}
</Link>
</td>
<td>{User.email}</td>
<td>{User.dob}</td>
<td>{User.city}</td>
<td>{User.services}</td>
<td><button onClick={handleRowClick}> show details</button></td>
</tr>
</>
))}
</tbody>
handleRowClick method implementation:
const handleRowClick = (e) => {
e.preventDefault();
alert("Hello")
//setShowPopup(true);
}

TypeError: users.map is not a function React js

am stuck with a problem , am try to solve it lots of time but am not able to solve it , please try to fix my error. If you have any query please free feel to ask.
Userdata.js
This is the userdata.js file where I want to load my all data which are in backend database
import React, { useEffect, useState } from "react";
import { Link,useParams } from "react-router-dom";
import Axios from 'axios';
const UserData = () => {
const [users, setUser] = useState({
title : "",
description : ""
});
const {id} = useParams();
useEffect(() => {
AllUsers();
}, []);
const AllUsers = async () => {
const res = await Axios.get(`http://localhost:3000/${id}`);
console.log(res.data);
setUser(res.data)
};
return (
<div>
<div className="container">
<table className="table table-hover table-bordered mt-5">
<thead>
<tr>
{/* <th scope="col">No</th> */}
<th scope="col">Title</th>
<th scope="col">Details</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{users.map((user, index) => (
<tr key={index}>
<th scope="row">{user.id}</th>
<td>{user.title}</td>
<td>{user.description}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
};
export default UserData;
users looks to me to be an object, not an array. The map() function exists only on Array's prototype, so you can't call it on your users object. Did you mean to initialize users like this?
const [users, setUser] = useState([{
title : "",
description : ""
}]);
The map method is defined on on array and not on objects. Lets look at your code
const [users, setUser] = useState({
title : "",
description : ""
});
In UserData component you defined an object state with properties title and description. So users will be an object with those properties. Thus when you try to apply map on the users object it fails since map is not a function defined on objects.
Instead if you want to have an array of users with those two properties you can declare the state as follows
const [users, setUser] = useState([{
title : "",
description : ""
}]);

How to display mongoDB collection in html?

I am a beginner with mongoose and would like to display a mongoDB document(s) from "exColl" collection in a file called "example.ejs" in a basic html list however I have hit various problems. There are other posts on this topic yet I remain stumped by this.
-I do have a working chunk of code that outputs all documents from exColl.find({}) using res.json, obviously putting them in json format. However I have been unable to adapt this code into something that works using res.render for example.
-When I define a variable in app.js and try to access it in example.ejs the variable is not found, therefore even if I could save the results of exColl.find({}) in a variable I don't see how I would be able to enter it into the HTML
Clearly I don't know what I don't know which is very frustrating. If someone could help fill my conceptual gaps that would be fantastic.
---Edit----
Adding a snippet I have tried
app.get("/example", function (req, res){
exColl.find({})
.exec(function (err, examples){
if (err) {
res.send("an error has occurred")
} else res.render(examples: examples);
});
});
In .ejs file
<p> <%= examples %> </p>
Your problem seems to be the EJS syntax which you should review here: EJS Docs. Consider the following test project structure:
.
├── index.js
├── package.json
├── setup.js
└── views
├── index.ejs
└── table.ejs
I create a test DB with setup.js so that we have some dummy posts to display:
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:8081/test", {
useNewUrlParser: true
});
const Post = mongoose.model("Post", {
title:String,
body: String
});
const toMake = [
{title: "hello", body: "world"},
{title: "foo", body: "bar"},
{title: "fizz", body: "buzz"},
{title: "a", body: "b"}
];
Post.insertMany(toMake)
.then(()=>{
console.log("done");
mongoose.connection.close();
})
.catch(err => console.error(err));
I create an EJS template views/table.ejs to render my posts as a table:
<table>
<thead>
<tr>
<th>Title</th>
<th>Body</th>
</tr>
</thead>
<tbody>
<% posts.forEach(post => { %>
<tr>
<td><%= post.title %></td>
<td><%= post.body %></td>
</tr>
<% }) %>
</tbody>
</table>
I then create an EJS template views/index.ejs to use the table template
<main>
<h1>Posts</h1>
<%- include("table", {posts}); %>
</main>
I also make a server to respond to requests in index.js and run it with node index.js:
const express = require("express");
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:8081/test", {
useNewUrlParser: true
});
const app = express();
const Post = mongoose.model("Post", {
title: String,
body: String
});
app.set("view engine", "ejs");
app.get("/", async (req, res) => {
const posts = await Post.find({});
res.render("index", {posts});
});
app.listen(3000, () => console.log("Listening"));
And when I curl localhost:3000 I get the rendered HTML:
<main>
<h1>Posts</h1>
<table>
<thead>
<tr>
<th>Title</th>
<th>Body</th>
</tr>
</thead>
<tbody>
<tr>
<td>hello</td>
<td>world</td>
</tr>
<tr>
<td>foo</td>
<td>bar</td>
</tr>
<tr>
<td>fizz</td>
<td>buzz</td>
</tr>
<tr>
<td>a</td>
<td>b</td>
</tr>
</tbody>
</table>
</main>
No matter what, I will need to feed data to the res.render() function and populate the render scope with all the data needed to render.
However, I have made table.ejs reusable. So lets say that I have another page that I want to be able to show some of the posts in a tabular fashion.
I have another EJS template: views/profile.ejs that looks like this:
<main>
<h1>2 Posts</h1>
<%- include("table", {posts: posts.slice(0, 2)}); %>
</main>
And I add another route to my application at /sliced:
app.get("/sliced", async (req, res) => {
const posts = await Post.find({});
res.render("profile", {posts});
});
Whenever I curl localhost:3000/sliced I get only the first 2 items in the posts since I only populated the include's scope with a slice of all the posts:
<main>
<h1>2 Posts</h1>
<table>
<thead>
<tr>
<th>Title</th>
<th>Body</th>
</tr>
</thead>
<tbody>
<tr>
<td>hello</td>
<td>world</td>
</tr>
<tr>
<td>foo</td>
<td>bar</td>
</tr>
</tbody>
</table>
</main>

pages.forEach() is not a function

I am trying to display a list of items from a mongodb database in a Node.js application. I am using ejs as a templating engine. I am encountering the following error on the page:
Code for router:
const express = require('express');
const router = express.Router();
// Get page model
var Page = require('../models/page');
// GET page index
router.get('/', function(req, res) {
Page.findOne({}).sort({sorting: 1}).exec(function(err, pages) {
res.render('admin/pages', {
pages: pages
});
});
});
EJS code:
<%- include('../_layouts/adminheader') %>
<h2 class="page-title">Pages</h2>
Add a new page
<br><br>
<table class="table table-striped">
<thead>
<tr>
<th>Title</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<% pages.forEach(function(page) { %>
<tr>
<td><%= page.title %></td>
<td>Edit</td>
<td>Delete</td>
</tr>
<% }); %>
</tbody>
</table>
<%- include('../_layouts/adminfooter') %>
You should replace .findOne() by .find(), .findOne() only return one page object, whereas .find() return an array of objects:
Page.find({}).sort({sorting: 1}).exec(function(err, pages) {
res.render('admin/pages', {
pages: pages
});
});

template design for sending mail using nodejs

This is my code. When it runs in Postman it shows error like cannot get method.
var sendTempMail = function (req,res)
{
const nodemailer = require('nodemailer');
let transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
auth: {
user: 'transactions#gmail.com',
pass: 'qwertyu#'
}
});
let mailOptions = {
from: 'transactions#gmail.com',
to: 'xxxxxx#gmail.com','yyyyyyyy#gmail.com',zzzzzz#mydomain.com,//here to:receiver not accept more than one
subject: 'mail notification Test',
text: 'Hello !!!!!!!!!everything works fine'
html:<h1>Notification mail</h1>
<head>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
padding: 10px;
text-align: left;
}
</style>
</head>
<body>
<table style="width:100%">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>80</td>
</tr>
</table>
</body>
};
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log("mail not sent" +error.message);
}
console.log('success');
});
};
module.exports = {
newTemplate :newTemplate,
sendTempMail : sendTempMail
};
Please paste your error message with your question. However I can see one mistake that the HTML parameter has all raw html pasted there. It should be in string format.
Please check line no 44 in the code in below link
https://github.com/nodemailer/nodemailer/blob/master/examples/full.js

Resources