I am using the data from below to pass as props in React. Everything works fine but I need to only bold the words "target audience" in the text property. Is there a way to do this?
const SlideData = [
{
index: 1,
title: "Target Audience",
text: [
"The target audience for this course is anyone who is assigned roles as a HR Employee Maintainer...",
],
image: {
src: targetAudience,
width: imageSize,
},
},
index: 2,
title: "Reporting ",
text: [
"Reporting Manager is designated to...",
],
image: {
src: reporting,
width: imageSize,
},
},
]
export default SlideData
Added Render Component
const TextSlide = ({ title, text = [], list, image }) => {
return (
<>
<div className="slide">
<div className="standard-grid">
<span className="slide-title title">{title}</span>
<div className="content">
{text.map((t, i) => (
<p key={i} className="text">
{t}
</p>
))}
</div>
{image ? <img className="picture" src={image.src} style={{ maxWidth: image.width }} alt="image" /> : null}
</div>
</div>
</>
);
};
export default TextSlide;
``
You could split the text by target audience, and map the chunks inbetween to text nodes appending a node to each element:
"The target audience for this course is anyone who is assigned roles as a HR Employee Maintainer...",
.split("target audience")
.map((text, index) => <>{index !== 0 && <b>target audience</b>} {text}</>)
A more sophisticated approach would be to inject html tags into the text, and use dangerouslySetInnerHTML:
const formatted = text.replace(/(target audience)/g, it => `<b>${it}</b>`);
return <div dangerouslySetInnerHTML={formatted} />;
You could change the text to an object with a key of __html and use bold tags to render it by using dangerouslySetInnerHTML:
const SlideData = [
{
index: 1,
title: "Target Audience",
text: [
{
__html:
"The <b>target audience<b> for this course is anyone who is assigned roles as a HR Employee Maintainer...",
},
],
image: {
src: targetAudience,
width: imageSize,
},
},
];
const TextSlide = ({ title, text = [], list, image }) => {
return (
<>
<div className="slide">
<div className="standard-grid">
<span className="slide-title title">{title}</span>
<div className="content">
{text.map((t, i) => (
<p key={i} className="text" dangerouslySetInnerHTML={t} />
))}
</div>
{image ? (
<img
className="picture"
src={image.src}
style={{ maxWidth: image.width }}
alt="image"
/>
) : null}
</div>
</div>
</>
);
};
Here is a small codepen for demonstration.
Try this:
text: ["The ", <strong>target audience</strong>, " for this course is anyone who is assigned roles as a HR Employee Maintainer..."]
React will render this as a string with the HTML tags applied.
Related
I am working on a page
have two sections. In one section we upload image and can increase the number of input, in the other section we will preview the image.
I don't know I am not getting the right id that I want to edit.
we can add more fields on click of button and remove then at the end post data at api endpoint?
RightSection
const RightSection = ({ inputImage, setInputImage }) => {
const handleAddFields = () => {
if (inputImage.length <= 9) {
const values = [...inputImage];
values.push({
id: values.length + 1,
name: `Drop Image ${values.length + 1} Here`,
});
setInputImage(values);
}
};
const handleRemoveFields = () => {
if (inputImage.length > 3) {
const values = [...inputImage];
values.splice(values.length - 1, 1);
setInputImage(values);
}
};
const handleInputChange = (id, event) => {
console.log(id, event.target.id, "=====");
const newInputFields = inputImage.map((i) => {
if (id === i.id) {
i.url = URL.createObjectURL(event.target.files[0]);
i.name = event.target.files[0].name;
// push image object in array
setInputImage([
...inputImage,
{
id: id,
url: URL.createObjectURL(event.target.files[0]),
name: event.target.files[0].name,
},
]);
}
return i;
});
setInputImage(newInputFields);
};
console.log(inputImage);
return (
<>
<div id="right" className="flex">
<div className="margin">
<div className="inlineflex">
<H1>Background Image</H1>
<div>
<AddIcon onClick={handleAddFields} />
<RemoveIcon onClick={handleRemoveFields} />
</div>
</div>
</div>
<div
style={{
margin: "0 auto",
position: "relative",
width: "80%",
}}
>
{inputImage.map((inputField, index) => (
<FileInput key={index}>
<label
htmlFor={inputField.id}
onClick={(e) => {
console.log("click", index + 1);
}}
>
{inputField.name}
</label>
<input
id={index + 1}
onChange={(event) => handleInputChange(inputField.id, event)}
accept="image/*"
type="file"
/>
</FileInput>
))}
</div>
</div>
</>
);
};
LeftSection
const LeftSection = ({ inputImage }) => {
return (
<>
<div id="left" className="flex">
<div className="margin">
<H1>Preview</H1>
</div>
<Grid>
{Array.isArray(inputImage) &&
inputImage.map((item, index) => {
if (item?.url?.includes("http") || item?.url?.includes("https")) {
return (
<div key={index}>
<img src={item?.url} alt={item?.name} />
</div>
);
}
})}
</Grid>
</div>
</>
);
};
BackgroundImage
let initaValue = [
{ id: 1, name: "Drop Image 1 Here", url: "" },
{ id: 2, name: "Drop Image 2 Here", url: "" },
{ id: 3, name: "Drop Image 3 Here", url: "" },
];
const BackgroundImage = () => {
const [inputImage, setInputImage] = useState(initaValue);
return (
<>
<Container>
<RightSection inputImage={inputImage} setInputImage={setInputImage} />
<LeftSection inputImage={inputImage} setInputImage={setInputImage} />
</Container>
</>
);
};
export default BackgroundImage;
I think there is some issue with the handleInputChange function on the RightSection component.
Somehow I am not able to update the item with the correct id in the array.
Is there any other efficient solution for this problem?
I am trying to mapping through three objects in react to render multiple categories on react template , Code doesn't give any error but its not showing any content on react web page.
return (
<div className="container pt-80">
<center>Category Grouping</center>
{categories.map((cate,key)=>{
subCategories.map(subCate=>{
if(subCate.category === cate.id){
pType.map(ptype=>{
if (ptype.category === subCate.id){
console.log("Category : ",cate.category)
console.log("Sub Category : ",subCate.subCatName)
console.log("Product Type : ",ptype.ptype)
console.log("*******************************************")
return(
<Fragment>
<h1 style={{marginLeft:"30px"}}>{cate.category}</h1>
<h1 style={{marginLeft:"60px"}}>{subCate.subCatName}</h1>
<h1 style={{marginLeft:"120px"}}>{ptype.ptype}</h1>
</Fragment>
)
}
})
}
})
})}
</div>
)
Its printing the correct values in console :
Extending what #Akhil said in the comment. You are actually not returning anything in you're first two map calls, only the last.
add return before both nested map calls:
return subCategories.map(subCate=>{...
and
return pType.map(ptype=>{
Also I would add a return null after your if statements. Map expects a return value.
if(subCate.category === cate.id){
....
}
return null;
and
if (ptype.category === subCate.id){
....
}
return null;
Look into the comment by #Akhil. You missed the return for the map.
const categories = [{ id: 1, category: "Foods & Supplements" }];
const subCategories = [{ id: 1, category: 1, subCatName: "Herbal Drinks" }];
const pType = [
{ id: 1, category: 1, ptype: "Herbal Juice" },
{ id: 2, category: 1, ptype: "Herbal Coffee Tea&Soup" }
];
export default function App() {
return (
<div>
<h1>Category Grouping</h1>
{categories.map((cate, key) => (
<div key={key}>
{subCategories.map((subCate, sKey) => (
<div key={sKey}>
{subCate.category === cate.id &&
pType.map((ptype, pKey) => (
<div key={pKey}>
{ptype.category === subCate.id && (
<>
<h1 style={{ marginLeft: "30px" }}>{cate.category}</h1>
<h1 style={{ marginLeft: "60px" }}>
{subCate.subCatName}
</h1>
<h1 style={{ marginLeft: "120px" }}>{ptype.ptype}</h1>
</>
)}
</div>
))}
</div>
))}
</div>
))}
</div>
);
}
Also, use some sort of linting (e.g. Eslint) and format the code, both will help to catch syntax errors.
I'm having issue where when i put my state into index of an array, it gives error.
Here is there line of bug : {WorkData[state].title}
What i need to do is to display the elements of WorkData which is a array with objects : title, content, img math etc...
const WorkData = [
{
id: 0,
title: 'title',
subtext: 'React/Express',
content: 'content',
imgPath: 'imgPath',
},
{
id: 1,
title: 'Little Hero Academy',
subtext: 'React/API REST',
content:
'content,
imgPath: 'imgPath',
},
{
id: 2,
title: 'title',
subtext: 'subtext',
content: 'content',
imgPath: 'imgPath',
},
First, i have a list of cards with a button that contains data:
<div className="work-container flex">
<div className="work-bloc zoom">
<div className="work-hover" />
<div className="work-text">
<div className="text-title">{WorkData[0].title}</div>
<span className="subtext">{WorkData[0].subtext}</span>
</div>
<div
onClick={togglePopup}
data-id={WorkData[0].id}
className="work-showmore button2"
>
Show More
</div>
</div>
</div>
I store the data in state with this function :
const [id, setId] = useState();
const togglePopup = (e) => {
setIsOpen(!isOpen);
setId(e.target.dataset.id);
};
I need that data to get to the popup,
<Popup
togglePopup={togglePopup}
closePopup={closePopup}
isOpen={isOpen}
id={id}
/>
I pass the state to my popup component and try to display the value of id which is displayed
Also,i need to make the popup display of the content of the array that belong to the id (index) i passed in state : workData 1 2 3 etc...
const Popup = ({ closePopup, isOpen, id }) => {
return (
<div className={`popup-container ${isOpen ? 'opened' : 'closed'}`}>
<div className={`popup ${isOpen ? 'opened2' : 'closed2'}`}>
<span className='popup-title'>
{WorkData[id].title}
{id}
</span>
<div className='image-container'>
<img
src='https://i.picsum.photos/id/1060/536/354.jpg?blur=2&hmac=0zJLs1ar00sBbW5Ahd_4zA6pgZqCVavwuHToO6VtcYY'
alt=''
/>
</div>
<p>
Team projet with React and API REST. Our goal was to make an app with
a choosen API and make something out of it. We did a superhero-themed
website with games for children.
<br />
Check on <AiFillGithub className='menuicon' />
</p>
<div onClick={closePopup} className='close-icon button2'>
Show less{' '}
</div>
</div>
</div>
);
};
but i get this error :
**TypeError: _WorkData__WEBPACK_IMPORTED_MODULE_1__.default[id] is undefined**
Thanks in advance for any suggestion
Ok i fixed, it i changed the way of doing it, i mapped my workcard components so i can easily retrieve the id, title, etc, and i didnt change the event onclick to catch the card.id in state, i passed the state to parent, then to the popup, and then into the popup component i just imported the WorkData.js and simply did : WorkData[state-with-id].title etc
See sample of code below
works.js
const togglePopup = (e) => {
setIsOpen(!isOpen);
setPopupId(e.target.dataset.id);
};
const closePopup = () => {
setIsOpen(false);
};
useEffect(() => {
setCards(workData);
}, []);
workcards.js
<div
onClick={togglePopup}
className='work-showmore button2'
data-id={workcard.id}
>
popup.js
import workData from './workData';
<span className='popup-title'>{workData[popupId].title}</span>
This is my first Wordpreess Gutenberg block using the <img> tag. I can't seem to get the image to display. The text renders but it seems the image src doesn't work. When I open up the DOM and inspect elements the <img> tag is in the DOM tree but there is no src it's just empty. I've tried putting the <Media Upload> both inline and in the <Panel Body> but either way the <img src> is not taking. I'm certain I'm overlooking something but after much trial and error, I cannot seem to connect the <Media Upload> to the image source properly.
const { registerBlockType } = wp.blocks;
const {
RichText,
InspectorControls,
ColorPalette,
MediaUpload,
MediaUploadCheck,
Button,
RawHTML,
InnerBlocks
} = wp.editor;
const { PanelBody, IconButton } = wp.components;
const ALLOWED_BLOCKS = ['core/button', 'core/html', 'core/image']
registerBlockType('mycustomblock/feature-block', {
//Built-in Attributes
title: 'Feature Block',
description: 'Block Description',
icon: 'align-pull-left',
category: 'design',
//Custom Attributes
attributes: {
title: {
type: 'string',
source: 'html',
selector: 'p'
},
titleColor: {
type: 'string',
default: 'black'
},
bodyColor: {
type: 'string',
default: 'black'
},
image: {
type: 'object',
source:'html',
selector:'feature-icon'
},
body: {
type: 'string',
source: 'html',
selector: 'p'
}
},
//Built-in Functions
edit({attributes, setAttributes}) {
const{
title,
body,
titleColor,
bodyColor,
image,
} = attributes;
//Custom Functions
function onChangeTitle(newTitle) {
setAttributes( { title: newTitle } );
}
function onChangeBody(newBody) {
setAttributes( { body: newBody } );
}
function onTitleColorChange(newColor){
setAttributes( { titleColor: newColor } );
}
function onBodyColorChange(newBodyColor){
setAttributes( { bodyColor: newBodyColor } );
}
function onSelectImage(newImage) {
setAttributes( { image: newImage.sizes.full.url } )
}
return ([
<InspectorControls style={ { marginBottom: '40px' } }>
{/* <PanelBody title={ 'Image Settings' }>
</PanelBody> */}
<PanelBody title={ 'Headline Color' }>
<p><strong>Choose Title Color</strong></p>
<ColorPalette
value={titleColor}
onChange={onTitleColorChange}
/>
</PanelBody>
<PanelBody title={ 'Description Color' }>
<p><strong>Choose Description Color</strong></p>
<ColorPalette
value={bodyColor}
onChange={onBodyColorChange}
/>
</PanelBody>
</InspectorControls>,
<div class="row">
<div class="col-md-4">
<div class="feature-icon-container">
<MediaUpload
onSelect={onSelectImage}
type="image"
value={image}
render={ ( { open } ) =>
<IconButton
onClick={ open }
icon="upload"
className="editor-media-placeholder__button is-button is-default is-default"
>
Select Image
</IconButton>
}
/>
</div>
<div class="feature-description-container">
<RichText
key="editable"
tagName="p"
placeholder="Feature Title"
value= { title }
onChange= { onChangeTitle }
style= { { color: titleColor } }
/>
<RichText
key="editable"
tagName="p"
placeholder="Description"
value= { body }
onChange= { onChangeBody }
/>
</div>
</div>
</div>
]);
},
save({ attributes }) {
const {
title,
body,
titleColor,
bodyColor,
image,
} = attributes;
return(
<div class="row">
<div class="col-md-4">
<div class="feature-image-container">
<img class="feature-icon" src={ { image } } />
</div>
<div class="feature-description-container">
<RichText.Content style={ {color:titleColor } } tagName="p" value={title} />
<RichText.Content style={ {color:bodyColor } } tagName="p" value={body} />
</div>
</div>
</div>
)
}
});
There's a couple of things we need to correct, I'll just point you in the right direction:
Small misconception in how you "source" your image attribute. You are getting the src of the image from the MediaUpload component and set the image attribute (which is a URL string) via your onSelectImage function. In the way you declared it now you try to source it from the innerHTML of an html selector.
Therefore the following syntax is sufficient in your attribute declaration:
image: {
type: 'string',
default: '',
}
Instead of an empty string you can insert the src url for a default/placeholder image – if you want to.
And just to let you know: Sourcing from an html selector only makes sense if the innerHTML of that selector is editable in the content of the block, like an editable rich text component (i. e. paragraph).
You need some logic in edit to actually display the image in the backend after it has been selected. Below is just a simple version that needs to be further optimized (as you cannot select another image this way).
Replace your complete <div class="feature-icon-container"></div> structure in edit with this:
<div class="feature-image-container">
{ image === '' ?
<MediaUpload
onSelect={onSelectImage}
type="image"
value={image}
render={ ( { open } ) =>
<IconButton
onClick={ open }
icon="upload"
className="editor-media-placeholder__button is-button is-default is-default">
Select Image
</IconButton>
}
/>
:
<img class="feature-icon" src={ image } />
</div>
Change the double curly braces to single curly braces in save. Otherwise your URL string will be wrapped in an object.
<img class="feature-icon" src={ image } />
Maybe it will be best to move your MediaUpload to the controls sidebar, then it will be easier to keep the functionality of changing the selected image. Also if you set a default image it will not be possible to base your conditional on checking for an empty image string. But I'll leave this up to you.
I am working on a web app in the ReactJS framework and I'm using react-slideshow-image component for a simple slideshow. However due to how the component works, I can only render the images. I would like to add a short description for each image and have it appear with it. Is there a way to modify this code to render a description under the image? (I was thinking about useEffect hook but I'm not sure.)
const Slideshow = () => {
return (
<SlideContainer>
//styled component
<Zoom scale={0.4}>
//Zoom component comes from react-slideshow-image
{
slideshowImages.map((each, index) => <img key={index} style={{padding: "0", margin: "0", width: "20vw"}} src={each} />)
}
</Zoom>
</SlideContainer>
)
};
Try this behavior, Here you can show the description on the image.
const images = [
{
id: "img1",
url: "../images/image-1.png",
description: "image 1 description here"
},
{
id: "img2",
url: "../images/image-2.png",
description: "image 2 description here"
}
];
const Slideshow = () => {
return (
<div className="slide-container">
<Zoom {...zoomOutProperties}>
{images.map((each, index) => (
<div
style={{
background: `url(${each.url}) no-repeat`,
width: "300px",
height: "240px"
}}
>
<b>{each.description}</b>
</div>
))}
</Zoom>
</div>
);
};
Hope you are looking for the same use case.
Working demo:- https://codesandbox.io/s/modest-proskuriakova-28qsk?file=/src/App.js
This wasn't quite what I wanted but it pointed me in the right direction. Here's my solution inspired by yours and official React documentation:
const slideshowImages = [
{
id: 1,
image: "/imageUrl",
desc: //description
},
//as many elements as you want
]
const Slideshow = () => {
//SlideContainer and DescriptionWrapper are styled components
return (
<SlideContainer>
<Zoom {...zoomOutProperties}>
{
slideshowImages.map(
(slide) =>
<div key={slide.id}>
<img style={{padding: "0", margin: "0", width: "20vw"}} src={slide.image} />
<DescriptionWrapper>{slide.desc}</DescriptionWrapper>
</div>
)
}
</Zoom>
</SlideContainer>
)
};
export default Slideshow;
Thanks a lot, I wouldn't have thought of something like this.