Can't reference array's item by name indexOf() - javascript

So I have this dataBase that is gonna be used in the app.get function below. The goal is to make the app.get send the first item in the array dataBase (which is the array "posts") as the value for the object's atribute "posts:". In case I don't set any names for the array and call it in the app.get as "posts: dataBase[0]", it works - the forEach() can read it; otherwise, it seems it's not called as an array since the .forEach() can't be used.
const dataBase =
[
posts = [
{
title: "Post 1",
text: "Lorem ipsum",
stars: 2
},
{
title: "Post 2",
text: "Lorem ipsum"
},
{
title: "Post 3",
text: "Lorem ipsum",
stars: 5
}
],
ads = {}
]
app.get("/posts", (req, res)=>{
res.render("posts",
{
title: "Basic Project: Posts",
posts: dataBase[dataBase.indexOf("posts")]
}
)
})
IN THE .ejs FILE:
<article class="content">
<h1>POSTS:</h1>
<% posts.forEach(item=>{ %> <!-- ERROR: forEach is not a function -->
<div>
<% if (item.stars){ %>
<% for(let i = 0; i < item.stars; i++){ %>
<img src="images/star.pgn">
<% } %>
<% } %>
<h3><%= item.title %></h3>
<p><%= item.text %></p>
<br>
</div>
<% }) %>
</article>

You're mixing the concepts of arrays and objects. In JS they are not the same thing.
Your database should probably be:
const dataBase = {
posts: [
{
title: "Post 1",
text: "Lorem ipsum",
stars: 2
},
{
title: "Post 2",
text: "Lorem ipsum"
},
{
title: "Post 3",
text: "Lorem ipsum",
stars: 5
}
],
ads: {}
}
Then you can access posts simply with dataBase.posts.
Here is some more details about arrays vs objects: https://medium.com/#zac_heisey/objects-vs-arrays-42601ff79421.

Related

Iterate the data dynamically using Tiny Slider JS

