how to use data-target and data-toggle in Reactjs? - javascript

I was converting a static HTML site which uses bootstrap to React.js
Here there are several divs which do open only on data-target and data-toggle.
<div className="card-header" id="headingFive">
<h5 className="mb-0">
<button
className="btn btn-link"
type="button"
data-toggle="collapse"
data-target="#collapseFive"
aria-expanded="true"
aria-controls="collapseOne">
Site Wide Events
</button>
</h5>
</div>
<div
id="collapseFive"
className="collapse show"
aria-labelledby="headingFive"
data-parent="#accordionThree">
<div className="card-body">
<div className="row">
<div className="col wall">
<h4 className="text-center">12</h4>
<p className="text-center">Target</p>
</div>
<div className="col">
<h4 className="text-center">13</h4>
<p className="text-center">Actual</p>
</div>
</div>
</div>
</div>
I don't want to use any other npmmodule for the same.
I tried this but was not able to solve.
componentDidUpdate() {
$('.collapse').bootstrapToggle();
}

Bootstrap 5 (update 2020)
jQuery is no longer required so Bootstrap 5 is easier to use in React. Use the new namespaced data-bs- attributes as explained here or, with React's useEffect useState hooks as explained in this answer.
Bootstrap 4 (original question)
If you don't want to use jQuery or react-bootstrap, you can create a method to toggle the show class on the collapsing Navbar like this...
class Navbar extends React.Component {
constructor(props) {
super(props);
this.state = { showNav: true };
this.toggleNav = this.toggleNav.bind(this);
}
toggleNav() {
this.setState({
showNav: !this.state.showNav
})
}
render() {
const { showNav } = this.state
return (
<div className="navbar navbar-expand-lg navbar-light bg-light">
<a className="navbar-brand" href="#">Navbar</a>
<button className="navbar-toggler" type="button" onClick={this.toggleNav}>
<span className="navbar-toggler-icon"></span>
</button>
<div className={(showNav ? 'show' : '') + ' collapse navbar-collapse'}>
<ul className="navbar-nav mr-auto">
<li className="nav-item">
<a className="nav-link" href="#">Link</a>
</li>
...
</ul>
</div>
</div>
);
}
}
Example with Navbar Collapse
Example with Collapse

// Import the following in your App.js
import 'jquery/dist/jquery.min.js'; // Have to install and import jQuery because of bootstrap modal's dependency
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.bundle.min.js';
Bootstrap dependency https://getbootstrap.com/docs/4.0/getting-started/introduction/#js
Note: I am assuming that your structuring is correct.

Change data-toggle to data-bs-toggle and data-target to data-bs-target. Just managed to find this out myself after looking for ages and not finding a solution anywhere!

Use the new namespaced data-bs- attributes
eg.
<button className='btn btn-outline-info btn-block' data-bs-toggle='modal' data-bs-target='#add'> <i className='fas fa-plus'>Add</i> </button>

Related

My dropdown Menu does not working (react.js)

I need help with this code, at the end production process on the page called projects, my dropdown menu does not work and I have tried many ways to fix that, nevertheless, I can't fix that. Please I am looking forward to your help and answer.
I'm using React-Bootstrap v1.4.3 (Bootstrap 4.6)
import React, { Component } from 'react';
import Project from '../components/project.js';
import { projectData } from '../projectData';
import './projects.css';
export default class Projects extends Component {
constructor(props) {
super(props);
this.state = {
projectID: '',
}
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
e.preventDefault();
const projectID = e.target;
this.setState({ projectID: projectID })
}
render() {
const selectedProject = this.state.projectID;
return(
<div className="col-xs-12 col-lg-10 offset-lg-1 col-xl-8 offset-xl-2 mb-5 pb-5">
<div className="row justify-content-center pb-4">
<div class="dropdown">
<button
class="btn btn-retro dropdown-toggle textspaced textlarge"
type="button"
id="dropdownMenuButton"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
Mission Select
</button>
<div class="dropdown-menu raleway text-center" aria-labelledby="dropdownMenuButton">
{projectData.map((project, index) => {
return <button class="dropdown-item" onClick={this.handleClick} id={index}>{project.title}</button>
})}
</div>
</div>
</div>
<div className="pagebox shadow-lg row justify-content-center pr-0 pl-0">
{this.state.projectID
? <Project
title={projectData[selectedProject].title}
image={projectData[selectedProject].image}
description={projectData[selectedProject].description}
technologies={projectData[selectedProject].technologies}
link={projectData[selectedProject].link}
date={projectData[selectedProject].date_created}
github={projectData[selectedProject].github}
/>
: <h2 className="col-12 text-center textyellow textspaced pt-5 mt-5">
Please select a mission above.
</h2>
}
</div>
</div>
)
}
}

Mapping nested array inside mapped array in React JSX

