Display nested JSON data using React - reactjs

I'm displaying a Facebook feed, I've mapped the array that I've got from a JSON file to display the data, and so far so good.
let feedDisplay = feedArray.map((fbPost, index) => {
console.log(fbPost.attachments)
return (
<div key={index} >
<img src={fbPost.full_picture} />
<p>
{fbPost.message}
</p>
</div>
);
});
Now I want to display the data I get from fbPost.attachments which is an object with an array containing yet another object. I don't know what method I should use to access and display this.
{
data: [
{
description: 'some description',
media: { image: { src: 'source' } },
title: 'title',
},
],
};
What I want to display is everything inside data - description, media and title.

Related

is there a way to filter words in a sentence, then bold them?

Is there a way to bold certain words of a sentence in an object array? I thought about making like tags, then bolding those tags somehow? I am using React by the way. I am not sure of the logic on when to bold them but it makes more sense to me to identify the words in my data file..The goal is to be able to render the tags i choose as bolded from the given text in my data. So welcome and audience should show bold.
//decide on the bolded words//
const tags = ["Welcome", "Audience"];
//somehow bold the words///
function formatted() {
tags.map((tag) => {
return <span style={{ fontWeight: "bold" }}>{tag}</span>;
});
}
MY DATA
const Data = [
{
index: 0,
title: "Title 1",
layout: "wide",
content: [
{
type: "paragraph",
text: "Welcome the the course.",
},
{
type: "paragraph",
text: "The purpose of this training is to provide an overview.",
},
],
image: demo,
width: imageSize,
},
{
index: 1,
title: "Title 2",
layout: "standard",
content: [
{
type: "paragraph",
text: "The target audience for this course is anyone.",
},
{
type: "paragraph",
text: "Successful completion of this course is required.",
},
],
image: demo2,
width: imageSize,
},
]
//Or maybe alternatively bold them using innerhtml???//
//PARAGRAPH
function Paragraph({ text, size }) {
const formatted = text.replace(/(the word)/g, (it) => `<b>${it}</b>`);
return <span dangerouslySetInnerHTML={{ __html: formatted }}></span>;
}
If you can edit your MyData file, one option might be using the react-markdown library. You would then be able to put **Double Astorisks** around the word you would like in bold then just do:
//your component
...
return (
<ReactMarkdown>
{stringFromDataFile}
</ReactMarkdown>
)
You also have the benefit of having other markdown options like header, links, etc...
If you don't want to use external libraries you could also do something like this and avoid dangerouslySetInnerHTML.
My Data
In your data file, surround the objects you would like to have in bold with any specific key. I will use **.
ex:
content: [
{
type: "paragraph",
text: "**Welcome** the the course.",
},
{
type: "paragraph",
text: "The purpose of this training is to provide an overview.",
},
],
now you can just do:
const data = myData.split('**');
const boldOffset = myData.startsWith('**') ? 0 : 1;
return (
<>
data.map((string, index) =>{
// if we started with bold value
if(boldOffset === 0){
return (<span style={{ fontWeight: index % 2 === 0 ? "bold" : undefined }}>{string}</span>);
}else
return (<span style={{ fontWeight: index % 2 > 0 ? "bold" : undefined }}>{string}</span>);
});
</>
)
If we split the data using the key (**) that defines bold values, we know that every other value is bold. We then just need to check if the first value is bold or not.
Not an exact answer but getting close, if anyone has a better example please post. It doesn't work yet but i maybe need to use spread operator? i will post when closer as no one has posted an example yet.
{
type: "paragraph",
tags: ["Welcome", "course"]
text: "Welcome the the course.",
},
{
type: "paragraph",
text: "The purpose of this training is to provide an overview.",
},
function Paragraph({ text, size, tags }) {
const formatted = text.replace(`${tags}`, (it) => `<strong>${it}</strong>`);
return <div dangerouslySetInnerHTML={{ __html: formatted }} style={{
fontSize: size }} />;
}

Scroll to element when clicking table of contents