I have array of objects that includes name and description. My goal here is to display the name and description dynamically in my image carousel with the help of Tiny Slider js.
I try the following attempt but failed.
Use .getElementById() to get the slider element and .map() to render the data inside the object but unfortunately the whole data was rendered in one slider only.
The actual result:
index.html
<div id="sliderCont" class="my-slider">
<div>
<div class="slide">
<div class="slide-img" style="background-image: url('src/images/img-1.jpg')">
View More
</div>
<br>
<div class="slide-info">
<h3 id="project-name"></h3>
<p id="project-description" class="subtext"></p>
</div>
</div>
</div>
</div>
app.js
const project = [
{
image: "",
name: "Project 1",
description: "Project Description here.",
},
{
image: "",
name: "Project 2",
description: "Project Description here. 2",
},
{
image: "",
name: "Project 3",
description: "Project Description here. 3",
},
{
image: "",
name: "Project 4",
description: "Project Description here. 4",
},
];
document.getElementById("project-name").innerHTML = project.map((proj) => proj.name);
document.getElementById("project-description").innerHTML = project.map((proj) => proj.description);
Tiny Slider Config
let slider = tns({
container: ".my-slider",
slideBy: 1,
speed: 200,
nav: false,
controlsContainer: "#controls",
prevButton: ".previous",
nextButton: ".next",
preventScrollOnTouch: "auto",
autoplay: true,
autoplayButtonOutput: false,
responsive: {
1600: {
items: 4,
gutter: 20,
},
1024: {
items: 3,
gutter: 20,
},
768: {
items: 2,
gutter: 20,
},
480: {
items: 1,
},
},
});
project.map((proj) => proj.name)
...returns an array:
["Project 1", "Project 2", "Project 3", "Project 4"]
When assigning this array to document.getElementById("project-name").innerHTML it is converted to the string "Project 1,Project 2,Project 3,Project 4".
So you're essentially assigning this string to the .project-name innerHTMLvalue:
document.getElementById("project-name").innerHTML = "Project 1,Project 2,Project 3,Project 4";
The same thing happens with:
document.getElementById("project-description").innerHTML = project.map(
(proj) => proj.description
);
Instead, first iterate, forEach(), over the project array, and in the loop block add a slide.
To create multiple slides use cloneNode() to copy the .slide DIV. (Since you're duplicating this DIV and it's child nodes, don't use IDs. Use class names instead: .project-name and .project-description.) And append the new node to the .slide's parentNode.
After the project array loop is exited, remove, removeChild(), the original .slide-info DIV.
const project = [
{
image: "https://source.unsplash.com/random?w=200",
url: "p1.html",
name: "Project 1",
description: "Project Description here."
},
{
image: "https://source.unsplash.com/random?w=200",
url: "p2.html",
name: "Project 2",
description: "Project Description here. 2"
},
{
image: "https://source.unsplash.com/random?w=200",
url: "p3.html",
name: "Project 3",
description: "Project Description here. 3"
},
{
image: "https://source.unsplash.com/random?w=200",
url: "p4.html",
name: "Project 4",
description: "Project Description here. 4"
},
];
// get target DIV, containing .slide-img, .project-url, .project-name, and .project-description
const slide = document.querySelector(".slide");
// iterate over project array
project.forEach(proj => {
// make a clone of .slide for new slide
const newslide = slide.cloneNode(true);
// add image background to .slide-img div
newslide.querySelector(".slide-img").style.backgroundImage = `url('${proj.image}')`;
// add url href to .project-url anchor tag
newslide.querySelector(".project-url").href = proj.url;
// add name to .project-name header
newslide.querySelector(".project-name").innerHTML = proj.name;
// add description to .project-description paragraph
newslide.querySelector(".project-description").innerHTML = proj.description;
// add slide to .slide parent
slide.parentNode.appendChild(newslide);
});
// remove original slide
slide.parentNode.removeChild(slide);
<div>
<div class="slide">
<div class="slide-img">
<a class="project-url" href="" style="color: white;">View More</a>
</div>
<br>
<div class="slide-info">
<h3 class="project-name"></h3>
<p class="project-description subtext"></p>
</div>
</div>
</div>

Incorrect sorrting by insert with forEach

I have an array with objects. I want to import these into a sqlite3 database. I
do this with a forEach loop. It works well. But I wonder why the objects are not
imported in the order I put them into the database.
This is what I do
const comments = [
{post_id: 1, comment: "lorem ipsum comment 1", comment_author: "user 1"},
{post_id: 2, comment: "lorem ipsum comment 2", comment_author: "user 1"},
]
comments.forEach(c => {
sql = `INSERT INTO comments(post_id, comment, comment_author) VALUES (?,?,?)`
db.run(sql, [c.post_id, c.comment, c.comment_author], (err) => {
if (err) { console.log(err.message)};
});
});
If I now execute a select, I get the following pure order (take a look to post_id):
[
{id: 1, post_id: 2, comment: "lorem ipsum comment 2", comment_author: "user 1"},
{id: 2, post_id: 1, comment: "lorem ipsum comment 1", comment_author: "user 1"}
]
Question Why is this happening? And what can I do to change the behavior.
Expected result:
[
{id: 1, post_id: 1, comment: "lorem ipsum comment 1", comment_author: "user 1"},
{id: 2, post_id: 2, comment: "lorem ipsum comment 2", comment_author: "user 1"}
]
Note I Guess it has something to do with the async of javascript.
You are right with your guess: I Guess it has something to do with the async of javascript.!
let placeholders = comments.map((c) => '(?)').join(',');
let sql = 'INSERT INTO comments(post_id, comment, comment_author) VALUES ' + placeholders;
// output the INSERT statement
console.log(sql);
db.run(sql, [comments], (err, results, fields) => {
if (err) {
return console.error(err.message);
}
// get inserted rows
console.log('Row inserted:' + results.affectedRows);
});
// close the database connection
db.close();

Angular - Get array from JSON file

Sorry for the noob question but I am just getting started with Angular. I have this array declared in services.js:
var articles = [{
id: 1,
title: 'Article 1 Title',
intro: 'Article 1 Intro',
image: 'photo.jpg',
published: '27/10/2016',
text: 'Article 1 Text',
url: 'http://www.domain.com'
}, {
id: 2,
title: 'Article 2 Title',
intro: 'Article 2 Intro',
image: 'photo.jpg',
published: '27/10/2016',
text: 'Article 2 Text',
url: 'http://www.domain.com'
}];
Now that everything works fine in my Angular App I want to read this array from a JSON file that can be found, for example, at www.domain.com/articles.json and it looks like this:
{
"articles": [
{
"id": 1,
"title": "Article 1",
"intro": "Article 1 Intro",
"image": "image.png",
"published": "27/10/2016",
"text": "Article 1 Text",
"url": "http://www.domain.com/article-1"
},
{
"id": 2,
"title": "Article 2",
"intro": "Article 2 Intro",
"image": "image.png",
"published": "27/10/2016",
"text": "Article 2 Text",
"url": "http://www.domain.com/article-2"
}
]
}
How can I make this change?
To get the data of the file in your Angular app, you'll have to get the file's contents through an HTTP request. The easiest way to do this is by using the $http service.
Example (with relative url):
$http.get('/articles.json').then(function (response) {
var articles = response.data.articles;
// Do something with articles...
});
The callback function you're passing to the then method will be called when the HTTP request was successful. Note that your data will only be available in this callback function. Also don't forget to include a dependency to the $http service in your controller. ;)

