I am trying to make a sample React Modal of Menu in which it must display Menu. So, I already developed its Backend using NodeJS + Express and it works properly. But, after I integrate it to Frontend Page, it does not show any menu data.
import React, {Component} from 'react';
import {Tab, Tabs, TabList, TabPanel} from 'react-tabs';
import 'react-tabs/style/react-tabs.css';
import '../Styles/RestDetails.css';
import {Button} from 'react-bootstrap';
import Modal from 'react-modal';
import axios from 'axios';
import QueryString from 'query-string';
class RestDetails extends React.Component
{
constructor()
{
super();
this.state = {
menus: [],
isModalOpen: false
}
}
componentDidMount()
{
const Qparams = QueryString.parse(this.props.location.search);
const restID = Qparams.id;
axios({
method: 'GET',
url: `http://localhost:4005/api/restaurantMenu/${restID}`,
headers: {'Content-Type' : 'application/json'}
}).then(result => {
this.setState({
menus: result.data.menus
})
}).catch(error => {
console.log(error);
});
}
handleOrder = (event) => {
const {menus} = this.state;
this.setState({
isModalOpen: true
});
}
cancelHandler = (event) => {
this.setState({
isModalOpen: false
});
}
render()
{
const {isModalOpen, menus} = this.state;
return(
<div className="container-fluid">
<div className="row">
<Modal isOpen={isModalOpen} className="modal-dialog modal-lg" id="modal_header">
<div className="modal-content">
<div className="modal-header">
<h3 className="modal-title">MENU</h3>
<button type="button" className="close" onClick={this.cancelHandler}>×</button>
</div>
<div className="modal-body">
<table className="table table-bordered">
<tbody>
<tr>
{
menus.map((item, index) => {
return (
<div className="row">
<td>
<div className="col-6">{item.item}</div>
<div className="col-2">{item.cost}</div>
</td>
<td>
<div className="col-4"><Button>ADD</Button></div>
</td>
<hr/>
</div>
)
})
}
</tr>
</tbody>
</table>
</div>
<div className="modal-footer">
<div className="float-left">Subtotal: 220</div>
<button className="btn btn-primary" onClick={this.Handler}>Order</button>
<button className="btn btn-danger" onClick={this.cancelHandler}>Cancel</button>
</div>
</div>
</Modal>
</div>
)
}
}
export default RestDetails;
Here, the Modal is linked with Button using State Handler and componentDidMount() which is linked to Backend using Axios and Query-String. I checked the Backend using Postman and it able to fetch and display data by entering the restaurant ID. But it can't able to display at the Frontend Modal. Please share some ideas. Thanks in advance.
Related
I have a dashboard with a table component inside it. I am making a graphql call in the dashboard and need to pass the data recieved into the table like this . However I can't get the data to show up inside the table component.
Here is my approach. Please let me know what I'm missing
Dashboard.js
import React from "react";
import "bootstrap/js/src/collapse.js";
import DashboardTable from "../DashboardTable";
import { API } from "#aws-amplify/api";
import config from "../../aws-exports";
import * as queries from "../../graphql/queries";
export default function Dashboard() {
var opportunityTable;
API.configure(config);
async function asyncCall() {
const opportunityTable = await API.graphql({
query: queries.listMockOppsTables,
});
// console.log(opportunityTable.data.listMockOppsTables); // result: { "data": { "listTodos": { "items": [/* ..... */] } } }
}
asyncCall();
return (
<div>
<div className="container py-5">
<DashboardTable
data={opportunityTable.data.listMockOppsTables}
></DashboardTable>
</div>
</div>
);
}
Table (receiving prop data)
import React from "react";
import "bootstrap/js/src/collapse.js";
require("../opportunityData.json");
export class Opportunity extends React.Component {
constructor(props) {
super(props);
this.state = {
opportunityData: this.props.items,
};
}
render() {
console.log(this.opportunityData);// returns nothing
return (
<div>
<section class="py-5 mt-5">
<div class="container py-5">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Shadow ID</th>
<th>Role Title</th>
<th>Interview Type</th>
<th>Level</th>
<th>Date and Time</th>
<th># Requests</th>
<th>Make Request</th>
</tr>
</thead>
{this.opportunityData.map((opportunity) => (
<tbody>
<tr>
<td>{opportunity.shadow_id}</td>
<td>{opportunity.job_title}</td>
<td>{opportunity.shadow_type}</td>
<td>4</td>
<td>
{opportunity.shadow_datetime}
<br />
{opportunity.shadow_datetime}
</td>
<td>2</td>
<td>
<div class="btn-group" role="group">
<button
class="btn btn-primary"
type="button"
style={{
backgroundColor: "#ff9900",
border: 0,
}}
>
Shadow
</button>
<button
class="btn btn-primary"
type="button"
style={{
backgroundColor: "#ffac2f",
border: 0,
}}
>
Reverse Shadow
</button>
</div>
</td>
</tr>
</tbody>
))}
</table>
</div>
</div>
</section>
</div>
);
}
}
export default Opportunity;
You're problem is either with your method of passing state or with you querying. One issue in your code is by practice in React, you want state to be managed as a stateful value with the useState()hook. You will have to verify your data is loaded before passing it into the hook. This would look like:
const [opportunityTable, changeOpportunityTable] = useState(asyncCall());
Also you should've posted your DashBoardTable component instead of your Oppurtunity component which you don't seem to import in DashBoard to begin with. Here's a little skeleton
const DashBoardTable = ({data}) => {
//whatever code you may need
return (
//other formatting
data.map((key) => {
//access with data.<VARIABLE>
}
);
}
export default DashBoardTable;
So, this code is supposed to show JQuery table, and in the third column, every row is clickable and when clicked it shows a Modal.
When i start the code, the table shows, and when i clicked the third row, the alert test works, but the modal didnt show, and in the console it printed an error log:
UnCaught TypeError: topics.jsx
$(...).modal is not a function
So clearly the show modal function in the .click(function()) does not work, some similar questions from StackOverflow is saying that bootstrap.min.js and jquery.min.js is not referenced, but i'm not sure if that is the case because im using those libraries in this page no problem.
How do i fix this?
topics.jsx:
import React from 'react';
import ReactDOM from 'react-dom';
import ReactDOMServer from 'react-dom/server';
import PropTypes from 'prop-types';
import Navbar, { MENU as MAIN_MENU } from '../../components/Navbar';
import TopicFilter from '../../components/TopicFilter';
import PeriodTag from '../../components/PeriodTag';
import LecturerInfo from '../../components/LecturerInfo';
import Layout from '../../components/layouts';
import { Nav, NavItem, NavLink, Collapse, Modal, ModalBody, ModalHeader, Button, Form, FormGroup, FormInput, Alert } from "shards-react";
var $ = require('jquery');
var dt = require('datatables.net')();
class TopicTable extends React.Component {
constructor(props) {
super(props);
$(document).ready(() => {
$('#topic-table').DataTable({
data: this.props.topics || [],
columns: [
{ data: 'id', visible: false }, //id
{ data: 'name' }, //name
{ data: 'quota' }, //quota
{ data: 'deskripsi'}, //DESKRIPSI
{ data: 'kk', visible: false }, //kk
{ data: 'peminatan', render: 'abbrev' }, //peminatan
{ data: 'period', render: 'semester' }, //period
{ //lecturer
data: 'lecturer',
/*render: function(data, type, row, meta) {
if (type=='display') {
const lecturerInfo = (
<LecturerInfo
nik={data.nik}
name={data.name}
lecturerCode={data.lecturerCode}
/>
);
return ReactDOMServer.renderToString(lecturerInfo)
}
}*/
render: 'name'
},
{ data: 'isDeleted', visible: false } //isDeleted
]
})
$('#topic-table').find('td:nth-child(3)').click(function() {
alert($(this).html());
$('#myModal').modal('show'); //FUNCTION TO SHOW MODAL
});
})
}
componentDidUpdate() {
$(function () {
$('[data-toggle="popover"]').popover()
})
}
render() {
return (
<div>
//MODAL
<div class="modal" id="myModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Modal Heading</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
Modal body..
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
//TABLE
<table id="topic-table">
<thead>
<tr>
<th bgcolor="#E8E8E8">Id</th>
<th bgcolor="#E8E8E8">Topik</th>
<th bgcolor="#E8E8E8">Quota</th>
<th bgcolor="#E8E8E8">Deskripsi</th>
<th bgcolor="#E8E8E8">KK</th>
<th bgcolor="#E8E8E8">Peminatan</th>
<th bgcolor="#E8E8E8">Semester</th>
<th bgcolor="#E8E8E8">Dosen</th>
<th bgcolor="#E8E8E8">sudah dihapus</th>
</tr>
</thead>
</table>
</div>
)
}
}
TopicTable.propTypes = {
topics: PropTypes.arrayOf(PropTypes.object)
}
function Page() {
const { currentPeriod, topics, peminatanList } = window.SAILS_LOCALS;
return (
<div className="page main-content-container px-4 pb-4 container-fluid">
{/* <Navbar activeMenu={MAIN_MENU.TOPICS} /> */}
<div className="container">
<h2 class="display-4">Daftar Topik <PeriodTag period={currentPeriod} /></h2>
<div>
<TopicFilter peminatanList={peminatanList} />
<TopicTable topics={topics} />
</div>
</div>
</div>
)
}
ReactDOM.render(<Layout><Page /></Layout>, document.getElementById('root'));
jQuery doesn't have a modal method.
There are various plugins which add such a method, including bootstrap.
To use a plugin, you need to register it with jQuery.
In traditional web programming, this is done by:
Adding a <script> element which loads jQuery and creates jQuery and $ as globals.
Adding a <script> element which loads the plugin, which accesses one of those global variables and modifies the object assigned to it.
In your code, you are assigning a value to $ with require. It is locally scoped to the JS module. If you had loaded the Bootstrap JS which would have added the plugin with a <script> in the page then it would have either thrown an error, or associated the plugin with a different copy of the jQuery object.
Since you are working with React, use React Bootstrap which provides things like the Bootstrap Modal as React components.
when I make a call to the unsplash api in the componentDidMount, the this.state.photos data is still undefined after the api call, but when I console.log out the response to the console, the data is showing. You can see thay I have console.log the informations. (response.data and this.state.photos). The this.state.photos is the one being undefined and not showing the data. I am using ReactJS. Anyone know why? Please see code below. Thanks!
import React, { useState, useEffect } from "react";
import Footer from "../components/Footer";
import axios from "axios";
import NavBar from "../components/NavBar";
import AOS from 'aos';
class CountryPage extends React.Component{
state = {
country: null,
photos: []
}
componentDidMount() {
axios.get(`https://restcountries.eu/rest/v2/name/${this.props.match.params.name}`)
.then(response=> {
this.setState({
country: response.data[0]
})
console.log(this.state.country)
})
axios.get(`https://api.unsplash.com/search/photos?client_id=${Access_Key}&query=bike`)
.then(response=> {
this.setState({
photos: response.data[0]
})
console.log(response.data)
console.log(this.state.photos)
})
AOS.init({
duration: 1000
});
}
render() {
if(!this.state.country){
return <p>Loading</p>
}
return(
<div className="countryPageBack">
<NavBar/>
<div className="container">
<div className="countryAndFlag animate__bounceIn">
<h1 className="countryPageTitle">{`${this.props.match.params.name} - (${this.state.country.nativeName})`}</h1>
<img className="countryPageFlag" src={this.state.country.flag}/>
</div>
<div data-aos="fade-left" className="countryBasics">
<h3 className="sectionTitle">Basic Info</h3>
<div className="basicDesc">{`Located in ${this.state.country.region}, ${this.state.country.name} has a population of ${this.state.country.population} people`}</div>
<div className="propertyName">Currency: <span className="propertyValue">{this.state.country.currencies[0].name} - {`${this.state.country.currencies[0].symbol}`}</span></div>
<div className="propertyName">Langauges Spoken: <span className="propertyValue">{this.state.country.languages[0].name}</span></div>
<div className="propertyName">Capitols: <span className="propertyValue">{this.state.country.capital}</span></div>
</div>
<div data-aos="fade-right" className="countryRegion">
<h3 className="sectionTitle">Regional Info</h3>
<div className="propertyName">Region: <span className="propertyValue">{this.state.country.region}</span></div>
<div className="propertyName">Subregion: <span className="propertyValue">{this.state.country.subregion}</span></div>
<div className="propertyName">Timezones: <span className="propertyValue">{this.state.country.timezones}</span></div>
<div className="propertyName">Area: <span className="propertyValue">{this.state.country.area}</span></div>
</div>
<div data-aos="fade-left" className="countryOthers">
<h3 className="sectionTitle">Other Info</h3>
<div className="propertyName">Calling Code: <span className="propertyValue">{this.state.country.callingCodes}</span></div>
<div className="propertyName">Country Code: <span className="propertyValue">{this.state.country.alpha3Code}</span></div>
<div className="propertyName">Main Domain: <span className="propertyValue">{this.state.country.topLevelDomain}</span></div>
</div>
</div>
<Footer/>
</div>
)
}
}
export default CountryPage;
Looks like you are setting the wrong key to the state.
I tried a similar call to Unsplash API (ref) for fetching photos. I believe you should change your set code to
this.setState({
photos: response.data.results[0]
})
in case you want the first photo to be added to photos or response.data.results if you want the entire list.
I am learning React. I have tried to keep components in separate files. So, I have:
SaveDocument (class)
PersonList (const)
Person (const)
PersonList represents a dropdown of persons. I am trying to figure out how to get the value of the select dropdown in the SaveDocument class (i.e. when they click 'Save Changes').
How can i get the value of the select dropdown when the user clicks click Save?
Code below:
PersonList.js
import React from "react";
import Person from "./../model/Person";
const PersonList = props => {
return (
<div key="PersonList">
<select className="col-6">
{props.persons.map(person => <Person key={person.id} {...person} />)}
</select>
</div>
);
};
export default PersonList;
Person.js
import React from "react";
import moment from "moment";
import "react-datepicker/dist/react-datepicker.css";
const Person = person => {
console.log(JSON.stringify(person));
return (
<option id="{person.id}">{person.firstName + " " + person.lastName}</option>
);
};
Document.defaultProps = {
firstName: "",
lastName: ""
};
export default Person;
SaveDocument.js
import React, { Component } from "react";
import postDocument from "./../rest/PostDocument";
import fetchPersons from "./../rest/FetchPersons";
import PersonList from "./../components/PersonList";
import ShowDatePicker from "./../components/ShowDatePicker";
class SaveDocument extends Component {
state = {
persons: [],
personFromSelect: ''
};
cachePersons = personInfo => {
console.log(">> persons" + personInfo);
this.setState(prevState => ({
persons: personInfo
}));
};
resetFields () {
console.log("reset");
console.log(this.keys.PersonList.value);
}
componentWillMount() {
console.log("mounted");
fetchPersons.callApi(this.cachePersons);
}
render() {
return (
<div
className="modal fade"
id="basicExampleModal"
tabIndex="-1"
role="dialog"
aria-labelledby="exampleModalLabel"
aria-hidden="true"
>
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title" id="exampleModalLabel">
Save document
</h5>
<button
type="button"
className="close"
data-dismiss="modal"
aria-label="Close"
>
<span aria-hidden="true">×</span>
</button>
</div>
<div className="modal-body">
<div className="row">
<div className="col-4 text-left">Document Date:</div>
<div className="col-6">
<ShowDatePicker />
</div>
</div>
<br />
<div className="row">
<div className="col-4 text-left">Person From:</div>
<PersonList persons={this.state.persons} />
</div>
<br />
<div className="row">
<div className="col-4 text-left">Comments:</div>
<div className="col-md-6">
<div className="form-group">
<input
type="text"
className="form-control"
id="commentsBox"
placeholder="Comments"
onKeyPress={event => {
if (event.key === "Enter") {
}
}}
/>
</div>
</div>
</div>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-secondary"
data-dismiss="modal"
onClick={() => this.resetFields()}
>
Close
</button>
<button
type="button"
className="btn btn-primary"
onClick={() => postDocument.callApi(this.props)}
>
Save changes
</button>
</div>
</div>
</div>
</div>
);
}
}
export default SaveDocument;
In general uncontrolled components (where the input state is handled directly by the DOM element) are generally not advisable and make it harder to manage and reason about your app state. I'd recommend you change to a controlled component, where the state of your input is managed by React and the DOM simply renders that state.
PersonList.js:
Note that the <select> element receives its selected value from props, as well as a callback handler for when the user makes a change.
const PersonList = props => {
return (
<div key="PersonList">
<select className="col-6" value={this.props.value} onChange={this.props.onChangeCallback} >
{props.persons.map(person => <Person key={person.id} {...person} />)}
</select>
</div>
);
};
Person.js:
Note that it now has a value prop so that onchange events know what the new value will be, and <select> knows which option to display based on value.
const Person = person => {
console.log(JSON.stringify(person));
return (
<option value={person.id} id="{person.id}">{person.firstName + " " + person.lastName}</option>
);
};
SaveDocument.js:
Note that you're now keeping the dropdown select state in React state and passing it down to the child component PersonList, along with the callback handler for updating state.
...
onChangeCallback = (e) => {
this.setState({personValue: e.target.value});
}
cachePersons = personInfo => {
console.log(">> persons" + personInfo);
this.setState(prevState => ({
persons: personInfo,
personValue: personInfo[0].id
}));
};
render() {
...
<PersonList
persons={this.state.persons}
value={this.state.personValue}
onChangeCallback={this.onChangeCallback}
/>
...
}
Now you are actually keeping the select state of your dropdown menu in your parent component, SaveDocument, and passing it down into the list. The list simply renders the dropdown menu with the appropriately selected value (from state) and provides a callback for when it changes. Now the state of your dropdown lives inside React state and is easily accessible from inside SaveDocument when the user clicks the "save" button, instead of ambiguously living in the DOM element.
Add a prop to PersonList:
<PersonList onChangePerson={this.props.onChangePerson} />
Add an event handler for onChangePerson to SaveDocument.js and don’t forget to bind this in your constructor.
onChangePerson(event) {
var value = event.target.value
}
this.onChangePerson = this.onChangePerson.bind(this);
On the select add the onChange event
<select onChange={this.props.onChangePerson}></select>
You would then setState in the onChangePerson event to save your currently selected person and then when the user clicked Save, you would reference this.state.selectedPerson for example.
I am new to react js,I am little confused that how to stop triggering simple button from triggering when user clicks Enter Button ...
Sorry my code will be Awkward ...... If it is Uncomfortable to Read Feel free to comment it out
import React from 'react';
import {connect} from 'react-redux';
import {Link} from 'react-router';
import * as headerAction from '../../Actions/headerActions';
import * as notificationActions from '../../Actions/notificationActions';
import * as tagProfileActions from '../../Actions/tagProfileActions';
class TagProfile extends React.Component{
static contextTypes = {
router:React.PropTypes.object
};
constructor(props){
super(props)
this.state = {
data:[],
tagName:"",
In:null,
tagId:"",
tagFollowers:0,
isFollowStatus:""
}
this.handleFollow =this.handleFollow.bind(this)
}
handleFollow(e){
//How to Prevent this
console.log(e.keyCode)//Udefined
e.preventDefault();
console.log('Clicked')
}
render(){
console.log(this.state)
return (
<div className="ContainerForTagProfile">
<div className="TagProfileTopSecTion">
<h1>Topic: {this.state.tagName} </h1>
</div>
<div className="StatusBarRealTimeViewsAndFollowButtn">
<div className="ViewCcountBar">
<p>30,18,5222 👁 </p>
</div>
<div className="FollowButtonForTagPRofile">
<button type="button" onClick={(e)=>this.handleFollow(e)}>{this.state.tagFollowers} | {this.state.isFollowStatus}</button>
</div>
</div>
<div className="GallerySectionForTagforfile">
{this.state.data.map(data => {
return (
<Link key={data.id} href="#" target="_blank" to={'/'+data.postId}><div className="SingleImagePost">
<img src={data.thumNailUrl} />
<div className="LiveViewCountBar">
<p>{data.views} 👁 - {data.whoLikedIt.length} ❤</p>
</div>
<div className="LikesBar">
<div className="MakeItCenter">
<div className="ProfileTinyImage">
<img src={data.postOwnerPic} />
</div>
<div className="ProfilePosTOwnerName">
<p>{data.postOwnerFullName}</p>
</div>
</div>
</div>
</div></Link>
)
})}
</div>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
isLoggedIn:state.logInStatus
}
};
const mapDispatchToProps = (dispatch) => {
return {
getTagProfileData:(slug) => dispatch(tagProfileActions.getTagDetails(slug)),
getTagFollowInfo:slug => dispatch(tagProfileActions.getTagFollowInfo(slug)),
toogleSignInOut:bool => dispatch(headerAction.toggleSignPop(bool)),
popErrorNotification:(bool,color,message) => dispatch(notificationActions.popUpNotification(bool,color,message)),
tagProfileFollow:(data) => dispatch(tagProfileActions.tagProfileFollow(data))
}
};
export default connect(mapStateToProps,mapDispatchToProps)(TagProfile)
Finally I got Solution
Just added KeyDown and Onclick Evt And Throwed some if else statement for KeyBoard Events..
handleFollow(e){
e.preventDefault()
if(e.type !== 'keydown'){
//Start Code From here
}
}