In React, how can I scroll to a heading on the page, when the corresponding heading is clicked in my table of contents?
I parse my markdown document to generate a TOC:
const toc = [
{ id: 'lorem', title: 'Lorem' },
{ id: 'ipsum', title: 'Ipsum' },
{ id: 'dolor', title: 'Dolor' }
];
I then render this TOC in render()::
{ toc.map((entry) => {
return (
<li key={entry.id}>
{entry.title}
</li>
);
})}
When I click on an entry in my TOC, I would like the page to scroll to the h2 element with that id. How?
The examples I have seen all use ref. But I am not sure how to use ref in my case, where the TOC is created dynamically at runtime and hence the refs would need to be created dynamically? I cannot add them to my document's elements, since they are generated by markdown-to-jsx.
You need to add IDs to your Markdown headers in your Markdown files and you can add IDs with this syntax:
### Lorem {#lorem}
Then in your React code you render the TOCs with link tag linking to header IDs:
{ toc.map((entry) => {
return (
<li key={entry.id}>
<a href={`#${entry.id}`}>{entry.title}</a>
</li>
);
})}
To read more about Markdown ID syntax: https://www.markdownguide.org/extended-syntax/#heading-ids

dynamic import of images react

I am trying to dynamically render images from a local folder within my project
The object structure looks like this
{
id: 2,
text: 'How would you describe your level of influence in management of the farm?',
type: 'cardChoice',
choices: [
{
id: 1,
text: 'I am the primary decision maker',
questionId: 'Hm?',
value: 'I am the primary decision maker',
image: '1.jpg',
},
{
id: 2,
text: 'I hent',
questionId: 'Hrm?',
value: 'I',
image: '2.jpg',
},
{
id: 3,
text: 'I arm',
questionId: '?',
value: 'Irm',
image: '3.jpg',
},
],
},
In my component I select the folder that contains the images const baseUrl = '../../assets/images/CNA'
After that, in my return I try to render the images
<img src={`${baseUrl}'${questionChoice.image}'`} alt={questionChoice.text} />
The page renders, but my image isn't loading and it's showing my alt instead
Heres my full component
const CardChoiceQuestions = ({ cardChoiceArray, currentAnswer, updateCurrent, submitAnswer }) => {
const { id, value } = currentAnswer
const baseUrl = '../../assets/images/CNA'
return (
<ButtonContainer>
{cardChoiceArray.map(questionChoice => {
return (
<Button
active={questionChoice.id === id}
type="button"
key={questionChoice.id}
onClick={() => {
const answer = { id: questionChoice.id, value: questionChoice.value }
updateCurrent(answer)
submitAnswer()
}}
>
<p>{questionChoice.text}</p>
<img src={`${baseUrl}${questionChoice.image}`} alt={questionChoice.text} />
</Button>
)
})}
</ButtonContainer>
)
}
I don't have my laptop in front of me but a few things I noticed. Do you need a slash "/" after your base url? Also, the string concatenation should be completed in one set of brackets after the $ sign. Not sure if that's the issue try a few console.log(string path) amd verify it is going where you think it is. It looks like the path may be wrong. You may be better off conditional rendering images as opposed to building a dynamic url but either way it should render on change.
<img src={`${baseUrl}/${questionChoice.image}`} alt={questionChoice.text} />
use like this
Leaving this here in case someone comes across this...
<img src={require(`../../assets/images/CNA/${questionChoice.image}`)} alt={questionChoice.text} />
Not sure why I can't use ${baseUrl} but this works for now.

how to access an object element in a vue js list (nuxt)