React get object inside another object

I got a simple json api and want to display some of objects fields with react.
The api has the following structure:
{"data" : [
0: Object
id: "1"
type: "Item"
attributes: Object
title: "lorem impsum"
body: "lorem ipsum"
1: Object
id: "2"
....
]}
And I'm trying to display attributes items(title, body)
The problem is that
this works fine and displays id
{items.map(item =>
<div>{item.id}</div>
)}
BUT
If I try to use {item.attributes.title} I receive
TypeError: Cannot read property 'title' of undefined
So item.attributes is undefined.
What's wrong here?
this is the most common error that occurs because you never know what object you are going to get from server, so it is always good way to check before accessing the data, so you can try
{item.attributes && item.attributes.title ? item.attributes.title : 'print something for missing title' }
//item.attributes && item.attributes.title means if both the values are present in Object
This should help you. I couldn't find an error in your program. So, I've created a working example to solve this.
const data = {
"data": [{
id: "1",
type: "Item",
attributes: {
title: "lorem impsum",
body: "lorem ipsum",
}
}, {
id: "1",
type: "Item",
attributes: {
title: "lorem impsum",
body: "lorem ipsum",
}
}, {
id: "1",
type: "Item",
attributes: {
title: "lorem impsum",
body: "lorem ipsum",
}
}, {
id: "1",
type: "Item",
attributes: {
title: "lorem impsum",
body: "lorem ipsum",
}
}]
}
class Sample extends React.Component{
render() {
return <div>
{
data.data.map((el) => {
return <div>
<h1>{el.id}</h1>
<div>{el.attributes.title}</div>
<div>{el.attributes.body}</div>
</div>
})
}
</div>
}
}
ReactDOM.render(<Sample/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

Best way of getting the list of html values and populating them in a backbone-requirejs application

Here is the scenario, the page is made of backbone views (multiple views, around 20) and about 30 templates. All structured using requirejs architecture. But some of the values in the template such as heading tiles, sub heading titles and drop down values come from a single json object returned by an ajax request during page load. How do I pass these values around multiple templates?
If I understood correctly then you can do in the following way:
Link to jSFiddle
HTML:
<div id="container"></div>
<script type="text/template" id="modelTemplate">
<h1 data - id = "<%=Id%>" > <%= Name %> </h1>
<ul>
<%_.each(Titles,function(title){%>
<%=_.template($("#titleTemplate").html())(title)%>
<%});%>
</ul>
</script>
<script type="text/template" id="titleTemplate">
<li> <%= Name %>
<ul>
<%_.each(SubTitles,function(subTitle){%>
<%=_.template($("#subTitleTemplate").html())(subTitle)%>
<%});%>
</ul>
</li>
</script>
<script type="text/template" id="subTitleTemplate">
<li> <%= Name %> </li>
</script>
And JavaScript (instanceOfModel is some model that you populates with ajax request):
var model = Backbone.Model.extend({});
var instanceOfModel = new model({
Id: 1,
Name: "Some Name",
Titles: [{
Name: "First Title",
SubTitles: [{
Name: "SubTitle Name 1"
}, {
Name: "SubTitle Name 2"
}]
}, {
Name: "SecondTitle",
SubTitles: [{
Name: "SubTitle Name 3"
}, {
Name: "SubTitle Name 4"
}]
}, {
Name: "Last Title",
SubTitles: [{
Name: "SubTitle Name 5"
}, {
Name: "SubTitle Name 6"
}]
}]
});
var modelTemplate = _.template($("#modelTemplate").html());
$("#container").append(modelTemplate(instanceOfModel.toJSON()));

Categories

Resources