GlideJs adding buttons - javascript

I created a glider that works good, no problem with the functionality, what I'm trying to achieve is to add a button inside the slides. So far, the links and all the slide content works good but not the button click event. I tried adding the .disable() and the pause() methods but it doesn't work. And I can't find anything like this, nor anything in the documentation. If anyone would have an approach, it'll help me a lot.
Glide holder:
import React, { Component } from 'react';
import Glide, {Swipe, Controls} from '#glidejs/glide';
import myComponent from './myComponent';
class myHolder extends Component {
constructor(props) {
super(props);
}
}
componentDidMount() {
const glide = new Glide(`.myGliderComponent`, {
type: carouselType,
focusAt: 0,
perTouch: 1,
perView: 4,
touchRatio: 1,
startAt: 0,
rewind: false,
});
glide.mount({Controls});
const CAROUSEL_NUMBER = 3;
const carouselType = this.props.displayedProducts.length <= CAROUSEL_NUMBER ? 'slider' : 'carousel';
}
render() {
return (
<div>
<div data-glide-el="track" className="glide__track">
<ul className="glide__slides">
{
this.props.displayedProducts.map(({ name, image,} = product, index) => (
<li className="glide__slide slider__frame">
<MyComponent
name={name}
image={image}
/>
</li>
))
}
</ul>
</div>
</div>
);
}
}
export default myHolder;
myComponent:
import React from 'react';
const myComponent = (
{
name,
image,
}
) => {
const buttonClicked = () => {
console.log("button clicked")
}
return (
<div>
<p>{name}</p>
<img
alt=""
src={image}
/>
<button onClick={buttonClicked}>Testing btn</button>
</div>
);
}
export default myComponent;

For anyone trying the same, I just added position:static to the class, and the glide.mount({Anchor}); to the mount() method

Related

ScrollIntoView() can find the html element

I'm trying to create a scroll to element but I'm getting this error
"TypeError: Cannot read property 'scrollIntoView' of null".
By console logging mapRef I can see that I'm getting the correct div.
console.log
export class FinderComponent extends PureComponent {
constructor(props) {
super(props);
this.mapRef = React.createRef();
}
renderMap() {
return <div block="StoreFinder" ref={this.mapRef}></div>;
}
renderStoreCard(store) {
this.mapRef.current.scrollIntoView({ behavior: "smooth" });
//console.log(this.mapRef.current);
return (
<div
block="StoreFinder"
elem="Store"
key={store_name.replace(/\s/g, "")}
mods={{ isActive: store_name === selectedStoreName }}
>
{this.renderStoreCardContent(store)}
<button
block="Button"
mods={{ likeLink: true }}
onClick={() => changeStore(store)}
>
{__("Show on the map")}
</button>
</div>
);
}
}
I made this functional component that has a working example with ScrollIntoView(). If I understood you right, you want to add the scrollIntoView()-function to an element. This is how you do it with functional components:
import React, { useEffect, useRef } from 'react'
export const TestComponent = () => {
const inputEl = useRef(null) //"inputEl" is the element that you add the scroll function to
useEffect(() => {
inputEl.current.scrollIntoView() //use this if you want the scroll to happen when loading the page
}, [inputEl])
const onButtonClick = () => {
inputEl.current.scrollIntoView() //use this if you want the scroll to happen on click instead.
}
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
)
}

to display a different component with each click (using hooks)

