Gatsby image path from json - json

Edit: Got it working even if it feels kinda wrong this way.. Any ideas to make it possible to only use the filename and not a relative path would be appreciated. Anyway, here is how I got it working:
data.json
[
{
"slug": "bloom",
"name": "Bloom",
"image": {
"src": "../images/socks1.jpg"
}
}
]
Query:
{
allDataJson {
edges {
node {
slug
name
image {
src {
childImageSharp {
fluid {
src
}
}
}
}
}
}
}
}
I am trying to display an image of which the name is stored in data.json and the file itself is in src/images
src/data/data.json
[
{
"slug": "sock1",
"name": "sock1",
"image": "socks1.jpg"
}
]
If instead of the pure filename, I provide a url to any image on the web it works.. Tried getting it to work as follows:
gatsby-config.js
module.exports = {
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
name: `data`,
path: `${__dirname}/src/data`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
`gatsby-transformer-json`,
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
],
}
product.js
import React from 'react'
import { graphql } from 'gatsby'
import Layout from '../components/layout'
import get from 'lodash/get'
class ProductPage extends React.Component {
render() {
const products = get(this, 'props.data.allDataJson.edges')
console.log(products)
return (
<Layout>
{products.map(({ node }) => {
return (
<div key={node.name}>
<p>{node.name}</p>
<img src={node.image} />
</div>
)
})}
</Layout>
)
}
}
export default ProductPage
export const productsQuery = graphql`
query {
allDataJson {
edges {
node {
slug
name
image
}
}
}
}
`
All that's being outputted on the frontend is
<img src="socks1.jpg">
If I query for all files in the GraphiQl I get them, but (not sure about this one) I think the image field is just not recognized as file type field (cant query for src etc)
Any pointers would be much appreciated! :)

Your query should similar to this:
export const productsQuery = graphql`
query {
allDataJson {
edges {
node {
slug
name
image{
publicURL
childImageSharp{
fluid {
...GatsbyImageSharpFluid
}
}
}
}
}
}
}
`
Then you can output the path like this:
<img src={node.image.childImageSharp.fluid.src} />
You don't have to use fluid, you use other types of responsive images

Related

2 V-If Statements in the same div?

I am attempting to put two conditions into one div, but since I am new to coding, I am not sure where to go from here. Basically what my code is doing is displaying a part table constantly, but I only want to display the table when there are results found. When the no results div displays, I would like the table to not display. If any advice could be spared, it would be greatly appreciated. Here is the code....
<keep-alive>
<PartsTable style="grid-area: contentArea" v-if="displayStore.cardView" />
</keep-alive>
<div id="noResultsDiv" v-if="partStore.filterQuery && !computedList.length">No Results Found</div>
script
<script lang="ts">
import { defineComponent } from "vue";
import { mapStores } from 'pinia'
import PartsTable from "../components/PartsTable.vue";
import ActionButton from "../components/ActionButton.vue";
import PartCardHolder from "../components/PartCardHolder.vue";
import { useDisplayStore } from "../stores/display-store";
import { usePartStore } from "../stores/part-store";
import { PartDefinition } from "../types/PartDefinition";
export default defineComponent({
name: "Home",
components: {
PartsTable,
ActionButton,
PartCardHolder,
},
data() {
return {
pageCount: 50 as number,
emptyStore: false as boolean
}
},
computed: {
...mapStores(useDisplayStore, usePartStore),
computedList(): PartDefinition[] {
return this.partStore.filteredList.slice(0, this.pageCount);
},
},
methods: {
addPart(): void {
this.$router.push({
path: `/add`,
});
},
viewPart(id: PartDefinition["id"]): void {
this.$router.push({
path: `/view/${id}`,
});
},
async updateStorage() {
sessionStorage.setItem("cardView", this.displayStore.cardView.toString())
},
},
async mounted() {
if (sessionStorage.getItem("cardView") == "true") {
this.displayStore.cardView = true
sessionStorage.setItem("cardView", "true")
} else {
this.displayStore.cardView = false
sessionStorage.setItem("cardView", "false")
}
console.log(sessionStorage.getItem("cardView"))
},
unmounted() {
this.partStore.filterQuery = ""
},
});
</script>
You can use vue.js Conditional Rendering v-if/v-else to achieve.
<div v-if="computedList.length">
// Your parts table will come here.
</div>
<div v-else>
// No results div will display here
</div>
I just gave you a way to achieve the requirement. You can modify the condition as per your need.

