Remove Transaction with a certain ID in Firebase database - reactjs

How do I remove the transaction with a certain ID it includes data like name, company, position etc., as shown in the code and image below. It is saved in firebase database and I want a certain transaction completely removed. I cant figure out how to remove I tried `
deleteItem(key){
const filteredItems = this.state.items.filter(item =>
item.key!==key);
this.setState({
items:filteredItems
})
}
but its not working
import React, { Component } from 'react';
import fire from '../../config/Fire';
import Transaction from './Transaction/Transaction';
class Tracker extends Component {
state = {
transactions: [],
name: '',
company: '',
position: '',
link: '',
currentUID: fire.auth().currentUser.uid
}
handleChange = input => e => {
this.setState({
[input]: e.target.value !=="0" ? e.target.value : ""
});
}
// add transaction
addNewTransaction = () => {
const {name, company, position, link, currentUID} = this.state;
// validation
if(name && company && position && link){
const BackUpState = this.state.transactions;
BackUpState.push({
id: BackUpState.length + 1,
name: name,
company: company,
position: position,
link: link,
user_id: currentUID
});
fire.database().ref('Transactions/' + currentUID).push({
id: BackUpState.length,
name: name,
company: company,
position: position,
link: link,
user_id: currentUID
}).then((data) => {
//success callback
console.log('success callback');
this.setState({
transactions: BackUpState,
name: '',
company: '',
position: '',
link: ''
})
}).catch((error)=>{
//error callback
console.log('error ' , error)
});
}
}
componentWillMount(){
const {currentUID} = this.state;
const BackUpState = this.state.transactions;
fire.database().ref('Transactions/' + currentUID).once('value',
(snapshot) => {
// console.log(snapshot);
snapshot.forEach((childSnapshot) => {
BackUpState.push({
id: childSnapshot.val().id,
name: childSnapshot.val().name,
company: childSnapshot.val().company,
position: childSnapshot.val().position,
link: childSnapshot.val().link,
user_id: childSnapshot.val().user_id
});
// console.log(childSnapshot.val().name);
});
this.setState({
transactions: BackUpState,
});
});
}
render(){
var currentUser = fire.auth().currentUser;
return(
<div className="newTransactionBlock">
<div className="newTransaction">
<form>
<input
onChange={this.handleChange('name')}
value={this.state.name}
placeholder="Name"
type="text"
name="name"
/>
<div className="inputGroup">
<input
onChange={this.handleChange('company')}
value={this.state.company}
placeholder="Company"
type="text"
name="company"
/>
<input
onChange={this.handleChange('position')}
value={this.state.position}
placeholder="Position"
type="text"
name="position"
/>
<input
onChange={this.handleChange('link')}
value={this.state.link}
placeholder="Link"
type="url"
name="link"
/>
</div>
</form>
<button onClick={() => this.addNewTransaction()} className="addTransaction">+ Add Transaction</button>
</div>
</div>
<div className="latestTransactions">
<p>Latest Transactions</p>
<ul>
{
Object.keys(this.state.transactions).map((id) => (
<Transaction key={id}
name={this.state.transactions[id].name}
company={this.state.transactions[id].company}
position={this.state.transactions[id].position}
link={this.state.transactions[id].link}
/>
))
}
</ul>
</div>
</div>
);
}
}
export default Tracker;
Here is the transaction List imported
import React from 'react';
const Transaction = props => {
return (
<li>
<div>{props.name}</div>
<div>{props.company}</div>
<div>{props.position}</div>
<div>{props.link}</div>
<button>remove</button>
</li>
);
}
export default Transaction;

Related

I want to clear the text fields once I click on filter button

In this code I am unable to clear both the text fields even though I'm setting their states to blank after clicking on filter via this.Search function.
import React from 'react' import Axios from './Axios' import
'./index.css' export default class Practise extends React.Component {
constructor(props) {
super(props)
this.state = {
lists: [],
names: '',
emails: '',
arr: [],
}
this.Search = (names, emails) => {
const arr = this.state.lists.filter(item => {
if (item.name.includes(this.state.names) && item.email.includes(this.state.emails)) {
return true
} else {
return false
}
})
this.setState({names:''})
this.setState({emails:''})
console.log(arr)
}
}
componentDidMount() {
Axios.get('/comments').then(response => {
// console.log(response.data, 'data')
this.setState({ lists: response.data })
}).catch(response => {
console.log(response, 'Errored!!!')
this.setState({ errored: 'Error has Occured' })
})
}
render() {
const { lists, arr, names, emails } = this.state
return (
<>
<div >
<input type='text' onChange={(e) => this.setState({ names: e.target.value })} />
<input type='text' onChange={(p) => this.setState({ emails: p.target.value })} />
<button onClick={()=>this.Search()}>Filter</button>
</div>
<div>
{lists.length ? lists.map(item =>
<div className='divone' key={item.id}>
Id:- {item.id} <br />
Name:- {item.name} <br />
Email:- {item.email}</div>) : null}
</div>
</>
)
}
};
You have to add the value prop to both of the inputs.After that,
if you change the state to a blank string, the value of inputs will also get blank.Here is an example -
<input type='text' value={this.state.names} onChange={(e) => this.setState({ names: e.target.value })} />
<input type='text' value={this.state.emails} onChange={(p) => this.setState({ emails: p.target.value })} />
It should work.

React Redux - Showing Dialog after posting data not working - Unhandled Rejection (TypeError): Cannot read property 'openDialog' of undefined

I am very new to react-redux. I am trying to get an dialogbox to show "data posted successfully" upon posting of data through api. I want to achieve it through:
this.insertSingleUser(postData).then(function () {
console.log("user inserted");
this.openDialog("Data posted successfully");
});
Everything is working fine except this piece, data is being posted, console result is being shown but the dialog box this.openDialog("Data posted successfully"); is not opening.
However dialogbox will open if called outside of this.insertSingleUser(postData).then(function () { .
Please suggest me what i am doing wrong over here. Full code is pasted below:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { postUser } from '../redux/user/userActions';
import AlertDialog from '../reusables/AlertDialog';
class UsersContainerPost extends Component {
constructor(props) {
super(props);
this.state = {
first_name: '',
last_name: '',
phone: '',
email: '',
address: '',
city: '',
state: '',
message: '',
dialogIsOpen: false,
dialogHeaderText: '',
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
openDialog = (dialogHeaderMessage) => {
this.setState({
dialogIsOpen: true,
dialogHeaderText: dialogHeaderMessage
})
}
closeDialog = () => {
this.setState({
dialogIsOpen: false
})
}
handleChange = (field, event) => {
this.setState({ [field]: event.target.value })
}
async insertSingleUser(postData) {
return this.props.insertUser(postData);
}
handleSubmit(event) {
// alert('A name was submitted: ' + this.state.name);
event.preventDefault();
const {
first_name,
last_name,
phone,
email,
address,
city,
state
} = this.state;
const postData = {
first_name: first_name,
last_name: last_name,
phone: phone,
email: email,
address: address,
city: city,
state: state
};
// console.log(this.state);
// console.log(postData);
// alert('hi');
// this.props.insertUser(postData);
// console.log("user inserted");
this.insertSingleUser(postData).then(function () {
console.log("user inserted");
this.openDialog("Data posted successfully");
});
console.log("message" + this.props.message);
// (this.props.message) ? this.openDialog("Data posted successfully") : this.openDialog("Data POst error");
}
render() {
return (
<div>
<h1>Add New User</h1>
<form onSubmit={this.handleSubmit}>
<div>
<label>First Name:</label>
<input
type="text"
value={this.state.first_name}
onChange={(event, newValue) => this.handleChange('first_name', event)} />
</div>
<div>
<label>Last Name:</label>
<input
type="text"
value={this.state.last_name}
onChange={(event, newValue) => this.handleChange('last_name', event)} />
</div>
<div>
<label>Phone:</label>
<input
type="text"
value={this.state.phone}
onChange={(event, newValue) => this.handleChange('phone', event)} />
</div>
<div>
<label>Email:</label>
<input
type="text"
value={this.state.email}
onChange={(event, newValue) => this.handleChange('email', event)} />
</div>
<div>
<input type="submit" value="Submit" />
</div>
</form>
<div>
Notice Message : {this.props.message}
</div>
<div>
<Link to='/'>Go Home</Link>
</div>
{/* {this.props.message ? (<AlertDialog open={this.state.dialogIsOpen} onClose={this.closeDialog} />) : ('')} */}
<AlertDialog
headerMessage={this.state.dialogHeaderText}
open={this.state.dialogIsOpen}
onClose={this.closeDialog}
/>
</div>
);
}
}
const mapStateToProps = state => {
// console.log(state.user.successMessage);
return {
message: state.user.successMessage
}
}
const mapDispatchToProps = dispatch => {
return {
insertUser: postData => dispatch(postUser(postData))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(UsersContainerPost);
Thanks in advance.
Use an arrow function so the parent this is accessible from inside .then() callback.
Like this:
this.insertSingleUser(postData).then(() => {
console.log("user inserted");
this.openDialog("Data posted successfully");
});
So instead of this.insertSingleUser(postData).then(function() {...}) with the function keyword, you use this.insertSingleUser(postData).then(() => {...}) with the arrow function

Title and event form input not posted and retrieve using Reactjs

The Reactjs code below works excellently by posting and retrieving Users newStatus from a form input to and from an API.
Now I want to add two additional form form inputs (newTitle and newEvent) as per code below
<input className="input-status" name="newTitle"
value={this.state.newTitle}
onChange={e => this.handleNewStatusChange(e)}
placeholder="your Title"
/>
<input className="input-status" name="newEvent"
value={this.state.newEvent}
onChange={e => this.handleNewStatusChange(e)}
placeholder="Your Event Centre Name"
/>
I have also implemented newEvent and newTitle variables in code where possible. My issue is that if type in the first form inputs (eg newStatus) it gets replicated or inserted in all other remaining two forms inputs as can be seen in the screenshot below.
And I believe that's why only the newStatus get posted and retrieved.
I have commented out all newEvent and newTitle variables in code so readers can see where I am wrong.
Here is the code profile.jsx:
import React, { Component } from 'react';
import {
isSignInPending,
loadUserData,
Person,
getFile,
putFile,
lookupProfile
} from 'blockstack';
import Status from './Status.jsx';
const avatarFallbackImage = 'https://mysite/onename/avatar-placeholder.png';
const statusFileName = 'statuses.json'
export default class Profile extends Component {
constructor(props) {
super(props);
this.state = {
person: {
name() {
return 'Anonymous';
},
avatarUrl() {
return avatarFallbackImage;
},
},
username: "",
newStatus: "",
//newTitle: "",
// newEvent: "",
statuses: [],
statusIndex: 0,
isLoading: false
};
this.handleDelete = this.handleDelete.bind(this);
this.isLocal = this.isLocal.bind(this);
}
componentDidMount() {
this.fetchData()
}
handleNewStatusChange(event) {
this.setState({
newStatus: event.target.value,
//newTitle: event.target.value,
//newEvent: event.target.value
})
}
handleNewStatusSubmit(event) {
this.saveNewStatus(
this.state.newStatus,
//this.state.newTitle,
//this.state.newEvent
)
this.setState({
newStatus: "",
//newTitle: "",
//newEvent: "",
})
}
handleDelete(id) {
const statuses = this.state.statuses.filter((status) => status.id !== id)
const options = { encrypt: false }
putFile(statusFileName, JSON.stringify(statuses), options)
.then(() => {
this.setState({
statuses
})
})
}
saveNewStatus(statusText) {
let statuses = this.state.statuses
let status = {
id: this.state.statusIndex++,
text: statusText.trim(),
//textTitle: statusText.trim(),
//textEvent: statusText.trim(),
created_at: Date.now()
}
statuses.unshift(status)
const options = { encrypt: false }
putFile(statusFileName, JSON.stringify(statuses), options)
.then(() => {
this.setState({
statuses: statuses
})
})
}
fetchData() {
if (this.isLocal()) {
this.setState({ isLoading: true })
const options = { decrypt: false, zoneFileLookupURL: 'https://myapi/v1/names/' }
getFile(statusFileName, options)
.then((file) => {
var statuses = JSON.parse(file || '[]')
this.setState({
person: new Person(loadUserData().profile),
username: loadUserData().username,
statusIndex: statuses.length,
statuses: statuses,
})
})
.finally(() => {
this.setState({ isLoading: false })
})
} else {
const username = this.props.match.params.username
this.setState({ isLoading: true })
lookupProfile(username)
.then((profile) => {
this.setState({
person: new Person(profile),
username: username
})
})
.catch((error) => {
console.log('could not resolve profile')
})
const options = { username: username, decrypt: false, zoneFileLookupURL: 'https://myapi/v1/names/'}
getFile(statusFileName, options)
.then((file) => {
var statuses = JSON.parse(file || '[]')
this.setState({
statusIndex: statuses.length,
statuses: statuses
})
})
.catch((error) => {
console.log('could not fetch statuses')
})
.finally(() => {
this.setState({ isLoading: false })
})
}
}
isLocal() {
return this.props.match.params.username ? false : true
}
render() {
const { handleSignOut } = this.props;
const { person } = this.state;
const { username } = this.state;
return (
!isSignInPending() && person ?
<div className="container">
<div className="row">
<div className="col-md-offset-3 col-md-6">
<div className="col-md-12">
<div className="avatar-section">
<img
src={ person.avatarUrl() ? person.avatarUrl() : avatarFallbackImage }
className="img-rounded avatar"
id="avatar-image"
/>
<div className="username">
<h1>
<span id="heading-name">{ person.name() ? person.name()
: 'no name found' }</span>
</h1>
<span>{username}</span>
{this.isLocal() &&
<span>
|
<a onClick={ handleSignOut.bind(this) }>(Logout)</a>
</span>
}
</div>
</div>
</div>
{this.isLocal() &&
<div className="new-status">
<div className="col-md-12">
<textarea className="input-status" name="newStatus"
value={this.state.newStatus}
onChange={e => this.handleNewStatusChange(e)}
placeholder="What's on your mind?"
/>
<input className="input-status" name="newTitle"
value={this.state.newTitle}
onChange={e => this.handleNewStatusChange(e)}
placeholder="your Title"
/>
<input className="input-status" name="newEvent"
value={this.state.newEvent}
onChange={e => this.handleNewStatusChange(e)}
placeholder="Your Event Centre Name"
/>
</div>
<div className="col-md-12 text-right">
<button
className="btn btn-primary btn-lg"
onClick={e => this.handleNewStatusSubmit(e)}
>
Submit
</button>
</div>
</div>
}
<div className="col-md-12 statuses">
{this.state.isLoading && <span>Loading...</span>}
{
this.state.statuses.map((status) => (
<Status
key={status.id}
status={status}
handleDelete={this.handleDelete}
isLocal={this.isLocal}
/>
))
}
</div>
</div>
</div>
</div> : null
);
}
}
Here is just sample part for for status.jsx showing how I successfully return the status:
//some coding...
return (
<div className="status">
<div className="status-text">
{status.text}
/*
{status.textTitle} {status.textEvent}
*/
</div>
</div>
)
You can use the name attribute of the input field to your advantage.
And update your change handler function:
handleNewStatusChange(event) {
this.setState({
[event.target.name]: event.target.value,
})
}
more info on { [key]: value }

React: How to assign an image stored in Firebase Storage to items stored in Firebase Database?

I'm rendering a list of items stored in a Firebase Database and I'm wondering if it's possible to assign a distinct image (stored in Firebase Storage) to each distinct item in the list.
I've implemented upload functionality which can subsequently display the most recently uploaded file but I can't figure out how to assign an image to am item within my Database which persistently displays next to the item when rendered.
AdminPanel component code:
class AdminPanel extends Component {
constructor() {
super();
this.state = {
companyName: '',
ownerName: '',
items: [],
search: '',
image: '',
imageURL: '',
progress: 0,
images: null
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
this.setState({
[e.target.name]: e.target.value
});
}
handleSubmit(e) {
e.preventDefault();
const itemsRef = firebase.database().ref('items');
const item = {
companyNameObj: this.state.companyName,
ownerNameObj: this.state.ownerName
}
itemsRef.push(item);
this.setState({
companyName: '',
ownerName: ''
});
}
componentDidMount() {
const itemsRef = firebase.database().ref('items');
itemsRef.on('value', (snapshot) => {
let items = snapshot.val();
let newState = [];
for (let item in items) {
newState.push({
id: item,
companyNameObj: items[item].companyNameObj,
ownerNameObj: items[item].ownerNameObj
});
}
this.setState({
items: newState
});
});
}
removeItem(itemId) {
const itemRef = firebase.database().ref(`/items/${itemId}`);
itemRef.remove();
}
handleUploadStart = () => {
this.setState({
progress: 0
})
}
handleUploadSuccess = filename => {
this.setState({
image: filename,
progress: 100
})
firebase.storage().ref('images').child(filename).getDownloadURL().then(url => this.setState({
imageURL: url
}))
}
render() {
var image = this.state.imageURL;
let filteredItems = this.state.items.filter(
(item) => {
return item.companyNameObj.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1;
}
);
return (
<div>
<h1>ADMIN PANEL</h1>
<form onSubmit={this.handleSubmit}>
<input type="text" name="ownerName" placeholder="Company name: " onChange={this.handleChange} value={this.state.ownerName} />
<input type="text" name="companyName" placeholder="Owned by: " onChange={this.handleChange} value={this.state.companyName} />
<button>Add Company</button>
<input type="text" name="search" placeholder="Search: " onChange={this.handleChange} value={this.state.search} />
</form>
<label>
<p>Progress: </p>
{this.state.progress}
</label>
<label>
<p>Image: </p>
{this.state.image && <img src={this.state.imageURL} />}
</label>
<FileUploader
accept='image/*'
name='image'
storageRef={firebase.storage().ref('images')}
onUploadStart={this.handleUploadStart}
onUploadSuccess={this.handleUploadSuccess}
/>
<ul>
{filteredItems.map((item) => {
return (
<li key={item.id}>
<h3>{item.companyNameObj}</h3>
<p>Owned by: {item.ownerNameObj}</p>
{<img src={this.state.imageURL} />}
<button onClick={() => this.removeItem(item.id)}>Remove Item</button>
</li>
)
})}
</ul>
</div>
);
}
}
export default AdminPanel;
You need to get the url from the FirebaseStorage and place it the RealtimeDatabase or Firestore object.
I managed to implement a solution thanks to #Juanje's answer:
You need to get the url from the FirebaseStorage and place it the RealtimeDatabase or Firestore object.
I mapped the image URL to an image object in my handleSubmit(e) method and and pushed the URL object to the database in my componentDidMount() method as follows:
handleSubmit(e) {
e.preventDefault();
const itemsRef = firebase.database().ref('items');
const item = {
companyNameObj: this.state.companyName,
ownerNameObj: this.state.ownerName,
imageObj: this.state.imageURL
}
itemsRef.push(item);
this.setState({
companyName: '',
ownerName: '',
});
console.log(item);
}
and
componentDidMount() {
const itemsRef = firebase.database().ref('items');
itemsRef.on('value', (snapshot) => {
let items = snapshot.val();
let newState = [];
for (let item in items) {
newState.push({
id: item,
companyNameObj: items[item].companyNameObj,
ownerNameObj: items[item].ownerNameObj,
imageObj: items[item].imageObj
});
}
this.setState({
items: newState
});
});
}
To render the URL I added an tag to my mapped list and passed imageObj which contains the Firebase storage as the source as follows:
<ul>
{filteredItems.map((item) => {
return (
<li key={item.id}>
<h3>{item.companyNameObj}</h3>
<p>Owned by: {item.ownerNameObj}</p>
<img src={item.imageObj} />
<button onClick={() => this.removeItem(item.id)}>Remove Item</button>
</li>
)
})}
</ul>

Reactjs Hiding form clicking on button from another component

I have written a crud application and it works great!
I have successfully implemented when people click on ADD NEW button form will be visible
Now i am facing challange to hide form when people click on SAVE button, coz, the SAVE another component.
Here you go for my Form.js File:
import React, { Fragment } from "react"
import { connect } from 'react-redux'
const axios = require('axios');
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
id: this.props.selectedData.id,
name: this.props.selectedData.name,
age: this.props.selectedData.age,
};
this.onHandleChange = this.onHandleChange.bind(this);
this.submit = this.submit.bind(this);
}
submit(event) {
const data = {
name: this.state.name,
age: this.state.age,
email: this.state.email
};
if (this.props.isEdit) {
data.id = this.props.selectedData.id;
axios.put('http://127.0.0.1:8000/api/v1/employee/' + data.id + '/', data)
.then((response) => {
this.props.dispatch({ type: 'EDIT_POST', response });
});
} else {
// generate id here for new emplyoee
axios.post('http://127.0.0.1:8000/api/v1/employee/', data)
.then((response) => {
this.props.dispatch({ type: 'ADD_POST', response });
});
}
}
onHandleChange(event) {
this.setState({
[event.target.name]: event.target.value
});
}
componentDidUpdate(prevProps) {
if (prevProps.selectedData.age !== this.props.selectedData.age) { //Check on email, because email is unique
this.setState({ name: this.props.selectedData.name, age: this.props.selectedData.age })
}
}
render() {
return (
<form>
<div className="form-group">
<input onChange={(event) => this.onHandleChange(event)} value={this.state.name} name="name" type="text" />
</div>
<div className="form-group">
<input onChange={(event) => this.onHandleChange(event)} value={this.state.age} name="age" type="number" />
</div>
<button onClick={(event) => this.submit(event)} type="button">
{this.props.isEdit ? 'Update' : 'SAVE'}
</button>
</form>
);
}
}
export default connect(null)(Form);
And this is my Home.js file:
import React from "react"
import Table from "../components/table"
import Form from '../components/form'
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedData: {name: '', age: ''},
isEdit: false,
isFormVisible: false,
};
}
selectedData = (item) => {
this.setState({selectedData: item,isEdit:true, isFormVisible: true})
}
render() {
return (
<React.Fragment>
{this.state.isFormVisible && <div>
<Form selectedData={this.state.selectedData} isEdit={this.state.isEdit}/>
</div>}
{!this.state.isFormVisible &&
<button onClick={() => this.setState({isFormVisible: true})}>ADD NEW</button>}
<table>
<Table selectedData={this.selectedData} />
</table>
</React.Fragment>
);
}
}
export default Home;
Everything is working fine, only issue is hiding the form when i click on SAVE button.
Can anyone help to hide the form clicing on SAVE button?
Inside your Home.js, create a function that does the state change for you and pass it down as a prop to the Form Component.
Home.js
changeFormState = () => {
this.setState({ isFormVisible: !isFormVisible });
}
<Form
changeFormState={this.changeFormState}
selectedData={this.state.selectedData}
isEdit={this.state.isEdit}
/>
Form.js
<button
onClick={(event) => { this.props.isEdit ? this.submit(event) :
this.props.changeFormState() }} type="button"
>
{this.props.isEdit ? 'Update' : 'SAVE'}
</button>
JS Update
submit(event) {
const data = {
name: this.state.name,
age: this.state.age,
email: this.state.email
};
if (this.props.isEdit) {
data.id = this.props.selectedData.id;
axios.put('http://127.0.0.1:8000/api/v1/employee/' + data.id + '/', data)
.then((response) => {
// Fire an event
this.props.onSave && this.props.onSave();
this.props.dispatch({ type: 'EDIT_POST', response });
});
} else {
// generate id here for new emplyoee
axios.post('http://127.0.0.1:8000/api/v1/employee/', data)
.then((response) => {
// Fire an event
this.props.onSave && this.props.onSave();
this.props.dispatch({ type: 'ADD_POST', response });
});
}
}
hideForm = () => { this.setState({ isFormVisible: false }); }
JSX Update
<Form
selectedData={this.state.selectedData}
isEdit={this.state.isEdit}
onSave={this.hideForm}
/>

Resources