Reactjs json looping image path not loading - json

I am new to reactjs - I am keen to retain all the content from json - but I am having an issue with the images.
So the json looks like this:
"items" : [
{
"title" : "Projekt ausschreiben",
"description" : "Schreiben Sie Ihr Projekt aus und zeigen Sie es einer handverlesenen Gruppe von Fachexperten",
"image" : "/img/home/works_emp_01.png"
},
{
"title" : "15 Minuten Video-Gespräch",
"description" : "Führen Sie eine unverbindliche Unterhaltung mit 3 vorselektierten Anwälten",
"image" : "/img/home/works_emp_02.png"
},
{
"title" : "Transparente Zusammenarbeit",
"description" : "Erhalten Sie einen bindenden Kostenvoranschlag und arbeiten Sie online zusammen",
"image" : "/img/home/works_emp_03.png"
}
]
and then I've tried to loop through the markup on the template like this.
In a previous research it was suggested to use a require.context function to get the image paths defined. - but this isn't working
const pathToImages = require.context('./src', true)
{
lang.howTiles[0].items.map(function (item, index) {
return (
<div key={index}>
<div className='small-60 columns grid__row--offset--30 show-for-small-only'> </div>
<div className='small-45 medium-20 small-centered medium-uncentered columns'>
<div className='row'>
<div className='small-60 medium-45 small-centered columns'>
<div className='relative-container'>
x<img src={pathToImages(imagesArray[index], true)} />x
<img className='centered' src={imagesArray[index]} style={{maxWidth: '50%', marginLeft: '25%'}} />
<h3 className='text--bold text--center' style={{marginTop: '25px'}}>{item.title}</h3>
<p className='text--center text--font-size-14' style={{marginTop: '15px'}}>{item.description}</p>
</div>
</div>
</div>
</div>
</div>
)
})
}

check if yours src={ "../your_path_to_image" } works as expected at all.
then check lang.howTiles[0].items for same values. 100% something lost in translation here.
anyway i dont get why ya use require.context('./src', true) ?? it just loads images separate from div src
..maybe helpfull https://github.com/facebookincubator/create-react-app/issues/517

