pass an object containing html as an attribute to jsx element - javascript

I have a main component called VariantList which lists some boxes stacked on top of each other based on a json I created myself,there is a copy button on each box when clicked another box will be created below the first one exactly the same as the first one.
My problem is that when I save the data as an attribute in the box element, the inner object containing jsx will not be readable when the box is created an throw an error.
import React, { Component } from 'react';
class VariantList extends Component {
constructor() {
super();
this.handleCopy = this.handleCopy.bind(this);
this.state = {
variants: [
{
id: 1,
title: 'تنوع ۱',
status: {
number: 1,
title: 'تایید شده'
},
description: 'تنوع های مختص این محصول',
variants: [
{
icon: 'fa-paint-brush',
title: 'رنگ انتخاب شده:',
value: <div>
<span style={{ width:"12px",height:"12px",margin:"0 4px",backgroundColor:"#ff0000",borderRadius:"50%",display: "inline-block",verticalAlign: "middle" }}></span>
<span>قرمز</span>
</div>
},
{
icon: 'fa-pencil',
title: 'سایز:',
value: <span>XL</span>
},
{
icon: 'fa-plane',
title: 'گارانتی:',
value: <span>امرتات</span>
},
{
icon: 'fa-tag',
title: 'قیمت:',
value: <span>۱۲۰۰۰۰۰۰ تومان</span>
},
{
icon: 'fa-tint',
title: 'حافظه:',
value: <span>512 GB</span>
},
{
icon: 'fa-wifi',
title: 'تخفیف:',
value: <span>۲۵٪</span>
},
{
icon: 'fa-send',
title: 'هدیه:',
value: <span>دارد</span>
},
{
icon: 'fa-signal',
title: 'موجودی:',
value: <span>۱۰۰ عدد</span>
},
{
icon: 'fa-vcard',
title: 'زمان بندی:',
value: <span>۸ صبح پنج شنبه ۲۳ آبان</span>
}
]
}
]
}
}
handleCopy(variant) {
let variantArr = this.state.variants;
variantArr.splice(this.state.variants.findIndex(x => x.id === variant.id),0,variant);
this.setState({
variants: variantArr
});
}
render() {
let variant_boxes = [];
for (let i = 0; i < this.state.variants.length; i++) {
variant_boxes.push(<VariantBox key={ i } data = { this.state.variants[i] } copyVariant={ this.handleCopy } index={ i+1 } />);
}
return (
<div id="variantBoxContainer" className="row no-gutters">
{ variant_boxes }
</div>
);
}
}
class VariantBox extends Component {
constructor(props) {
super(props);
this.handleCopy = this.handleCopy.bind(this);
this.variantRef = React.createRef();
}
handleCopy = () => {
this.props.copyVariant(JSON.parse(this.variantRef.current.getAttribute('variant')));
}
render() {
return(
<div className="col-xxl-12 justify-content-center yelno-bg-white variant_box"
variant={ JSON.stringify(this.props.data) }
ref={this.variantRef} >
<div className="row no-gutters">
<div className="col-xxl variant_badges">
<div className="yelno-badge variant">
<span className="innerBadge">{ this.props.data.title }</span>
</div>
{
this.props.data.status.number ?
"" :
<div className="yelno-badge inprocess">
<span className="innerBadge">{ this.props.data.status.title }</span>
</div>
}
</div>
<div className="col-xxl text-left action_btn_container">
<div className="action_btn d-inline-block">
<i className="fa fa-copy fa-lg" variantid={ this.props.data.id } onClick={ this.handleCopy }></i>
</div>
<div className="action_btn d-inline-block">
<i className="fa fa-edit fa-lg"></i>
</div>
<div className="action_btn d-inline-block">
<i className="fa fa-eye fa-lg"></i>
</div>
<div className="action_btn d-inline-block">
<i className="fa fa-trash fa-lg"></i>
</div>
</div>
</div>
<div className="row no-gutters variant-attributes">
<VariantItem data = { this.props.data.variants } />
</div>
</div>
);
}
}
class VariantItem extends Component {
render() {
return(
this.props.data.map((data,index) => {
return (
<div key={ index } className="col-xxl text-center">
<i className={ "fa " + data.icon + " fa-2x yelno-color-light-grey variant-attribute-icon" }></i>
<span className="variant-attribute-title d-block yelno-color-light-grey">
{ data.title }
</span>
<div className="variant-attribute-value yelno-12BoldS">
{/* { data.value } */}
</div>
</div>
);
})
);
}
}
export default VariantList;
I have commented {/* { data.value } */} but if I uncomment it after clicking copy button an error is thrown due to the undefined this.state.variants[i].variants[j].value which contains html.
Your help is much appreaciated in advance.

