I am using django and reactjs for developing my app. I am trying to create a login form with modal effect using reactjs and semantic-ui but I am getting an error Uncaught ReferenceError: AddLoginModalEvent is not defined.
My code
base.html
<div class="ui large top fixed hidden menu navbar">
<div class="ui container">
<a class="active item"></a>
<div class="ui buttons">
<a class="ui button tomato pair" onClick="AddLoginModalEvent()">Login</a>
<div class="or"></div>
<a class="ui positive button pair">Signup</a>
</div>
</div>
</div>
<div id="loginmodal"></div>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="{% static 'js/semantic.min.js' %}"></script>
<script type="text/javascript" src="{% static 'build/js/app.js' %}"></script>
<script type="text/javascript">
var data = {
isUserAuthenticated:{% if request.user.is_authenticated %}true{% else %}false{% endif %}
};
$(function() {
app.showLoginModal("loginmodal",data);
});
</script>
Index.js
(entry: "./src/index.js",) its a entry point in webpack
import LoginModal from 'homepage/LoginModal';
window.app = {
showLoginModal: function(id,data){
ReactDOM.render(
<LoginModal data={data} />, document.getElementById(id)
);
},
}
LoginModal.js
function AddLoginModalEvent(){
let event = document.createEvent('Event');
event.initEvent('addLoginModal', true, true);
document.dispatchEvent(event);
}
class LoginModal extends React.Component {
constructor(){
super();
this.state = {
showModal:'none'
}
}
componentDidMount() {
document.addEventListener('addLoginModal', (e) => {
this.showModal();
}, false);
$('.ui.modal').modal({detachable: false});
}
showModal(){
this.setState({ showModal:'inherit' });
$('.ui.modal.editform').modal('show');
}
closeModal(){
this.setState({ showModal:'none'});
}
render() {
const style = { display:this.state.showModal, top:'50px' };
const close = <div className="ui black deny button" onClick={this.closeModal}> Nope </div>;
return (
<div>
<AddLoginModal style={style} title="Login" close={close} />
</div>
);
}
}
class AddLoginModal extends Component{
render(){
return(
<div style={this.props.style}>
<div className="ui modal editform">
<div className="ui middle aligned center aligned grid">
<div className="column">
<h2 className="ui teal image header">
<div className="content">
Log-in to your account
</div>
</h2>
</div>
</div>
</div>
</div>
)
}
}
export default LoginModal;
Where am i doing wrong?
Related
I am a beginner in using the React JS framework. Based on the official React JS documentation, an example is given for changing the state of a component that has a connected hierarchy. But in my case this time I split the components for Header and Main separately.
index.js
ReactDOM.render(
<React.StrictMode>
<Header />
<Main />
</React.StrictMode>,
document.getElementById('root')
);
In the Header component I also have another sub component that functions to activate / deactivate the sidebar which is also a sub menu for the Main component.
Header.js
import { BtnSidebarOnClick } from './Sidebar';
const Header = () => {
return (
<header className="header">
<div className="header__logo">
<BtnSidebarOnClick />
<div className="header__logo_img">
<a className="link"
href="/">
<img src=""
alt="Schedule App" />
</a>
</div>
</div>
<nav className="header__nav">
...
</nav>
</header>
);
}
export default Header;
Main.js
import { Sidebar } from './Sidebar';
const Main = () => {
return (
<main className="main">
<Sidebar />
<div className="main__content">
...
</div>
</main>
);
}
export default Main;
Notice that the BtnSidebarOnClick and Sidebar components are not connected. In my case, this time I want to make the Sidebar component accept state to detect whether the button contained in the BtnSidebarOnClick component is clicked / not.
Sidebar.js
class BtnSidebarOnClick extends React.Component {
constructor(props) {
super(props);
this.state = { onClick: false };
}
handleClick() {
this.setState(state => ({ onClick: !state.onClick }));
}
render() {
return (
<div className="header__logo_btn">
<div className="button button--hover button--focus"
role="button"
tabIndex="0"
onClick={this.handleClick.bind(this)}>
<i className="material-icons">menu</i>
</div>
</div>
);
}
}
const Sidebar = () => {
return (
<div className="main__sidebar"> {/* set style if BtnSidebarOnClick clicked */}
<div className="main__sidebar_menu">
<div className="tag-link">
<a className="link link--hover link--focus link--active"
href="/">
<i className="material-icons">insert_drive_file</i>
<span className="link-title">Files</span>
</a>
</div>
</div>
</div>
);
}
export { Sidebar, BtnSidebarOnClick };
So how do you set these two components to receive the same state?
TLDR; You should pull out the button state into the parent and pass it into the children component.
By the way, it is a common way to have file App.js for your main Application file. In your case, it should be like this:
index.js
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
App.js
class App extends React.Component {
constructor(props) {
super(props);
this.state = { isClicked: false };
}
handleClick() {
this.setState(state => ({ isClicked: !state.isClicked }));
}
render() {
return (
<div>
<Header onClick={this.handleClick} /> // --> notice
<Main isClicked={this.state.isClicked} /> // --> notice
</div>
)
}
}
Header.js
import BtnSidebar from './BtnSidebar';
const Header = (props) => {
return (
<header className="header">
<div className="header__logo">
<BtnSidebar onClick={props.onClick} /> // --> notice
<div className="header__logo_img">
<a className="link"
href="/">
<img src=""
alt="Schedule App" />
</a>
</div>
</div>
<nav className="header__nav">
...
</nav>
</header>
);
}
Main.js
import Sidebar from './Sidebar';
const Main = (props) => {
return (
<main className="main">
<Sidebar isClicked={props.isClicked} /> // --> notice
<div className="main__content">
...
</div>
</main>
);
}
BtnSidebar.js
const BtnSidebar = (props) => {
return (
<div className="header__logo_btn">
<div className="button button--hover button--focus"
role="button"
tabIndex="0"
onClick={props.onClick} // --> notice
>
<i className="material-icons">menu</i>
</div>
</div>
);
}
Sidebar.js
const Sidebar = (props) => {
return (
<div
className={
props.isClicked ? 'main__sidebar-clicked' : 'main__sidebar' // --> notice
}
>
<div className="main__sidebar_menu">
<div className="tag-link">
<a className="link link--hover link--focus link--active"
href="/">
<i className="material-icons">insert_drive_file</i>
<span className="link-title">Files</span>
</a>
</div>
</div>
</div>
);
}
I would like to ask question about some kind of grid gallery for a portfolio section. Each grid has a overlay which could be triggered by mouseover and the grids are generated by a map function and data in the grids are linked with a json file. The problem is that when I put a draft modal that I supposed it is for the grid , an error message showed "TypeError: Cannot read property 'toggleModal' of undefined" for this tag . Thanks for any solution.
import React, { Component } from 'react';
import Modal from './Modal';
class Portfolio extends Component {
constructor(props) {
super(props);
this.state = { isOpen: false };
}
toggleModal = () => {
this.setState({
isOpen: !this.state.isOpen
});
}
render() {
if(this.props.data){
var projects = this.props.data.projects.map(function(projects){
var projectImage = 'images/portfolio/'+projects.image;
return <div key={projects.title} className="columns portfolio-item">
<div className="item-wrap">
<a href={projects.url} className="open-popup" title={projects.title}>
<img alt={projects.title} src={projectImage} />
<div className="overlay">
<div className="portfolio-item-meta">
<h5>{projects.title}</h5>
<p>{projects.category}</p>
</div>
</div>
<div className="link-icon"><i className="fa fa-link"></i></div>
</a>
</div>
<button onClick={this.toggleModal}>
Open the modal
</button>
<Modal show={this.state.isOpen} onClose={this.toggleModal} >
Here's some content for the modal
</Modal>
</div>
})
}
return (
<section id="portfolio">
<div className="row">
<div className="twelve columns collapsed">
<h1>Check Out Some of My Works.</h1>
<div id="portfolio-wrapper" className="bgrid-quarters s-bgrid-thirds cf">
{projects}
</div>
</div>
</div>
</section>
);
}
}
export default Portfolio;
and the Modal.js is below:
import React from 'react';
import PropTypes from 'prop-types';
class Modal extends React.Component {
render() {
// Render nothing if the "show" prop is false
if(!this.props.show) {
return null;
}
// The gray background
const backdropStyle = {
position: 'fixed',
top: 0,
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'rgba(0,0,0,0.3)',
padding: 50
};
// The modal "window"
const modalStyle = {
backgroundColor: '#fff',
borderRadius: 5,
maxWidth: 500,
minHeight: 300,
margin: '0 auto',
padding: 30
};
return (
<div className="backdrop" style={backdropStyle}>
<div className="modal" style={modalStyle}>
{this.props.children}
<div className="footer">
<button onClick={this.props.onClose}>
Close
</button>
</div>
</div>
</div>
);
}
}
Modal.propTypes = {
onClose: PropTypes.func.isRequired,
show: PropTypes.bool,
children: PropTypes.node
};
export default Modal;
The error is caused from this line:
var projects = this.props.data.projects.map(function(projects){
Since you used this.toggleModal inside this function, the this context is linking to this function, not the React component.
The solution is to use an arrow function like this:
var projects = this.props.data.projects.map((projects) => {
On a side note, it's not a good idea to define a variable inside a block and use it outside of it.
This is my revised version, thanks. What should I do if I want to add next and previous function in modal in order to show next or previous project information? Thanks. I am sorry that I am new with React and Javascript.
import React, { Component } from 'react';
import Modal from './Modal';
class Portfolio extends Component {
constructor(props) {
super(props);
this.state = {
isOpen: false,
activeProjects:"",
activeProjectImage:""
};
}
toggleModal = (projects,projectImage) => {
this.setState({activeProjects:projects, activeProjectImage:projectImage},() =>
this.setState({
isOpen: !this.state.isOpen
}));
}
render() {
if(this.props.data){
var projects = this.props.data.projects.map((projects) => {
var projectImage = 'images/portfolio/'+projects.image;
return <div key={projects.title} className="columns portfolio-item">
<div className="item-wrap">
<a onClick={() => this.toggleModal(projects,projectImage)} className="open-popup" title={projects.title}>
<img alt={projects.title} src={projectImage} />
<div className="overlay">
<div className="portfolio-item-meta">
<h5>{projects.title}</h5>
<p>{projects.category}</p>
</div>
</div>
<div className="link-icon"><i className="fa fa-link"></i></div>
</a>
</div>
</div>
})
}
return (
<section id="portfolio">
<div className="row">
<div className="twelve columns collapsed">
<h1>Check Out Some of My Works.</h1>
<div id="portfolio-wrapper" className="bgrid-quarters s-bgrid-thirds cf">
{projects}
<Modal show={this.state.isOpen} onClose={this.toggleModal} >
<img alt={this.state.activeProjects.title} src={this.state.activeProjectImage} />
</Modal>
</div>
</div>
</div>
</section>
);
}
}
export default Portfolio;
Hi i have problem using reactjs to reload the second component in parent component.
I have some 3 file 1 parent component 2 child component to make simple chat website.
The problem is my component Chatroom was not reload/change the data when i click the Chatlist in the second time.
This is my parent.js
import React, { useContext } from 'react'
import $ from 'jquery'
import Wrapper from '../components/wrapper'
import ChatList from './chat-list'
import ChatRoom from './chat-room'
export default class extends React.Component {
constructor(props) {
super(props)
this.state = {
login: 0,
user: null,
tokenChat: '',
roomChat: '',
isToken: false
}
this.clickChat = this.clickChat.bind(this)
}
componentDidMount() {
$('body').addClass('menu-position-side menu-side-left')
}
componentWillUnmount() {
$('body').removeClass('menu-position-side menu-side-left')
}
clickChat(token, room) {
let self = this
self.setState({
tokenChat: token,
roomChat: room,
isToken: true
})
}
render() {
return (
<Wrapper {...this.props} title="Dashboard" selected="dashboard" padding={false}>
{this.state.login == 1 &&
<div className="content-i">
<div className="content-box">
<div className="full-chat-w">
<div className="full-chat-i">
<div className="full-chat-left">
<div className="os-tabs-w">
<ul className="nav nav-tabs upper centered">
...
</ul>
</div>
<ChatList clickChat={this.clickChat} />
</div>
<div className="full-chat-middle">
{
this.state.isToken == false ?
null
:
<ChatRoom token={this.state.tokenChat} room={this.state.roomChat} />
}
</div>
<div className="full-chat-right">
<div className="user-intro">
<div className="avatar"><img alt="" src="/static/doctor-theme/img/avatar1.jpg" /></div>
<div className="user-intro-info">
<h5 className="user-name">John Mayers</h5>
<div className="user-sub">San Francisco, CA</div>
<div className="user-social"><i className="os-icon os-icon-twitter"></i><i className="os-icon os-icon-facebook"></i></div>
</div>
</div>
<div className="chat-info-section">
<div className="ci-header"><i className="os-icon os-icon-documents-03"></i><span>Shared Files</span></div>
<div className="ci-content">
<div className="ci-file-list">
<ul>
<li>Annual Revenue.pdf</li>
<li>Expenses.xls</li>
<li>Business Plan.doc</li>
</ul>
</div>
</div>
</div>
<div className="chat-info-section">
<div className="ci-header"><i className="os-icon os-icon-documents-07"></i><span>Shared Photos</span></div>
<div className="ci-content">
<div className="ci-photos-list">
<img alt="" src="/static/doctor-theme/img/portfolio9.jpg" />
<img alt="" src="/static/doctor-theme/img/portfolio2.jpg" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
}
</Wrapper>
)
}
}
Please Help Thank you.
I wanna dynamically render the images and then show the modal when the image is clicked and it should close when the modal background is clicked. Please help I'm new to React.
What should I do to make it work like is anything wrong in this. I'm stuck in this.
Whenever the images load from the api and I I click on them nothing happens.
import React from "react";
import axios from "axios";
import { Modal } from "./Modal";
class MediaGallery extends React.Component {
constructor() {
super();
this.state = {
data: "",
show: false,
loading: true
};
}
showModal = () => {
this.setState({ show: true });
};
hideModal = () => {
this.setState({ show: false });
};
componentDidMount() {
const url =
"https://amyapi.com";
axios
.get(url)
.then(response => {
this.setState({
data: response.data,
loading: false
});
})
.catch(error => {
console.log(error);
});
}
render() {
let content;
if (this.state.loading) {
content = (
<div>
<div className="modal is-active">
<div className="modal-background has-background-primary" />
<div className="modal-content has-text-centered">
<p classname="image is-48x48">
<img
src="https://raw.githubusercontent.com/sharadcodes/css_snippets/master/Infinity-1.4s-200px.gif?token=AIXQ22JWJBKUHGP45ANQZ4K5SW46A"
alt=""
/>
</p>
</div>
</div>
</div>
);
} else {
content = this.state.data.map((response, index) => {
return (
<div
key={index}
className="column is-one-quarter-desktop is-half-tablet"
style={{ cursor: "zoom-in" }}
onClick={this.showModal}
>
<Modal show={this.state.show} handleClose={this.hideModal}>
<img src={response.acf.image} alt={response.acf.title} />
</Modal>
<div className="card cardimages">
<div className="card-image" id="small-image-zoomable">
<figure className="image is-3by2">
<img src={response.acf.image} alt={response.acf.title} />
</figure>
<div
className="card-content is-overlay is-clipped"
data={response.acf.title}
>
<span className="tag is-primary">{response.acf.title}</span>
</div>
</div>
</div>
</div>
);
});
}
return (
<div>
<section className="hero is-medium is-bold has-background-black has-text-centered">
<div className="hero-body">
<div className="container">
<h1 className="title is-1" style={{ color: "#FFD581" }}>
Captured Moments
</h1>
</div>
</div>
</section>
<div className="section" style={{ marginTop: "-1.2rem" }}>
<div className="container">
<div className="columns is-multiline" id="media-gallery">
{content}
</div>
</div>
</div>
</div>
);
}
}
export default MediaGallery;
And modal code is
import React from "react";
export const Modal = ({ handleClose, show, children }) => {
const showHideClassName = show ? "is-active" : "";
return (
<div>
<div className={{ showHideClassName } + " modal"} id="modal">
<div className="modal-background" onClick={handleClose} />
<div className="modal-content" style={{ width: "70vw!important" }}>
<p className="image ">{children}</p>
</div>
<button
className="modal-close is-large"
aria-label="close"
onClick={handleClose}
/>
</div>
</div>
);
};
I have a userlist which contains name and email id of each user. I want to display it using the .map() method on userlist state variable. I have created displayusers() function to display the users but I am getting failed to compile error.
Code:
import React, { Component } from 'react';
class App extends Component {
constructor(props){
super(props);
this.state = {
userlist:[
{'name':'Rohan Singh',
'email':'rohan#gmail.com'
},
{'name':'Mohan Singh',
'email':'mohan#gmail.com'
},
{'name':'Rakesh Roy',
'email':'rakesh#gmail.com'
},
{'name':'Sunil Shah',
'email':'sunil#gmail.com'
}]
}
}
displayusers(){
return this.state.userlist.map( user => {
return(
<div className="item-card">
<div className="sub">
<div className="type">Username: {user.name}</div>
<div className="members">Email: {user.email}</div>
</div>
<div className="del-wrap">
<img src={require("../../images/cancel.svg")}/>
</div>
</div>
);
})
}
render() {
return(
<div className="users-wrap">
<h1>Users</h1>
<div className="task-content">
<div className="user-wrap">
<div className="users">
{this.displayusers()}
</div>
</div>
</div>
</div>
);
}
}
export default App;
I think you forgot about adding a key attribute to the element and there's missing </div> closing tag in your map function.
See the corrected code:
displayusers(){
return this.state.userlist.map( user => {
return(
<div className="item-card" key={user.name}>
<div className="sub">
<div className="type">Username: {user.name}</div>
<div className="members">Email: {user.email}</div>
</div>
<div className="del-wrap">
<img src={require("../../images/cancel.svg")}/>
</div>
</div>
);
});
}
You need to bind your displayusers function to this. You can do that in the constructor.
Update your code as following:
import React, { Component } from 'react';
class App extends Component {
constructor(props){
super(props);
this.state = {
userlist:[
{'name':'Rohan Singh',
'email':'rohan#gmail.com'
},
{'name':'Mohan Singh',
'email':'mohan#gmail.com'
},
{'name':'Rakesh Roy',
'email':'rakesh#gmail.com'
},
{'name':'Sunil Shah',
'email':'sunil#gmail.com'
}]
};
this.displayusers = this.displayusers.bind(this); // you need to add this line
}
displayusers(){
return this.state.userlist.map((user, index) => {
return(
<div className="item-card" key={index}>
<div className="sub">
<div className="type">Username: {user.name}</div>
<div className="members">Email: {user.email}</div>
</div>
<div className="del-wrap">
<img src={require("../../images/cancel.svg")}/>
</div>
);
})
}
render() {
return(
<div className="users-wrap">
<h1>Users</h1>
<div className="task-content">
<div className="user-wrap">
<div className="users">
{this.displayusers()}
</div>
</div>
</div>
</div>
);
}
}
export default App;