I want to display a different component with each button click.
I'm sure the syntax is wrong, can anyone help me? The browser doesn't load
I would love an explanation of where I went wrong
One component (instead of HomePage) should display on the App component after clicking the button. Help me to understand the right method.
Thanks!
App.js
import React, {useState} from 'react';
import './App.css';
import Addroom from './components/Addroom.js'
import HomePage from './components/HomePage.js'
function App() {
const [flag, setFlage] = useState(false);
return (
<div className="App">
<h1>My Smart House</h1>
<button onClick={()=>{setFlage({flag:true})}}>Addroom</button>
<button onClick={()=>{setFlage({flag:false})}}>HomePage</button>
{setState({flag}) && (
<div><Addroom index={i}/></div>
)}
{!setState({flag}) && (
<div><HomePage index={i}/></div>
)}
</div>
)
}
export default App;
HomePage
import React from 'react'
export default function HomePage() {
return (
<div>
HomePage
</div>
)
}
Addroom
import React from 'react'
export default function Addroom() {
return (
<div>
Addroom
</div>
)
}
I didn't test it but as i can see it should be something like this:
<button onClick={()=>setFlage(true)}>Addroom</button>
<button onClick={()=>setFlage(false)}>HomePage</button>
{flag && (
<div><Addroom index={i}/></div>
)}
{!flag && (
<div><HomePage index={i}/></div>
)}
You need to call setFlage function with argument of Boolean saying true or false and it changes the flag variable that you want to read.
Try the following.
function App() {
const [flag, setFlage] = useState(false);
return (
<div className="App">
<h1>My Smart House</h1>
<button
onClick={() => {
setFlage(true);
}}
>
Addroom
</button>
<button
onClick={() => {
setFlage(false );
}}
>
HomePage
</button>
{flag ? <Addroom /> : <HomePage /> }
</div>
);
}
You are missing render methods and also you should use setState for reactive rendering.( when you use state variables and once value changed render method will rebuild output so this will load your conditinal component.
https://jsfiddle.net/khajaamin/f8hL3ugx/21/
--- HTML
class Home extends React.Component {
constructor(props) {
super(props);
}
render() {
return <div> In Home</div>;
}
}
class Contact extends React.Component {
constructor(props) {
super(props);
}
render() {
return <div> In Contact</div>;
}
}
class TodoApp extends React.Component {
constructor(props) {
super(props);
this.state = {
flag: false,
};
}
handleClick() {
this.setState((state) => ({
flag: !state.flag,
}));
console.log("hi", this.state.flag);
}
getSelectedComp() {
if (this.state.flag) {
return <Home></Home>;
}
return <Contact></Contact>;
}
render() {
console.log("refreshed");
return (
<div>
<h1>
Click On button to see Home component loading and reclick to load back
Contact component
</h1
<button onClick={() => this.handleClick()}>Switch Component</button>
{this.getSelectedComp()}
</div>
);
}
}
ReactDOM.render(<TodoApp />, document.querySelector("#app"));

How do you use multiple react components on the same element?

I would like to hover a div, get the image inside that div, show it and then make the image follow my cursor. The hover component is working but then I can't make the follow cursor component work. How would you go about doing this ?
Component number 1 :
import React from 'react';
class FollowMouse extends React.Component {
state = {
xPos: 0,
yPos: 0
};
onMouseMove(e) {
this.setState({
xPos: e.screenX,
yPos: e.screenY
});
}
render() {
return (
<div
onMouseMove={this.onMouseMove.bind(this)}
className="img-ctn"
>
{this.props.children(this.state.xPos, this.state.yPos)}
</div >
);
}
}
export default FollowMouse;
Component 2 :
import React from 'react';
class HoverProject extends React.Component {
state = {
isHovered: false,
};
onMouseEnter() {
this.setState({ isHovered: true });
}
onMouseLeave() {
this.setState({ isHovered: false });
}
render() {
return (
<div
onMouseEnter={this.onMouseEnter.bind(this)}
onMouseLeave={this.onMouseLeave.bind(this)}
className="project-item"
>
{this.props.children(this.state.isHovered)}
</div >
);
}
}
export default HoverProject;
and then the parent component.
import React from 'react';
// modules
import HoverProject from '../modules/HoverProject';
import FollowMouse from '../modules/FollowMouse';
import VLEC from '../images/vlec.png';
class ProjectList extends React.Component {
constructor(props) {
super(props);
this.sels = {
state: 'active'
};
};
render() {
return (
<div className="project-list module">
<div className="sectionTitle">Project I've worked on</div>
{this.props.data.map((res, i) => (
<HoverProject key={i}>
{
isHovered =>
<div className="inner-ctn">
{/* <FollowMouse /> */}
<img className={"project-image " + (isHovered ? this.sels.state : "")} src={VLEC} alt="VLEC" />
<div className="header">
<div className="number">0{res.id + 1}</div>
<div className="name">{res.nomProjet}</div>
</div>
<div className="item-ctn">
<div className="categ">{res.categProjet}</div>
<div className="roles">{res.roles}</div>
<div className="date">{res.date}</div>
</div>
</div>
}
</HoverProject>
))}
</div>
);
}
}
export default ProjectList;
I have no idea what to do with the other component, can you even render childs inside a parent like this ?
I would like pass the props from FollowMouse as style attributes of my img element.
I'm not 100% sure I follow your question, and I don't know what you're expecting this.props.children to do when invoked as a function, but if you want to add props to a child element you can do so via React.cloneElement:
const ParentComponent ({children}) => (
<div>
{React.cloneElement(
React.Children.only(children), // clone the only child...
{ style: { left: xPos, top: yPos} } // ...and add new props
)}
</div>
)
Given:
<ParentComponent>
<div>Wookies and Hats</div>
</ParentComponent>
The child component will get the additional props, the equivalent of:
<ParentComponent>
<div style={{left: xPos, top: yPos}}>Wookies and Hats</div>
</ParentComponent>

Close responsive navigation | React JS

I have a header component which manages the state for my navigation component.
The navigation successfully toggles if the user clicks on the hamburger icon however, if the user clicks or taps anywhere outside of the navigation I need the navigation to close.
How can I achieve this?
Here is my code:
export default class Header extends React.Component {
constructor() {
super();
this.state = {
mobileOpenNav: false
};
bindAll([
'openMobileNav',
'openContactModal'
],this);
}
openMobileNav() {
this.props.contactModalToggle(false);
this.setState({
mobileOpenNav: !this.state.mobileOpenNav
})
}
openContactModal() {
this.props.contactModalToggle();
this.setState({
mobileOpenNav: !this.state.mobileOpenNav
});
}
render() {
const {nav, contactModalToggle, location, logos} = this.props;
const {mobileOpenNav} = this.state;
return (
<div className="header-wrap">
<div className="header">
<Logo location={location} logoUrls={logos} />
<Navigation
location={location}
nav={nav}
contactModalToggle={this.openContactModal}
mobileOpen={mobileOpenNav}
mobileToggle={this.openMobileNav}
/>
<div className="hamburger" onClick={this.openMobileNav}><img src={HamburgerIcon} /></div>
</div>
</div>
)
}
}
The following solution should work for you.
componentDidMount() {
document.addEventListener('click', this.handleClickOutside.bind(this), true);
}
componentWillUnmount() {
document.removeEventListner('click', this.handleClickOutside.bind(this), true);
}
handleClickOutside(e) {
const domNode = ReactDOM.findDOMNode(this);
if(!domNode || !domNode.contains(event.target)) {
this.setState({
mobileOpenNav: false
});
}
}
use react-onclickoutside module https://github.com/Pomax/react-onclickoutside
import onClickOutside from "react-onclickoutside"
import Navigation from "pathToNvaigation"
const ContentWrapper = onClickOutside(Navigation)
and use
<ContentWrapper
location={location}
nav={nav}
contactModalToggle={this.openContactModal}
mobileOpen={mobileOpenNav}
mobileToggle={this.openMobileNav}
/>

Scrolling to a particular item

In my React component, I'm displaying a list of items -- each in its own DIV element with a unique id i.e. <div id="abc-123">.
I'm also using react-perfect-scrollbar to make the whole thing nicer looking.
I keep a variable in my reducer named activeElementId and when the value of activeElementId changes, I want to automatically scroll to that item on the screen.
Setting the activeElementId is the easy part but I'm not sure how to scroll to that element and would appreciate some pointers.
This is the parent component that contains the ListComponent.
class MyComponent extends Component {
constructor(props) {
super(props);
}
render() {
return(
<div>
{this.props.items.length > 0
?
<PerfectScrollBar>
<ListComponent items={this.props.items} />
</PerfectScrollBar>
: null}
</div>
);
}
}
My ListComponent is a presentational component:
const ListComponent = ({ items }) => {
return(
<ul className="pretty-list">
{items.map(item => <ItemComponents item={item} />)}
</ul>
);
}
export default ListComponent;
And the ItemComponent is a presentational component as well:
const ItemComponent = ({ Item }) => {
return(
<li>
<div id={item.id}>
{item.someProperty}
</div>
</li>
);
}
export default ItemComponent;
I really like the idea of keeping ListComponent and ItemComponent separate and as presentational components as that helps keep the code simpler and easier to manage. Not sure if that would make it difficult to implement the auto scroll logic though.
The library you use has a method called setScrollTop. You can use it with getBoundingClientRect. To use getBoundingClientRect you need to have the dom-element. You didn't give any code about how you are setting or getting the active element but I'll try to give you an example. Maybe it will help you to implement on your code.
Example
class MyComponent extends Component {
constructor(props) {
super(props);
}
_onListItemChange = (itemsPosition) => {
this.scrollbar.setScrollTop(itemsPosition.top);
}
render() {
return (
<div>
{this.props.items.length > 0 ?
<PerfectScrollBar ref={(scrollbar) => { this.scrollbar = scrollbar; }}>
<ListComponent
items={this.props.items}
onListItemChange={this._onListItemChange} />
</PerfectScrollBar>
: null}
</div>
);
}
const ListComponent = ({ items, onListItemChange }) => {
return(
<ul className="pretty-list">
{items.map(item => (
<ItemComponents
item={item}
onListItemClick={onListItemChange} />
))}
</ul>
);
}
export default ListComponent;
import { render, findDOMNode } from 'react-dom';
class ListItem extends React.Component {
_onClick = () => {
let domElement = findDOMNode(this.item);
this.props.onListItemClick(domElement.getBoundingClientRect());
}
render() {
const { item } = this.props;
return(
<li>
<div id={item.id} ref={(item) => { this.item = item; }} onClick={this._onClick}>
{item.someProperty}
</div>
</li>
);
}
}

Categories