I found the answer by the idea I was given in the comments, so I didn't save HTML node as JSX in JSON instead saved it as string and used the react-html-parser library to convert the string to react component like below:
import ReactHtmlParser from 'react-html-parser';
edited this line in the JSON in VariantList component
value: '<div><span style="width:12px;height:12px;margin:0 4px;background-color:#ff0000;border-radius:50%;display: inline-block;vertical-align: middle; "></span><span>قرمز</span></div>'
and finally in the VariantItem component converted { data.value } to { ReactHtmlParser(data.value) } and it worked perfectly.

Related

Vue3 toggle element in v-for loop

I am looping through an array on v-for loop in vue 3. Is there a way to toggle the v-show of a paragraph by clicking on the Heading element. Below is my code :
<div class="defs">
<ul v-for="(d, index) in definitions"
:key="'d' + index">
<li>
<div class="project" >
<div #click="showDetails" class="actions">
<h3>{{ d.title }}</h3>
<div class="icons">
<span class="material-icons" ><i class="fas fa-trash-alt"></i></span>
<span class="material-icons" ><i class="fas fa-pencil-alt"></i></span>
</div>
</div>
<div v-if="show" class="details">
<p>{{d.explanation}}</p>
</div>
</div>
</li>
</ul>
</div>
<script>
import { ref } from "vue";
import { projectDatabase} from '../../firebase/config'
export default {
props: ['id'],
setup(props){
const show = ref(false);
const showDetails = () =>{
show.value = !show.value
}
return {
definitions, props, show, showDetails,
}
}
}
</script>
I know we cant use this in composition API. so how can we solve the toggle issue ?
Try like following snippet, here is the codesandbox with composition API
const demo = {
data() {
return {
definitions: [
{ title: "aaa", explanation: "aaa" },
{ title: "bbb", explanation: "bbb" },
{ title: "ccc", explanation: "ccc" },
],
show: null
}
},
methods: {
showDetails(idx) {
this.show === idx ? (this.show = null) : (this.show = idx);
}
},
// same code with coposition API
/*import { ref } from "vue";
import { projectDatabase} from '../../firebase/config'
setup() {
const show = ref(null);
const definitions = ref([
{ title: "aaa", explanation: "aaa" },
{ title: "bbb", explanation: "bbb" },
{ title: "ccc", explanation: "ccc" },
]);
const showDetails = (idx) => {
show.value === idx ? (show.value = null) : (show.value = idx);
};
return { definitions, show, showDetails }
},*/
};
Vue.createApp(demo).mount("#demo");
<script src="https://unpkg.com/vue#next"></script>
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous" />
<div id="demo">
<div class="defs">
<ul>
<li v-for="(d, index) in definitions" :key="index">
<div class="project">
<div #click="showDetails(index)" class="actions">
<h3>{{ d.title }}</h3>
<div class="icons">
<span class="material-icons"
><i class="fas fa-trash-alt"></i
></span>
<span class="material-icons"
><i class="fas fa-pencil-alt"></i
></span>
</div>
</div>
<div v-if="show === index" class="details">
<p>{{ d.explanation }}</p>
</div>
</div>
</li>
</ul>
</div>
</div>

pass change of prop from parent to child with change Vue 3 Option api