I'm trying to write a dashboard sidebar which has a couple of "primary" buttons which (via Bootstrap) collapse a number of "secondary" buttons. I want to be able to easily update and style the whole thing so writing static markup is out of the picture. Here is one object out of the array:
const menuArray = [
{
primaryText: "Applications",
primaryIcon: "fa fa-rocket",
primaryURL: "/applications",
secondaries: [
{
secondaryText: "Softwares",
secondaryURL: "/softwares",
},
{
secondaryText: "Videogames",
secondaryURL: "/videogames",
},
{
secondaryText: "Tools",
secondaryURL: "/tools",
},
],
},
]
And here is the function rendering the array which i'm simply calling in the JSX markup by {renderMenuArray}
const renderMenuArray = menuArray.map((menuItem) => (
<li className="py-2">
<button
data-target={`#${menuItem.primaryText}Submenu`}
data-toggle="collapse"
aria-expanded="false"
className="btn btn-dark btn-menu btn-block pl-0 mb-1"
>
<Link to={menuItem.primaryURL}>
<span className="mr-3">
<i className={menuItem.primaryIcon}></i>
</span>
{menuItem.primaryText}
</Link>
</button>
<div
className="card-body collapse ml-5"
id={`${socialItem.primaryText}Submenu`}
>
<ul className="list-unstyled">
<li>
<Link className="small" to="/applications/softwares">
<span className="mr-3">
<i className="fa fa-chevron-right"></i>
</span>
Softwares
</Link>
</li>
</ul>
</div>
));
I can render the "primary" objects with no problem at all, but I want each "primary" object ( each iteration of the parent array) to each iterate through the count of "secondaries" array ( which is going to be different for each "primary" object).
I'm a beginner developer.
The object passed into the callback function for the map, menuItem has the included property secondaries. You can use map on this property since secondaries is an array, simply place the map inside of your JSX.
<div
className="card-body collapse ml-5"
id={`${socialItem.primaryText}Submenu`}
>
<ul className="list-unstyled">
{menuItem.secondaries.map((subItem) => {
...
})
</ul>
</div>
P.S. you forgot to close your last div tag, and you have a second </li> instead of a </ul>
This'll work (made it a bit more functional, to give you an example of what's possible with functional React components)
const menuArray = [
{
primaryText: "Applications",
primaryIcon: "fa fa-rocket",
primaryURL: "/applications",
secondaries: [
{
secondaryText: "Softwares",
secondaryURL: "/softwares"
},
{
secondaryText: "Videogames",
secondaryURL: "/videogames"
},
{
secondaryText: "Tools",
secondaryURL: "/tools"
}
]
}
];
export default function App(props) {
function renderSecondaryMenu(items) {
return items.map(secondaryItem => {
return (
<li>
<Link className="small" to={secondaryItem.secondaryURL}>
<span className="mr-3">
<i className="fa fa-chevron-right" />
</span>
{secondaryItem.secondaryText}
</Link>
</li>
);
});
}
function renderMenuArray() {
return menuArray.map(menuItem => {
return (
<li className="py-2">
<button
data-target={`#${menuItem.primaryText}Submenu`}
data-toggle="collapse"
aria-expanded="false"
className="btn btn-dark btn-menu btn-block pl-0 mb-1"
>
<Link to={menuItem.primaryURL}>
<span className="mr-3">
<i className={menuItem.primaryIcon} />
</span>
{menuItem.primaryText}
</Link>
</button>
<div
className="card-body collapse ml-5"
id={`${menuItem.primaryText}Submenu`}
>
<ul className="list-unstyled">
{renderSecondaryMenu(menuItem.secondaries)}
</ul>
</div>
</li>
);
});
}
return <div className="App">{renderMenuArray()}</div>;
}
I don't think you gain a lot from defining the sidebar as an object, unless you are using the same Sidebar component with different sets of buttons and you wanna be able to switch between them. JSX is already a markup language, so it's declarative.
You could define simply the Sidebar as
const Sidebar = () => (
<PrimaryItem text="Applications" icon="fa fa-rocket" url="/applications">
<SecondaryItem text="Softwares" url="/softwares" />
<SecondaryItem text="Videogames" url="/videogames" />
<SecondaryItem text="Tools" url="/tools" />
</PrimaryItem>
)
And then implement each component as you need to display them. I think this is cleaner and easier to maintain and modify.

Navbar data-toggle and data-target doesn't work

I'm trying to make a responsive navbar.
In desktop shows the NavItems in the NavBar, but in small devices shows the sandwich icon and when we click it should show the same NavItems.
However, when I click on the button, nothing happens.
I was making an adaption of this tutorial:
https://www.youtube.com/watch?v=oUKJA6B1Xr4
The view look like this:
small devices version
desktop version
My NavBar.js
import React, {Component} from 'react';
import NavItems from "./NavItems";
class NavBar extends Component {
render() {
return (
<div>
<nav className="navbar navbar-default panel-app">
<div className="navbar-header">
<button type="button" className="navbar-toggle collapsed" data-toggle="collapse"
data-target="#nav-collapse">
<span className="icon-bar"></span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
</button>
<a className="navbar-brand" href="#">Hoje para jantar</a>
</div>
<div className="collapse navbar-collapse" id="nav-collapse">
<NavItems className="nav navbar-nav" data-toggle="collapse" data-target=".in" href=""></NavItems>
</div>
</nav>
</div>
);
}
}
export default NavBar;
My NavItems.js
import React, {Component} from 'react';
class NavItems extends Component {
constructor(props) {
super(props);
}
render() {
return (
<ul>
<li className="nav navbar-brand">Receitas</li>
<li className="nav navbar-brand">Por categoria</li>
</ul>
);
}
}
export default NavItems;
I forgot to put the jquery link in the index.html file.
Now it works :)

