React get object inside another object - javascript

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>

Related

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

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.

JSON.parse not returning the orginal object

I am storing a java script object in the DB by converting that into the string by using JSON.stringify, But when i want to retrieve that object from DB i use the JSON.parse. But the JSON.parse is not returning the original object. In the below console screenshot it can be seen that the object Obj had some changes after it is converted into string and then parsed. So how can i get back the original object after doing JSON.stringify
The Object is as below:
var Obj = {
onchange: function(){
},
validate: function(obj){
},
elements: {
"list": {
menu: [{
caption: "Append an",
action: Xonomy.newElementChild,
actionParameter: "dd"
}]
},
"item": {
menu: [{
caption: "Add ",
action: Xonomy.newAttribute,
actionParameter: {name: "label", value: "something"},
hideIf: function(jsElement){
return jsElement.hasAttribute("label");
}
}, {
caption: "Delete this ",
action: Xonomy.deleteElement
}, {
caption: "New before this",
action: Xonomy.newElementBefore,
actionParameter: "sas"
}, {
caption: "New after this",
action: Xonomy.newElementAfter,
actionParameter: "aa"
}],
canDropTo: ["list"],
attributes: {
"label": {
asker: Xonomy.askString,
menu: [{
caption: "Delete this",
action: Xonomy.deleteAttribute
}]
}
}
}
}
};
As already mentioned in comments - you can't serialize JS functions with JSON.stringify. Please take a look at serialize-javascript library to store the functions.

Filter array by tag Vuejs

I'm currently working with vuejs and vuex. Here is my issue :
I have a store with all the data
state: {
articles: [{
title: "Article 1",
id: 1,
tag: "Tutorial"
}, {
title: "Article 2",
id: 2,
description: "Article 2",
tag: "Review"
}
}]
}
On the homepage, I want to display all kind of articles. On the tutorial page I only want to display articles with tag "tutorial", etc...
I'm using vue-router. I'm working with a computed property and a v-for so I can loop in the articles.
computed: {
articles() {
if (this.$route.meta.title == 'Tutorial') {
return this.$store.state.articles.tag == 'Tutorial'
}
if (this.$route.meta.title == 'Review') {
return this.$store.state.articles.tag == 'Review'
}
else if (this.$route.meta.title == 'Home') {
return this.$store.state.articles
}
}
}
I know that return this.$store.state.articles.tag == 'Tutorial' can't work, I'm looking for a way to code it correctly but I'm stuck!
Also, if you have a completely different and better way to do it, feel free to tell me!
Thank you for your time :)
As everybody mentioned you will need to use filter but as a pattern you should structure it with vuex getters
when you access properties from vuex state do not to access them directly but the correct thing is to use getters
Vuex store e.x.
const store = new Vuex.Store({
state: {
articles: [
{
title: "Article 1",
id: 1,
tag: "Tutorial"
},
{
title: "Article 2",
id: 2,
description: "Article 2",
tag: "Review"
}
]
},
getters: {
allArticles: state => {
return state.articles
},
tutorialArticles: state=>{
return state.articles.filter(article=>articles.tag=='Tutorial')
},
reviewArticles: state=>{
return state.articles.filter(articles=>articles.tag=='Review')
}
}
})
//end of vuex store
Then in your "all articles" component you use
computed:{
articles(){
return this.$store.getters.allArticles;
}
}
Then in your tutorial articles component you use
computed:{
articles(){
return this.$store.getters.tutorialArticles;
}
}
This is very important because if you need to change the code for the filter method you do it in one place and thats the purpose of using Vuex
Probably the best way is using .filter()
var obj = {state: {
articles: [{
title: "Article 1",
id: 1,
tag: "Tutorial"
}, {
title: "Article 2",
id: 2,
description: "Article 2",
tag: "Review"
}
]}}
var filtered = obj.state.articles.filter(o=>o.tag == "Tutorial");
console.log(filtered)

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. ;)

Angularjs JSON treeview, json format issue

I'm trying to implement a JSON treeview with this plugin
My issue is this line :
$scope.structure = { folders: [
{ name: 'Folder 1', files: [{ name: 'File 1.jpg' }, { name: 'File 2.png' }], folders: [
{ name: 'Subfolder 1', files: [{ name: 'Subfile 1' }] },
{ name: 'Subfolder 2' },
{ name: 'Subfolder 3' }
]},
{ name: 'Folder 2' }
]};
In my case, I'm reading a file that returns me a JSON format
[
{
"item": {
"title": "Kids"
},
"children": [
{
"item": {
"title": "HELLO"
},
"children": []
}
]
}
]
I thought using JSON.parse(myFileContent) should have been enough for having the same data structure as in the $scope.structure but the data isn't displaying, i'm not getting errors.
How can I parse my file content to make it work ?
First, the structure should be an object, since the directive differentiates "folders" from "files". So, considering you already define child elements inside a children property, you could wrap your array (assuming it's called content) into an object like so:
$scope.structure = {
"children": content
};
Then, you'll need to override the default values for the property names in which the directive will try to get the values.
$scope.structureOptions = {
foldersProperty: "children",
displayProperty: "item.title"
};
And last, you add the tree-view-options attribute to the HTML element.
<div tree-view="structure" tree-view-options="structureOptions"></div>

Categories

Resources