Ok...king..
I'm trying to pass a value to child when a click event occur from other component it will change the prop value from parent. But it only shown the first mount value that pass.
topdown component that emit change
<template>
<div class="dropdown">
<button
class="btn btn-secondary dropdown-toggle h-75"
type="button"
id="dropdownMenuButton1"
data-bs-toggle="dropdown"
aria-expanded="false"
>
{{ value }}
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1" role="menu">
<li v-for="option in options" :key="option">
<a
class="dropdown-item"
#click="(value = option);dunder;dundet;"
href="javascript:void(0)"
>{{ option }}</a
>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "TopDown",
data() {
return {
options: ["Edit", "Delete"],
value: "",
};
},
computed:{
dunder(){
return this.$emit("edit-task", this.value)
},
dundet(){
return this.$emit("edit-task-index",this.value)
}
}
};
</script>
<style>
</style>
parent component
<template>
<div
v-for="(item, index) in tasker"
:items="item"
:key="index"
class="border border-dark "
>
<section class="d-flex justify-content-between">
<h4 class="w-50 font-weight-bold fs-5">
<u>{{ item.title }}</u>
</h4>
<TopDown
#edit-task="val"
#edit-task-of="show(item, index)"
:index="index"
/>
</section>
<p class="text-start">{{ item.description }}</p>
<GoTask :showVal="showVal" :bool="bool" />
</div>
</template>
<script>
import TopDown from "#/components/TopDown.vue";
import GoTask from "#/components/GoTask.vue";
export default {
inheritAttrs: false,
components: {
TopDown,
GoTask,
},
data() {
return {
takss: {
items: "sss",
index: "",
},
showVal: "",
bool: false,
};
},
name: "Taski",
props: ["tasker"],
methods: {
show(item, index) {
this.takss.items = item;
this.takss.index = index;
},
val(val) {
if (val == "Edit") {
setTimeout(() => {
console.log(this.takss);
this.showval = this.takss;
console.log(this.showval);
console.log(this.bool)
}, 1000);
this.bool = !this.bool;
}
},
},
};
</script>
<style></style>
child component
<template>
<section
v-if="bools"
class="bg-white"
style="z-index: 20"
#click="closeModal"
></section>
<section
v-if="bools"
class="position-absolute"
style="
z-index: 50;
left: 50%;
top: 50%;
height: 100vh;
margin-top: 20vh;
"
>
<form
class="mt-10"
#submit.prevent="editTask"
>
<input
class="border rounded p-2 mb-2"
v-model.lazy="newTask.title"
placeholder="Title"
type="text"
/>
<textarea
ref="texsearch"
rows="20"
class=" p-2 mb-2"
v-model.lazy="newTask.description"
placeholder="Task Details"
type="text"
></textarea>
<button
class="border rounded p-2 bg-success text-white"
type="submit"
#submit.prevent=""
>
New Task
</button>
</form>
</section>
<button #click="test">dd</button>
</template>
<script>
export default {
inheritAttrs: false,
name: "GoTask",
props: ["tasker", "showVal", "bool"],
data() {
return {
showVals: this.showVal,
bools: this.bool,
newTask: {
title: "",
description: "",
},
};
},
methods: {
test() {
console.log(this.bools);
console.log(this.showVal);
},
ModalOpen() {
this.bools = true;
},
closeModal() {
this.bools = false;
},
showModal() {
this.bools = true;
// auto focus
this.$nextTick(() => {
this.$refs.textsearch.focus();
});
},
showtheVal() {
console.log(this.showtheVal);
},
},
};
</script>
<style></style>
When I click the button form other component that emit change of #edit-task-of and #edit-task the it doesn't send the new value of bool and showval to child component the bool value still false as same as first mount and showVal = "" when click button that run test function to see this two value at child. I'm totally new to vue. Thanks
You do mistake in GoTask component , method test, first console.log(this.bools);, bools is local state which is not updated after prop bool changed, just do correct console.log(this.bool);. You don't need to set props to local state, you can use props directly.
GoTask correct example:
props: ["tasker", "showVal", "bool"],
data() {
return {
newTask: {
title: "",
description: "",
},
};
},
methods: {
test() {
console.log(this.bool);
console.log(this.showVal);
},
codesandbox

React - map issues, empty paragraphs

I have objects that go through the map, everything was fine until I added the "title" property when rendering, empty paragraphs were displayed https://ibb.co/hfp07t9
JavaScript_Lessons_Objects.js
import React from "react";
import jsStyle from "./css/JavasCript_Lesson.module.css";
import {faDotCircle} from "#fortawesome/free-solid-svg-icons/faDotCircle";
const one = "Robby";
function JavaScriptLessonObject() {
return (
[
{
title: [<div><span className={jsStyle.title}>JSON OBJECTS</span></div>],
},
{
titleName: "JS Introduction",
iconName: faDotCircle,
description: [
<span className="yourClass">{one}</span>,
` advanced diverted domestic sex repeated bringing you old.`
],
},
{
titleName: "JS Where To",
iconName: faDotCircle,
description: [
<span className="yourClass">{one}</span>,
` advanced diverted domestic sex repeated bringing you old.1`
],
},
{
title: [<div><span className={jsStyle.title}>JSON OBJECTS</span></div>],
},
{
titleName: "JS Output",
iconName: faDotCircle,
description: [
<span className="yourClass">{one}</span>,
` advanced diverted domestic sex repeated bringing you old.`
],
},
]
);
}
export default JavaScriptLessonObject;
Lesson.jsx
import React from 'react';
import less from "./css/lesson.module.css";
import "./css/betaLesson.css";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { Navbar } from "../../../Navbar/Navbar";
export class Lessons extends React.Component {
constructor(props) {
super(props);
this.state = {
indexDescription: 0,
}
}
render() {
const listLessons = this.props.lesson.map((item, index) => {
return (
<div key={index}>
<li style={{background: "#ffa50070"}}>
<div>
<p>{item.title}</p>
</div>
</li>
<li onClick={() => { this.setState({ indexDescription: index }) }}>
<div className={less.sidebar_list}>
<div>
<FontAwesomeIcon className={less.item_icon} icon={item.iconName} />
</div>
<div className={less.titleName}>
<div>
<p>{item.titleName}</p>
</div>
</div>
</div>
</li>
</div>
);
});
return (
<>
<div className="abc">
<Navbar color="blue" bg="tomato" centerFlexNavbarContainer="flex"
navbarSearchPage="Search" navbarHomePage="Home" centerHeadlineNavbarColumn="center" />
<div className={less.wrapper}>
<div>
<div className={less.sidebar}>
<div>
<ul>
{listLessons}
</ul>
</div>
</div>
</div>
<div className={less.main_content}>
<div className={less.main_inside_content}>
<div className={less.header}>
<div>
<h2>JavaScript JSON Reference</h2>
</div>
</div>
<div className={less.info}>
<div className={less.description}>
<p>
{
this.props.lesson[this.state.indexDescription]["description"]
}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</>
);
}
}
I think the problem is clear, when I added in the title object: [<div> <span className = {jsStyle.title}> JSON OBJECTS </span> </div>], I get empty paragraphs. I specifically set the color orange to make it easier to navigate

Vue modal with a router

I am new to Vue. I am building a simple app that will list all countries and when you click on a particular country it shows you more details about the country. Idea is to open country details in a modal.
I'm stuck with displaying that modal. The modal opens, but in the background. It also opens a detail page.
CountryDetail.vue:
<script>
import axios from 'axios';
export default {
name: 'country-detail',
props: [ 'isDarkTheme' ],
data () {
return {
pending: false,
error: null,
countryInfo: null,
alpha3Code: [],
alpha3CodetoString: [],
}
},
mounted () {
this.pending = true;
axios
.get(`https://restcountries.eu/rest/v2/name/${this.$route.params.country}?fullText=true`)
.then((response) => {
(this.countryInfo = response.data)
this.alpha3CodetoString = this.alpha3Code.join(';');
})
.catch(error => (this.error = error ))
.finally( () => { this.pending = false });
},
filters: {
formatNumbers (value) {
return `${value.toLocaleString()}`
}
}
}
</script>
<template>
<modal v-model="show">
<div class="modal-mask" :class="{ darkTheme : isDarkTheme }" name="modal">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
<h1 v-if="error !== null">Sorry, an error has occurred {{error}}</h1>
<div class="loaderFlex"><div v-if="pending" class="loader"></div></div>
</slot>
</div>
<div v-for="country in countryInfo" class="countryTile modal-body" v-bind:key="country.id">
<slot name="body">
<img v-bind:src="country.flag" alt="Country Flag" class="flag">
<div class="country-details">
<h1>{{country.name}}</h1>
<div class="listDiv">
<ul>
<li><span>Population:</span> {{country.population | formatNumbers }}</li>
<li><span>Capital:</span> {{country.capital}}</li>
<li><span>Iso:</span> {{country.alpha3Code}}</li>
</ul>
<ul>
<li><span>Currencies:</span> {{country.currencies['0'].name}}</li>
<li><span>Languages:</span>
<span
v-for="(language, index) in country.languages"
v-bind:key="index"
class="languages">
{{language.name}}<span v-if="index + 1 < country.languages.length">, </span>
</span>
</li>
</ul>
</div>
</div>
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
<a #click="$router.go(-1)" class="backBtn"><i class="fas fa-arrow-left" />Go Back</a>
</slot>
</div>
</div>
</div>
</div>
</modal>
</template>
Home.vue:
<script>
import axios from 'axios';
export default {
name: 'home',
props: [ 'isDarkTheme' ],
data () {
return {
pending: false,
error: null,
countryInfo: null,
search: '',
darkMode: false,
}
},
mounted () {
this.pending = true;
axios
.get('https://restcountries.eu/rest/v2/all')
.then(response => (this.countryInfo = response.data))
.catch(error => (this.error = error ))
.finally( () => { this.pending = false });
},
filters: {
formatNumbers (value) {
return `${value.toLocaleString()}`
}
},
computed: {
filteredCountries: function () {
return this.countryInfo.filter((country) => {
if (this.region === '' ) {
return country.name.toLowerCase().match(this.search.toLowerCase());
} else if (this.search !== '') {
return country.name.toLowerCase().match(this.search.toLowerCase());
} else {
return ('blbla');
}
})
}
},
}
</script>
<template>
<div class="home" :class="{ darkTheme : isDarkTheme }">
<div class="searchBar">
<div class="searchContainer">
<i class="fas fa-search searchIcon"></i>
<input
class="searchInput"
type="text"
v-model="search"
aria-label="Search for a country..."
placeholder="Search for a country..."
/>
<ul class="searchResults"></ul>
</div>
</div>
<h1 v-if="error !== null">Sorry, an error has occurred {{error}}</h1>
<div class="loaderFlex"><div v-if="pending" class="loader"></div></div>
<div v-if="countryInfo" class="tileGrid" #click="showModal = true">
<div v-for="country in filteredCountries" class="countryTile" v-bind:key="country.id">
<router-link
:to="{ name: 'country-detail', params: {country: country.name }}"
class="linkTile"
>
<img v-bind:src="country.flag" alt="Country Flag" class="flag">
<div class="text">
<h1>{{ country.name }}</h1>
</div>
</router-link>
</div>
</div>
</div>
</template>
The router-link will always redirect you to another page, because its basically <a href="..."> see here. You don't need router if you just want to show the detail on a modal, you could just add the modal component inside the Home.vue component, then bind the modal and the countryName with props, then pass them in when clicking a button.
Home.vue:
<template>
<div>
<button #click="showDetail">
Show Detail
</button>
<CountryDetail :countryName="countryName" :showModal="showModal"/>
<div>
</template>
<script>
import CountryDetail from './CountryDetail.vue'
export default {
name: 'Home',
components: { CountryDetail },
data: () => ({
countryName: '',
showModal: false,
}),
methods: {
showDetail() {
this.showModal = true;
},
},
}
</script>
And instead of making request on mounted, you could use watch to do something like watching for the showModal prop, and make request everytime it has a truthy value. Like this:
CountryDetail.vue:
<template>
<modal v-model="showModal">
<!-- modal content -->
</modal>
</template>
<script>
export default {
name: 'CountryDetail',
props: ['countryName', 'showModal'],
watch: {
'showModal': {
deep: true,
handler(val) {
if (val && this.countryName !== '') {
// Make request
}
}
}
}
}
</script>

Need help making clickable dropdown menu toggle off while simultaneously toggling the different target dropdown

I have a nav bar with dropdown buttons that toggle on with button press and off with clicking outside the window. When you hover over each button, the text is underlined in yellow. When you click the button, a list of other buttons drops down beneath it. If the user decides to open another drop down while one is already open, it takes two clicks. One to click out of the current dropdown window, and one to click on the new button. I would like it to have a case of clicking off on a navbutton to simultaneously close the current window and open the new target window.
Another small detail that I'm struggling to implement is to make the clicked navbar button toggle on the same underlined style that appears when hovering. I'm struggling in both case to target and reference the right element.
class NavBar extends Component {
constructor(){
super();
this.state = { displayMenu: '' }
this.showDM = this.showDM.bind(this);
this.hideDM = this.hideDM.bind(this);
}
showDM (type) {
this.setState({ displayMenu: type }, () => {
document.addEventListener('click', this.hideDM);
});
}
hideDM (ev) {
this.setState({ displayMenu: '' }, () => {
document.removeEventListener('click', this.hideDM)
});
}
render() {
return (
<header>
<div className="image">
<img className="logo" src={Logo} alt="Pre-Collegiate Program Yangon" />
</div>
<div className="right">
<div className="text" >
<h1 className="pcp"><strong>The Pre-Collegiate Program </strong>of Yangon</h1>
</div>
<div className="navbar">
<div className="dropdown">
<button id="about" onClick={() => this.showDM("about")} className="dropbtn">About
<i className="fa fa-caret-down"></i>
</button>
{ this.state.displayMenu === "about" ? (
<div className="dropdown-content" id="ddc">
<Link to="/mission">Mission</Link>
<Link to="/history">History</Link>
<Link to="/alumni">Alumni</Link>
</div>
):
(
null
)
}
</div>
<div className="dropdown">
<button onClick={() => this.showDM("academics")} className="dropbtn">Academics
<i className="fa fa-caret-down"></i>
</button>
{ this.state.displayMenu === "academics" ? (
<div className="dropdown-content" id="ddc">
<Link to="/liberal-arts">Liberal Arts Education</Link>
<Link to="/faculty-and-staff">Our Faculty and Staff</Link>
<Link to="/curriculum">Our Curriculum</Link>
<Link to="/study-abroad">Study Abroad</Link>
</div>
):
(
null
)
}
You can do something like this. With this you will separate concerns, have less code, it will be more readable and easier to maintain.
class NavBar extends Component {
constructor(){
super();
this.state = {
menu: [
{
type: 'about',
isOpen: false,
links: [
{
title: "Mission",
link: "/mission"
},
{
title: "History",
link: "/history"
},
{
title: "Alumni",
link: "/alumni"
}
]
},
{
type: 'academics',
isOpen: false,
links: [
{
title: "Liberal Arts Education",
link: "/liberal-arts"
},
{
title: "Our Faculty and Staff",
link: "/faculty-and-staff"
},
{
title: "Our Curriculum",
link: "/curriculum"
},
{
title: "Study Abroad",
link: "/study-abroad"
}
]
}
],
isActive: null
};
}
componentDidMount(){
document.addEventListener('mousedown', this.handleClickOutside);
}
componentWillUnmount(){
document.removeEventListener('mousedown', this.handleClickOutside);
}
activateMenu = (type) => {
this.setState(prevState => {
prevState.displayMenu = type;
for(let i=0; i<prevState.menu.length; i++){
prevState.menu[i].isOpen = prevState.menu[i].type == type ? true : false;
}
return prevState;
});
}
setMenuWrapper = node => {
this.setState({isActive: node});
}
handleClickOutside = e => {
if (this.state.isActive && !this.state.isActive.contains(e.target)) {
this.setState(prevState => {
for(let i=0; i<prevState.menu.length; i++){
prevState.menu[i].isOpen = false;
}
return prevState;
})
}
}
render() {
return (
<header>
<div className="image">
<img className="logo" src="logo" alt="Pre-Collegiate Program Yangon" />
</div>
<div className="right">
<div className="text" >
<h1 className="pcp"><strong>The Pre-Collegiate Program </strong>of Yangon</h1>
</div>
<div className="navbar">
<div ref={this.setMenuWrapper} id="set-menu-wrapper">
{ this.state.menu.map(m => (
<div className="dropdown">
<button id="about" onClick={() => this.activateMenu(m.type)} className="dropbtn">{m.type}
<i className="fa fa-caret-down"></i>
</button>
{ m.isOpen &&
<div className="dropdown-content" id="ddc">
{ m.links.map(l => (
<a href={l.link}>{l.link}</a>
))}
</div>
}
</div>
))}
</div>
</div>
</div>
</header>
);
};
}

Categories