Tabs when set one to active turn all false alogrithim Meteor React

I am trying to:
Make a tab be active and turn off all the other ones.
Currently I only have it working where it will turn off and on one at a time.
I a trying to figure out how I can do this.
I was thinking is there a way to pass in the parent component to the function and then be able to access the className property of all its children??
Currently I have:
import React from 'react';
import ReactDOM from 'react-dom';
export default class TestContainer extends React.Component{
setActive(event){
event.preventDefault();
//getting id from component
let isActive = event.target.id;
if(event.currentTarget.className === "list-group-item text-center active"){
event.currentTarget.className = "list-group-item text-center";
} else if(event.currentTarget.className === "list-group-item text-center") {
event.currentTarget.className = "list-group-item text-center active";
}
}
render(){
return (
<div className="col-lg-6 col-md-6 col-sm-6 col-xs-6 bhoechie-tab-container scroll-y">
<div className="col-lg-2 col-md-2 col-sm-2 col-xs-2 bhoechie-tab-menu">
<div className="list-group">
<a href="#" onClick={this.setActive} id="eyes" className="list-group-item text-center active">
<h4 className="glyphicon glyphicon-eye-close"></h4><br/>1
</a>
<a href="#" onClick={this.setActive} id="hair" className="list-group-item text-center">
<h4 className="glyphicon glyphicon-tint"></h4><br/>2
</a>
<a href="#" onClick={this.setActive} id="mouth" className="list-group-item text-center">
<h4 className="glyphicon glyphicon-minus"></h4><br/>3
</a>
<a href="#" onClick={this.setActive} id="clothing" className="list-group-item text-center">
<h4 className="glyphicon glyphicon-user"></h4><br/>4
</a>
<a href="#" onClick={this.setActive} id="props" className="list-group-item text-center">
<h4 className="glyphicon glyphicon-gift"></h4><br/>5
</a>
</div>
</div>
)}
By trying to change the state of your elements outside of the render() method, you're fighting against the strengths of React's rendering engine. Use state, either internal to the component or provided via props/context (preferably props), to determine which tab should be rendered with active in its className.
When you respond to a click, change the state and let React re-render the component based on the new state.
For the limited example provided here, I'd recommend storing the ID of the active element internally in the component's state.
export default class TestContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
activeTab: this.props.activeTab || 'eyes'
};
}
setActive(event) {
this.setState({ activeTab: event.target.id });
}
render() {
const { activeTab } = this.state;
const tabClassName = "list-group-item text-center";
const eyesTabClassName = tabClassName + (activeTab === 'eyes' ? ' active' : '');
...
<a href="#" onClick={this.setActive} id="eyes" className={eyesTabClassName}>
...
}
}
This is a rough, unoptimized solution, but it should get the idea across. When you call this.setState, React responds by marking the component as needing to be re-rendered. The render() method will automatically be called and thus all of your JSX will be re-evaluated and re-rendered. React will then look at the difference between what it just produced and what is already in the virtual DOM and merge in your changes.
This means that whichever tab was previously rendered with "active" in its className will be re-rendered. If it's no longer active, your render code would not have concatenated the active class into that tab's className. Further, whichever class is active will now have its className appended with "active".
TL;DR
Don't manipulate the DOM in your event handlers. Manipulate state and let React work its magic by re-rendering with your new state.

toggle classes in ReactJS

I am trying to toggle the className to 'active' on clicking the 'Follow' button. I have tried following the tutorials and guides on the react website and other references but had no luck. Below is my code:
import React from 'react';
import styles from './Cover.css';
import withStyles from '../../decorators/withStyles';
import Link from '../../utils/Link';
import Avatar from './Avatar';
import { Button } from 'react-bootstrap';
#withStyles(styles)
class Cover extends React.Component {
render() {
return (
<div className="Cover">
<div className="Cover-container">
<div>
<Avatar
username="hilarl"
profession="Web Developer"
location="New York, New York"
status="I am here to protect my business, a bunch of kids are out to ruin me" />
<div className="Cover-submenu-container">
<div className="Cover-submenu-section">
.
</div>
<div className="Cover-submenu-section links">
<a href="#" className="Cover-submenu-link">
<i className="fa fa-twitter"></i>
</a>
<a href="#" className="Cover-submenu-link">
<i className="fa fa-facebook"></i>
</a>
</div>
// follow button
<div className="Cover-submenu-section connect-menu">
<Button className="follow-btn" href="#">Follow</Button>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default Cover;
Would be great if somebody could helpout with this. Thanks
you render the Button with the active class.
render () {
let isFollowing = this.state.isFollowing
...
<Button className={`follow-btn ${isFollowing? ' active':''}`} ...
all you need to do now is to update isFollowing on button click.

Categories

Resources