Replace an Url from Json with a button that gives URL to another function

I’m trying to implement a function in my web application, that can discover URLs in a loaded Json via Regular Expressions using angular. Afterwards the URLs get replaced with buttons and when the button gets clicked the exact URL who got replaced gets handed in another function in another component which loads the given URL.
Until now I’m at the point that I can replace the URL of the loaded JSON with a button. I’m using a pipe for that named transform-url.pipe:
import {
Pipe,
PipeTransform,
Input,
Component
} from '#angular/core';
import {
DomSanitizer
} from "#angular/platform-browser";
#Pipe({
name: 'transformUrl',
pure: false
})
export class TransformUrlPipe implements PipeTransform {
constructor(protected sanitizer: DomSanitizer) {}
transform(value: any, ): any {
if (value.match === 0) {
return value;
}
return this.sanitizer.bypassSecurityTrustHtml(
value.replace(/"url:\/\/.*\/.*\/.*"/g, "<button type='button' >Run</button>")
);
}
}
Hmtl:
<h3>Unrecognized JSON data:</h3>
<pre [innerHTML] = "genericJson | transformUrl"></pre>
Sample of Json:
"documentVersion": "1.0",
"documentType": "Urls",
"name": {
"request": {
"version": "1.0",
"abc": [
{
"productUrl": "url://awrtwtgsfgshsfh/sfg/v1/document/jsfhljhl564356lhgljhsljh5895hj",
"attributes": [
{
"attributeSet": {
"attributes": {
"426824828246824828282468248": {
"value": "1"
},
"647474373748648248282824": {
"value": "true"
}
}
}
}
]
},
"productUrl": "url://adgagjfjfjfjhf/sfg/v1/document/adfah5ahfah5jahlkhaliohßjkjlaß73-3",
"attributes": [
{
"attributeSet": {
"attributes": {
"426824828246824828282468248": {
"value": "1"
},
"647474373748648248282824": {
"value": "true"
}
}
}
}
]
},
I found nothing on google on how to do this specific task. Is a pipe even the best solution for this? I tried to implement functions in the pipe but it didnt work.
Another thing that i cant figure out is how i can make every button unique so the application knows which excat URL it should take when the button is clicked? And how can I select the URL and give it in another function in another component?
First of all rather than using pipe, I have created solution in Component only.
Stringify JSON which needs to be get values from. genericJson
Remove first and last ", which is matched in regex.
Using *ngFor, create buttons and pass separate link to click function.
Demo (check console for button click)
EDIT: NEW DEMO.
import { Component } from "#angular/core";
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
name = "Angular";
genericJson = { ... some json ... }
formatedOutput: (string | boolean)[] = [];
ngOnInit() {
// adding formatting to make regex search easier
const jsonFormattedString = JSON.stringify(this.genericJson, null, 4);
this.formatedOutput = jsonFormattedString.split('\n');
}
onClick(out: string) {
// do whatever operation on link
const link = out.match(/url:\/\/.*\/.*\/.*/)[0];
console.log(link);
}
urlFound(out: string): boolean {
const match = out.match(/"url:\/\/.*\/.*\/.*"/);
if (match !== undefined && match !== null && match.length > 0) {
return true;
}
return false;
}
}
Use matched links in HTML template,
<div>
<div *ngFor="let out of formatedOutput">
<ng-container *ngIf="urlFound(out); else simple_json"><pre>{{out}}<button (click)="onClick(out)">Link</button></pre></ng-container>
<ng-template #simple_json><pre>{{out}}</pre></ng-template>
</div>
</div>
I think, you should do it like this instead of using pipe:
.html
<button (click)="goTo(genericJson.url)">Run</button>
.ts
genericJson = {
url: "www.google.com"
};
goTo(url: string) {
if (url) {
if (!url.includes("https")) {
url = "https://" + url;
}
window.open(url, "_blank");
}
}

Mapping through an Array of Images created in a local JSON File and rendering it

I am learning RN and I am having trouble setting up a mapping method to go through an array of images of some players that I created in a local JSON file, and render them in their respective profile pages.
This is how I have set my json.
//PlayerImages.js
const PlayerImages = [
{
id: "1",
name: "Cristiano Ronaldo",
images:["https://www.thesun.co.uk/wp-content/uploads/2019/05/NINTCHDBPICT000485852530.jpg",
"https://e00-marca.uecdn.es/assets/multimedia/imagenes/2019/05/18/15582064666477.jpg",
"https://e00-marca.uecdn.es/assets/multimedia/imagenes/2019/05/18/15582064666477.jpg"]
},
{
id: "2",
name: "Lionel Messi",
images:["https://www.thesun.co.uk/wp-content/uploads/2019/05/NINTCHDBPICT000485852530.jpg",
"https://e00-marca.uecdn.es/assets/multimedia/imagenes/2019/05/18/15582064666477.jpg",
"https://e00-marca.uecdn.es/assets/multimedia/imagenes/2019/05/18/15582064666477.jpg"]
},
{
id: "3",
name: "Neymar",
images: mages:["https://www.thesun.co.uk/wp-content/uploads/2019/05/NINTCHDBPICT000485852530.jpg",
"https://e00-marca.uecdn.es/assets/multimedia/imagenes/2019/05/18/15582064666477.jpg",
"https://e00-marca.uecdn.es/assets/multimedia/imagenes/2019/05/18/15582064666477.jpg"]
},
{
id: "4",
name: "Gabriel de Jesus",
images:["https://i.pinimg.com/474x/f1/36/ca/f136ca04817e60fa12f4a5680101ff8b.jpg",
"https://i.pinimg.com/474x/b1/da/e2/b1dae2fe6ca1620e5d1949a2dcd33a0c.jpg",
"https://i.pinimg.com/564x/7b/53/32/7b5332ef6a981b3c54e855495ea1c828.jpg"]
},
{
id: "5",
name: "Roberto Firmino",
images:mages:["https://www.thesun.co.uk/wp-content/uploads/2019/05/NINTCHDBPICT000485852530.jpg",
"https://e00-marca.uecdn.es/assets/multimedia/imagenes/2019/05/18/15582064666477.jpg",
"https://e00-marca.uecdn.es/assets/multimedia/imagenes/2019/05/18/15582064666477.jpg"]
}
]
export default PlayerImages;
This is how I have the ImageGallery component set up. Unfortunately, the way I have componentDidMount set up, shows Cristiano Ronaldos images in all profiles. How can I map it in order to make sure that each profile has the pictures of that particular player when you tap the gallery button on their profile?
//ImageGallery.js
import React, { Component } from "react";
import { StyleSheet, Text, View } from "react-native";
import { SliderBox } from "react-native-image-slider-box";
import { withNavigation } from "react-navigation";
import PlayerImages from "../Data/PlayerImages";
class ImageGallery extends React.Component {
static navigationOptions = {
title: "Player Gallery",
headerStyle: {
backgroundColor: "#53b4e6"
},
headerTintColor: "#f6c945",
headerTitleStyle: "bold"
};
constructor(props) {
super(props);
this.state = {
images: []
};
}
componentDidMount() {
let images = PlayerImages[0].images;
this.setState({ images });
}
render() {
return (
<View style={styles.container}>
<SliderBox
images={this.state.images}
sliderBoxHeight={900}
onCurrentImagePressed={index =>
console.warn(`image ${index} pressed`)
}
dotColor="yellow"
inactiveDotColor="white"
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
}
});
export default withNavigation(ImageGallery);
Finally, when you are on the players profile, you should have access to their gallery by tapping the button in the header. As I mentioned earlier in the post, when you tap it, you get only the images of Cristiano Ronaldo.
//PlayerProfile.js
headerRight: (
<Button
onPress={() => navigation.navigate("ImageGallery")}
title="Gallery"
color="#f6c945"
/>
)
Pass the id of the player or the index of the player you want to display images of using navigation parameters , then use it to get the images of the player, right now you are using images at the 0th index of array.
componentDidMount() {
let images = PlayerImages[0].images;
this.setState({ images });
}
change this to
componentDidMount() {
let images = PlayerImages[index].images; //index is the index of the player whose images you want to show
this.setState({ images });
}

Creating a dynamic gallery in React Native, but images will not appear

I am trying to create a dynamic photo gallery for all the characters on my app. When I click on the gallery for that particular character, It takes me to their gallery, but no images appear. Each character should have 3 images for their gallery. While the app does not break, I do get a warning message saying the following: "Failed prop type: Invalid prop source supplied to image." Can somebody look at my code and see where I am wrong?
I created a JSON file with images for each character.
//CharacterImages.js
const CharacterImages = [
{
id: "1",
name: "Homer Simpson",
urlone:
"https://i.pinimg.com/474x/f1/36/ca/f136ca04817e60fa12f4a5680101ff8b.jpg",
urltwo:
"https://i.pinimg.com/474x/b1/da/e2/b1dae2fe6ca1620e5d1949a2dcd33a0c.jpg",
urlthree:
"https://i.pinimg.com/564x/7b/53/32/7b5332ef6a981b3c54e855495ea1c828.jpg"
},
{
id: "2",
name: "Marge Simpson",
urlone:
"https://i.pinimg.com/564x/63/e4/7d/63e47d98e66622bbff5e4578ccffeffc.jpg",
urltwo:
"https://i.pinimg.com/564x/04/48/60/044860ebcd5d6c14a1140b351cb620b1.jpg",
urlthree:
"https://i.pinimg.com/564x/6d/99/26/6d9926fa54bc3650acf9295d997fc72c.jpg"
},
{
id: "3",
name: "Bart Simpson",
urlone:
"https://i.pinimg.com/564x/fe/18/af/fe18af309234936e231fa107c6d2b4c7.jpg",
urltwo:
"https://i.pinimg.com/564x/20/59/7a/20597ab32ab0f7ec8a5484fa384e0bb4.jpg",
urlthree:
"https://i.pinimg.com/564x/20/59/7a/20597ab32ab0f7ec8a5484fa384e0bb4.jpg"
}
export default CharacterImages;
I created a separate folder so that the images can come in dynamically.
// ImageGallery.js
import React, { Component } from "react";
import { StyleSheet, Text, View } from "react-native";
import { SliderBox } from "react-native-image-slider-box";
import { withNavigation } from "react-navigation";
import CharacterImages from "../Data/CharacterImages";
class ImageGallery extends React.Component {
static navigationOptions = {
title: "Gallery",
headerStyle: {
backgroundColor: "#53b4e6"
},
headerTintColor: "#f6c945",
headerTitleStyle: "bold"
};
constructor(props) {
super(props);
this.state = {
CharacterImages
};
}
render() {
return (
<View style={styles.container}>
<SliderBox
images={this.state.CharacterImages}
sliderBoxHeight={900}
onCurrentImagePressed={index =>
console.warn(`image ${index} pressed`)
}
dotColor="yellow"
inactiveDotColor="white"
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
}
});
export default withNavigation(ImageGallery);
Finally, the user can access the each characters gallery when they are in that particular profile this way:
//CharacterProfile.js
headerRight: (
<Button
onPress={() => navigation.navigate("ImageGallery")}
title="Gallery"
color="#f6c945"
/>
)
The problem here is that you are passing a whole object of datas instead of an array of strings with urls.
Try changing images prop to:
images = {this.state.CharacterImages.urlone}
Then i would advise to create a single "image" key object with the array of strings, making your CharacterImages be:
const CharacterImages = [
{
id: "1",
name: "Homer Simpson",
images:["https://i.pinimg.com/474x/f1/36/ca/f136ca04817e60fa12f4a5680101ff8b.jpg",
"https://i.pinimg.com/474x/b1/da/e2/b1dae2fe6ca1620e5d1949a2dcd33a0c.jpg",
"https://i.pinimg.com/564x/7b/53/32/7b5332ef6a981b3c54e855495ea1c828.jpg"]
},
{
id: "2",
name: "Marge Simpson",
images:["https://i.pinimg.com/564x/63/e4/7d/63e47d98e66622bbff5e4578ccffeffc.jpg",
"https://i.pinimg.com/564x/04/48/60/044860ebcd5d6c14a1140b351cb620b1.jpg",
"https://i.pinimg.com/564x/6d/99/26/6d9926fa54bc3650acf9295d997fc72c.jpg"]
},
{
id: "3",
name: "Bart Simpson",
images:["https://i.pinimg.com/564x/fe/18/af/fe18af309234936e231fa107c6d2b4c7.jpg",
"https://i.pinimg.com/564x/20/59/7a/20597ab32ab0f7ec8a5484fa384e0bb4.jpg",
"https://i.pinimg.com/564x/20/59/7a/20597ab32ab0f7ec8a5484fa384e0bb4.jpg"]
}
]
export default CharacterImages;
EDIT
Forgot that CharacterImages is an Array of objects!!!
I updated also the constant as i didn't close the array
Here you have to decide how you want to render your images based of which condition. I'm going to show you how to put them so all images gets rendered:
constructor(props){
super(props)
mergedArray=CharacterImages.map(item=> item.images).concat.apply([], mergedArray)
this.state={
images=mergedArr
}
}
After this you can use this.state.images inside your SliderBox

How do I retrieve images from JSON into React?

I want to use JSON to retrieve my images along with their file location. My program looks like the code below.
I've tried with {photos.Lillian.portfolioImage} and with JSON.stringify(photos.Annalise.portofolio however, none of them can display the images. I've done a console.log(); and checked if the data can be read and it does appear however, the images will not appear. I've checked the source address and it works when I add it here <img src="./img/TheGuardian/Lillian.png">.
What is my error? Do I need to reformat the object called from JSON? I've seen one can use parse and fetch however, this is used for APIs and as far as I can see, this isn't?
Here's my JSON:
{
"Lillian" : {
"type": "The Guardian",
"portfolioImage": "./img/TheGuardian/Lillian.png"
},
"Annalise" : {
"type": "TheGuardian",
"portfolioImage": "./img/TheGuardian/Annalise.png"
},
"Raven" : {
"type": "DCComics",
"portfolioImage": "./img/TheGuardian/Raven.png"
}
}
Here's my HTML:
import React, { Component } from 'react';
import logo from './logo.svg';
import photos from './images.json';
import './App.css';
class App extends Component {
render() {
console.log(JSON.stringify(photos.Annalise.portfolioImage));
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>beeccy´s portfolio.</h2>
</div>
<p className="App-intro">
This was a test to present images from my portfolio.
</p>
<img src={photos.Lillian.portfolioImage} alt="Lillian" />
<img src={photos.Raven.portfolioImage} alt="Raven" />
<img src="JSON.stringify(photos.Annalise.portfolioImage)" alt="Annalise" />
</div>
);
}
}
export default App;
Like in HTML, you want to set the src attribute of an img element the source to the image. The following example also shows how you can loop over the JSON and show all images at once.
const JSON = {
Lillian: {
type: 'The Guardian',
portfolioImage: './img/TheGuardian/Lillian.png'
},
Annalise: {
type: 'TheGuardian',
portfolioImage: './img/TheGuardian/Annalise.png'
},
Raven: { type: 'DCComics', portfolioImage: './img/TheGuardian/Raven.png' }
};
class Example extends React.Component {
render() {
return (
<div>
{Object.keys(JSON).map(key => (
<div>
{JSON[key].type}
<img src={JSON[key].portfolioImage} key={key} />
</div>
))}
</div>
);
}
}
ReactDOM.render(<Example />, document.getElementById('root'));
const obj =
{
"Lillian" : { "type": "The Guardian", "portfolioImage": "./img/TheGuardian/Lillian.png" },
"Annalise" : { "type": "TheGuardian", "portfolioImage": "./img/TheGuardian/Annalise.png" },
"Raven" : { "type": "DCComics", "portfolioImage": "./img/TheGuardian/Raven.png" }
};
let images = [];
for(let item in obj){
images.push(item.portfolioImage);
}
By doing this you can retrieve images from the object of objects into the images array