I have an array of object like that :
{ id: 33617,
datePublication: 1532266465,
dateUpdate: 1532266574,
headline: 'An headline title here',
images: [ [Object] ] },
{ id: 33614,
datePublication: 1532265771,
dateUpdate: 1532271769,
headline: 'another super headline article',
images: [ [Object], [Object], [Object], [Object], [Object] ] }
so i iterate that way on my vue js template :
<v-flex v-for="(ip, i) in ips" :key="i" xs12 sm6 >
<v-card>
<v-card-media
:src="ip.images[0].url"
height="200px"
/>
<v-card-title primary-title>
<div>
<h3 class="headline mb-0">{{ ip.headline }}</h3>
<div>Located two hours south of Sydney in the <br>Southern Highlands of New South Wales, ...</div>
</div>
</v-card-title>
<v-card-actions>
<v-btn flat color="orange">Share</v-btn>
<v-btn flat color="orange">Explore</v-btn>
</v-card-actions>
</v-card>
</v-flex>
And here is my associated script :
var api = "https://my api.org/news/fr-FR/2018-25-07";
export default {
data() {
return {};
},
layout: "no-live",
async asyncData({ app }) {
const ips = await app.$axios.$get(api);
console.log(ips);
return { ips };
}
};
Each object in the images array should return me an id and an url, so i want to take that url as a source in my image but i have this error : Cannot read property '0' of undefined
it seems i need to do another loop over the images array, is there a proper way to do that with vue JS ?
if you have any objects in ips that doesn't have images, you would get that error,
you can try to add a conditional to not have an error in rendering
<v-card-media
v-if="ip.images && ip.images[0]"
:src="ip.images[0].url"
height="200px"
/>
I usually add a <pre>{{ip}}</pre> in these cases to see what's going on.
Try put v-if="ip.images" on v-card-media component. You will assure the images are not empty and loaded.

How to display an array of objects inside the html template in Angular 2?

I am building web app that will have a list of 3d models. I’m doing it for a practice purposes, in order to gain some initial knowledge of angular 2.
Each listed model, will have name, main picture, category, and a slider (array of images).
Model data array is:
export var MODELS: Model[] = [{
id: 1,
name: 'Model 1',
image: 'app/img/models/model-1.jpg',
category: 'Cat 1',
slides: [
{ alt: 'Model 1 front view' , url: 'app/img/models/model-2.jpg' },
{ alt: 'Model 1 rear view' , url: 'app/img/models/model-2.jpg' },
{ alt: 'Model 1 side view' , url: 'app/img/models/model-2.jpg' }
]
},
{
id: 2,
name: 'Model 2',
image: 'app/img/models/model-2.jpg',
category: 'Cat 2',
slides: [
{ alt: 'Model 2 front view' , url: 'app/img/models/model-2.jpg' },
{ alt: 'Model 2 rear view' , url: 'app/img/models/model-2.jpg' },
{ alt: 'Model 2 side view' , url: 'app/img/models/model-2.jpg' }
]
}
];
Service that is used for proper displaying of certain model is:
#Injectable()
export class ModelService {
getModels(): Promise<Model[]> {
return Promise.resolve(MODELS);
}
getModel(id: number): Promise<Model> {
return this.getModels()
.then(models => models.find(model => model.id === id));
}
}
Model detail’s page template is:
<div *ngIf="model">
<h2>{{model.name}} details!</h2>
<img [src]="model.image" alt="{{model.name}}"/>
<div>{{model.slides}}</div>
</div>
These are Mostly stuff that I used from: https://angular.io/docs/ts/latest/tutorial/
However, when I try to use simplest way to display slides array into model-detail page, it shows [object Object]. I read that this is might be a common issue in angular 2, that can be resolved by using custom pipes. Unfortunately, I have no clue how to write one for this certain case.
General question will be: How to properly display array of objects (slides) on html template, and wrap them separately into img tag.
Here is plunker example link: http://plnkr.co/edit/HVo3dtGprMHsPYeyRWBR?p=preview
Thanks in advance,
That's because your slides property is in fact an Object, it's an array so displaying the property alone will simply display 'object'. What you need to do is iterate over the slides property and separately create img divs:
<img *ngFor="let slide of model.slides" [alt]="slide.alt" [src]="slide.url" />
this is what your updated template would look like from your plunkr:
<ul class="models">
<li *ngFor="let model of models" (click)="gotoDetail(model)">
<img *ngFor="let slide of model.slides" [src]="slide.url"/>
{{model.name}},{{model.category}}
</li>
</ul>
You could use *ngFor in an img tag I have included some of my practice code to show you what I mean.
<div class="col-md-6" *ngFor="let picture of imageUrl; let i = index; trackBy: trackByFn">
<div class="portfolio-item"
style="padding-bottom: 10px;">
<a (click)="galleryOpen = false;componentIndex = i;" data-toggle="dropdown" href="#" name="gal2">
<img class="img-portfolio img-responsive" src={{picture}} height="350" width="455"
style="height: 350px; max-width: 455px;">
</a>
</div>
</div>
The *ngFor in this case could just a easily be placed in the img tag. I hope this helps you out.

Resources