make simple array with your image paths and in render function just one div with map and src={item} to check 100% if it path problem or more .. i still got strong feeling of that is problem.
btw. in mentioned older thread there already shows up some problems with this approach.
and i still see no reason to use require.context there if ya simply want add dynamic path to view render.
as i understand web packs require` it runs per build and do all magic paths related job etc.. but it will run in trouble when dynamic path names given
gaearon commented on Mar 10
Is there a problem with explicitly importing them in the code? After all require.context is just sugar for doing that.
here is my code example how to deal with dynamic paths:
var some_path = ( some_value ) ? ${root_path}/0${other_value + tag.toUpperCase()}_Active.svg : default_path;
return <div className={class_names.join(' ')} >
<div className="some class name">
<img src={some_path} alt="image" />
</div>
</div>;
and with array
return (
<div className="class name">
{my_array.map(function( path ){
return <img src={ path } alt="image" />
})}
</div>
);

Related

conditional rendering not acting uniformly in reactjs?

I have used conditional rendering in the past but for some reason, it's working on one element here but not on another although they are both using the same JSON phrasing and the same type of conditional rendering?
JSON array
//Adobe component data
export default[
{
workName: 'Switch up your "Grub" Motiongraphic',
workDescription: 'This is a motion graphic comparing the environmental and health effects of consuming animal products compared to insects as dietary source of protein.',
workTech: ['Adobe After effects'],
videoAddress: ['https://youtu.be/cloat51hzDY'],
Images: []
},
{
workName: 'Simplyfit concept poster',
workDescription: 'This is a poster developed explaining the concept of Simplyfit, a fitness application developed as part of my final year project.',
workTech: ['Adobe Illustrator'],
videoAddress: [],
Images: ['SFPoster.jpg'],
},
{
workName: 'Switch up your "Grub" Infographic',
workDescription: 'This is an infographic developed explaining the benefits of consuming insects as a source of protein.',
workTech: ['Adobe Illustrator'],
videoAddress: [],
Images: ['insectMotiongraphic.png'],
},
{
workName: 'Crunchy Nut Advert spoof',
workDescription: 'This video was made as a comedic spoof of a Crunchy Nut advert',
workTech: ['Adobe Premier Pro'],
videoAddress: ['https://youtu.be/y8S2RUYrLN8'],
Images: [],
},
{
workName: 'Icons and Designs',
workDescription: 'These are a selection of logos and icons created by me.',
workTech: ['Adobe Premier Pro'],
videoAddress: [],
Images: ['Mylogo.png'],
},
]
The problem I'm having is with the 'videoAdress' and the 'Images' I've tried setting null values undefined etc for them both but for the images the only thing that stops them from rendering is setting the value as [] but this doesn't work for the videoAdress the iframe is still rendered?
React js code
{Data.map((Projects, index) => {
return <div className='Cards'>
<Carousel showThumbs={false} infiniteLoop={true} swipeable={false} emulateTouch={false} showStatus={false} autoPlay={slideShow} dynamicHeight={false}>
{Projects.Images && Projects.Images.map((Image, index) => { return <div className='image-iframeContainer'><img src={require("../assets/Port-images/Adobe/" + Image)} /></div> })}
{Projects.videoAddress && <div className='image-iframeContainer'><ReactPlayer url={Projects.videoAddress} muted={false} controls={false} onPlay={autoplayChange} onPause={autoplayChange} onEnded={autoplayChange} /></div>}
</Carousel>
{Projects.webAddress && <div className='webButton'><LinkIcon onClick= { () => {window.open(Projects.webAddress);}}/></div>}
<h1>{Projects.workName}</h1>
{Projects.workTech.map((Tech, index) => { return <p className='techList'>{Tech}</p> })}
<div className='descriptionContainer'>
<p className='description'>{Projects.workDescription}</p>
</div>
</div>
})}
The function I would like is for the Images and Videos only to render if there is a stored address I'm sure I'm missing something very silly but still, I've been stuck on this for awhile.
Conditional rendering works by casting the condition to a truthy value. For example:
Projects.Images && <Component />
is equal to this:
!!Project.Images && <Component />
Now if you do this for an empty array [], the truthy value is TRUE. This means that <ReactPlayer /> is rendered with [] value and the <img /> is not rendered because [].map() doesn't run on an empty array.
To fix this do this instead:
{Projects.Images && Projects.Images.length > 0 && Projects.Images.map((Image, index) => {
return <div className='image-iframeContainer'>
<img src={require("../assets/Port-images/Adobe/" + Image)} />
</div>
})}
{Projects.videoAddress && Projects.videoAddress.length > 0 &&
<div className='image-iframeContainer'>
<ReactPlayer url={Projects.videoAddress[0]} muted={false} controls={false} onPlay={autoplayChange} onPause={autoplayChange} onEnded={autoplayChange} />
</div>}
I noticed that your videoAddress doesn't use the map() method, but I guess it's a typo

React + Next js: Cross json values in component

first I'd like to thank you for your time trying to help. I am a designer and I suck at developing stuff, so I have no other option than to scream for help.
So this is the situation:
I was asked to add an image (country flag) that's gonna be dynamic, in an element that fetches info from a JSON file with, among others, Resorts (one of the elements being its country's long name, i.e. Australia) and Countries (by long name and shortcode, i.e. Australia, au).
I need to get the country shortcode printed in the img src, but the resort array is only containing its long name.
The code:
This is the way the JSON file presents the information:
{
"Countries":[
{"name":"Australia",
"code":"au",
"continent_code":"oc",
"slug":"australia"}],
"Continents":[
{"name":"Oceania",
"code":"oc",
"slug":"oceania"}],
"Resorts":[{
"id":"1",
"resort_name":"Resort Name",
"encoded_name":"resort-name",
...
"country":"Australia",
...}]
}
And this is my file bit:
const DesktopResort = ({resort}) => (
<Link href="/resort/[resort]" as={`/resort/${resort.encoded_name}`}>
<a target='_blank' className='resort-item'>
<div className="resort">
<div className="top">
<div className="title">{resort.resort_name}</div>
<img className="logo" src="/assets/img/resort-logo-sample.png" />
<span className="info">{`${resort.ski_network} - ${resort.region}`}</span>
// Down below is the "dynamic" file call
<img className="flag-icon" src={`/assets/img/flags/${resort.country}.svg`} />
</div>
<div className="arrow"><img src="/assets/img/arrow-link.png" /></div>
</div>
</a>
</Link>
)
I know its badly done right now, for this australian resort my image src is /assets/img/flags/Australia.svg and what I would need to print is of course /assets/img/flags/au.svg
How would you do it?
Thanks again!
I'd write a little helper function to look up a country code based on the country name.
Note: you'll need to handle what should happen if the country is not found, or the code is not there. I'm just defaulting to an empty string here.
const countryCode = name => {
const country = yourData.Countries.find(country => country.name === name);
return country && country.code || '';
};
Then use this when you're passing the src to your img.
<img
className="flag-icon"
src={`/assets/img/flags/${countryCode(resort.country)}.svg`}
/>

access certain element of JSON in angular JS

Below is my JSON file:
[
{
"Name":"Peter England Shirt",
"Prodimage":["./images/zoom/zoom1hi.jpg","./images/zoom/zoom2hi.jpg","./images/zoom/zoom3hi.jpg"],
"actualPrice":"90",
"discountedPrice":"70",
"desc":"Cotton",
"Prodcolor":["#f1f40e","#adadad","#4EC67F"],
"quantity":[1,3,4,5,60],
"size":["XL","L","M","S"],
"detail":"Take it away",
"sizeChart":["16 waist","Measurements taken from size 30","Model wears size 31. Model is 6'2"],
"shipping":[
{
"type":"Standard",
"days":"5-6 days",
"cost":"200"
},{
"type":"Next day",
"days":"1 days",
"cost":"500"
}
],
"sellerList":[
{
"sellerName":"ABC",
"price":"566",
"deliveryDay":"4-5 working days"
},{
"sellerName":"SEDF",
"price":"300",
"deliveryDay":"4-5 working days"
},{
"sellerName":"QWER",
"price":"555",
"deliveryDay":"2-5 working days"
}
]
}
]
The JS file is as below:
var pJson="./json/product.json";
$http.get(pJson).success(function(response){
$scope.product=response;});
Now, if I want to access "Name" attribute I can call {{product[0].Name}}.
But I am not able to access Prodimage attribute using ng-repeat. I am trying like this:
<div ng-repeat="image in product.Prodimage">
{{image[0]}}
</div>
is this wrong?>
Yes this is wrong ,, note that you have the product object as array ,, so if you want the first object you should do this
<div ng-repeat="image in product[0].Prodimage">
{{image[0]}}
</div>
or if you want to iterate over all the products ,, you need to make a nested ng-repeat
<div ng-repeat="p in product">
<div ng-repeat="image in p.Prodimage">
{{image[0]}}
</div>
</div>
You could loop over it, becasue the outside is technically an array, and use $first for you example of wanting to only grab the first image. You could also use $index but running it through a function that checks the $index.
Fiddle here http://jsfiddle.net/HB7LU/15324/
I just re worked it to loop twice like so
<div ng-repeat="prod in product">
<div ng-repeat="image in prod.Prodimage">
<div ng-show="$first">
{{image}}
</div>
</div>
</div>
then put a div inside the inner repeat that will only show if it's the first item. Again you could change that logic to show by index, or whatever you want. So if you know the index you could change that same logic to this -
see fiddle - http://jsfiddle.net/HB7LU/15332/
<div ng-show="checkIndex($index)"> << or whatever index you want
{{image}}
</div>
and in the controller
$scope.checkIndex = function(item){
if(item === 0){
return true;
}else{
return false;
}
}
You just pass the index of the current item in the repeat and check it. I would recommend this logic over the Prodimage[0] logic so you are not hardcoding it into the html, so if you have to change the desired index, you change it in the controller, not template. The checkIndex is a quick example, you could change that to do whatever you want.
$scope.product[n].Prodimage is an array. So, you need to loop through your product array first, and then loop through the Prodimage array of each product:
<div ng-repeat="prod in product">
<div ng-repeat="image in prod.Prodimage">
{{ image }}
</div>
</div>
Of course, you could also just access the nth image using something like:
<div ng-repeat="prod in product">
{{ prod.Prodimage[0] }}
</div>
Can you change your json to
"Prodimage":[
{ "loc": "./images/zoom/zoom1hi.jpg"},
{ "loc": "./images/zoom/zoom2hi.jpg"},
{ "loc": "./images/zoom/zoom3hi.jpg"}],
then your loop should work
<div ng-repeat="image in product.Prodimage">
{{image.loc}}
</div>

Mustache.to_html not returning anything

I have a total of (3) templates in my page and this overlay template is the third and final one. The first two are basically written the same as this template and they work fine. BUT For some reason, console.log(html) on this one returns nothing :
<!-- JSON -->
{ "art" : [{
"title" : "2 Intro-B",
"img_small" : "2 Intro-C",
"description" : "8x10 archival print on Epson Fine Art Velvet Paper.",
"price" : "20"}, { "title" : "6 Bison-B",
"img_small" : "6 Bison-C",
"description" : "8x10 archival print on Epson Fine Art Velvet Paper.",
"price" : "20"}, { "title" : "7 Cars-B",
"img_small" : "7 Cars-C",
"description" : "8x10 archival print on Epson Fine Art Velvet Paper.",
"price" : "20"}]}
<!-- HTML -->
<div id="overlay"></div>
----------------------------------------------
<!-- SCRIPT -->
<script id="overlayTmpl" type="text/template">
{{#overlayTemplate}}
<div id="lightbox">
<div id="closeButton">X</div>
<img src="/images/{{title}}.jpg"/>
</div>
{{/overlayTemplate}}
</script>
<script type="text/javascript">
$(function(){
$.getJSON('/scripts/art.json', function(data) {
var overlaytmpl = $('#overlayTmpl').html();
var html = Mustache.to_html(overlaytmpl, data);
console.log(html);
$('#overlay').html(html);
});
});
</script>
** On the first two templates, the console.log(html) returns the html output just fine. I don't know why this one is hung up on something. JSON file has been validated...
Please help me from going insane. There must be a hex on this block of code. Anyone have a magic wand?
This may help you - Change your template like this:
<script id="overlayTmpl" type="text/template">
{{#art}}
<div id="lightbox">
<div id="closeButton">X</div>
<img src="/images/{{title}}.jpg"/>
</div>
{{/art}}
</script>

Rendering json data (having anchor tag) to html page

I have json data having anchor tag .
task.json
{
"data": [{
"id": 1,
"title": "Launch an EC2 Instance",
"desc": "Needed an <a href='#'>EC2</a> instance to deploy the ccr code",
"status": "done",
"percentage_finished": 100
}]
}
I am using angularjs to render this data to my html page . But anchor tag is not working.
It prints as it is as Text.
<div class="task-pn panel panel-primary">
<div class="panel-heading"><b>Description : Task-{{task_detail.id}}</b></div>
<div class="panel-body">
<div onclick="this.contentEditable='true';">{{task_detail.desc}}</div>
</div>
</div>
Output img.
I need a simple link to EC2 word .How to deal with this isuue?
You need something like this:
In your controller:
scope.trustedHtml = sce.trustAsHtml(json.desc);
And to use it in your partial:
<p class="org-desc" ng-bind-html="trustedHtml"> </p>
user2720708 :Thanks for sharing your ideas.
eRIZ gave this link .There I used the idea of Luke Madera.
Current working html page .
<div class="task-pn panel panel-primary">
<div class="panel-heading"><b>Description : Task-{{task_detail.id}}</b></div>
<div class="panel-body">
<div contentEditable" ng-bind-html="task_detail.desc"></div>
</div>
</div>
and Then I follow only two steps :
1.include the angular-sanitize.min.js resource, i.e.:
2.In a js file (controller or usually app.js), include ngSanitize, i.e.:
angular.module('myApp', ['myApp.filters', 'myApp.services',
'myApp.directives', 'ngSanitize']) ---------from answer given by Luke Madera
Its working now ...:)