Reputation: 2045
App is running on Node.js and React. In database (mongodb used) I have collection Rooms that contains details about particular room.
I am trying to search that collection based on for example number of guests and if number of guests in search input is 2 I would like to display all the rooms that can have two guests.
Also my question is is it possible to do search input for every field in collection rooms? For example number of guests, room type, price and so on...
Also is it better to do it with search input or dropdown search?
SERVER PART
UserModel.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Define our model
const roomSchema = new Schema({
title: { type: String },
description: { type: String },
price: { type: Number },
room_type: { type: String },
nb_guests: { type: Number },
imageData: {type: String}
});
// Create the model class
const ModelClass = mongoose.model('room', roomSchema);
// Export the model
module.exports = ModelClass;
CLIENT PART
LandingPage.js
const Room = props => (
<div className = "col-md-4" >
<div className="card mb-4 shadow-sm">
<img src={room9} class="card-img-top"
alt="..." width="100%" height="225" />
<div className="card-body">
<h5 class="card-title">{props.room.title}</h5>
<p className="card-text">{props.room.description}</p>
<div className="d-flex justify-content-between align-
items-center">
<div className="btn-group">
<Link className="btn btn-sm
btn-outline-secondary" to={"/view/"+props.room._id}>View</Link>
</div>
</div>
</div>
</div>
</div >
)
function searchingFor(term){
return function(x){
return x.props.room.nb_guests.toLowerCase().includes(term.toLowerCase()) || !term;
}
}
export default class LandingPage extends React.Component {
constructor(props) {
super(props);
this.state = {
rooms: [],
term:''
}
this.onSearchHandler = this.onSearchHandler.bind(this);
}
componentDidMount() {
axios.get('http://localhost:3090/admin/')
.then(response => {
this.setState({
rooms: response.data
})
.catch(function (error) {
console.log(error);
})
})
}
roomList() {
return this.state.rooms.filter(searchingFor(this.state.term)).map(function (currentRoom, i) {
return <Room room={currentRoom} key={i} />
});
}
onSearchHandler(e){
this.setState({
term:e.target.value
})
}
render() {
return (
<div>
<LPheader />
<Carousel />
<div>
<div className="album py-5 bg-light">
<div className="container">
<div className="row">
<form>
<input
type="text"
onChange={this.onSearchHandler}
value={term}
/>
</form>
{this.roomList()}
</div>
</div>
</div>
</div>
</div>
)
}
}
This is the code I started with and I am getting this error
Uncaught ReferenceError: term is not defined
To be completely honest I am not even sure if this is right way to do it, any advice would be highly appreciated.
Update
roomList = () => {
const { rooms, term } = this.state;
if (!term) {
return rooms.map(function(currentRoom, i) {
return <Room room={currentRoom} key={i} />;
});
} else if {
return rooms
.filter(room => {
return room.nb_guests == term;
})
.map(matchingRoom => {
return <Room room={matchingRoom} />;
});
else if{
.filter(room => {
return room.price == term;
})
.map(matchingRoom => {
return <Room room={matchingRoom} />;
});
else if{
.filter(room => {
return room.room_type == term;
})
.map(matchingRoom => {
return <Room room={matchingRoom} />;
});
}
}
};
onSearchHandlerPrice = e => {
this.setState({
term: (e.target.value)
});
};
onSearchHandlerGuests = e => {
this.setState({
term: (e.target.value)
});
};
<div className="container">
<div className="row">
<form>
<input type="text" onChange={this.onSearchHandlerGuests} value={this.state.term} />
</form>
<form>
<input type="text" onChange={this.onSearchHandlerPrice} value={this.state.term} />
</form>
{this.roomList()}
</div>
</div>
Upvotes: 1
Views: 4124
Reputation: 15688
You're very close to getting this done. I think the searchingFor()
function is over-complicating your logic. See the following sandbox on how you can filter the rooms by number of guests: https://codesandbox.io/s/thirsty-dan-vjt7o
Notes:
axios
request and just plugged in some sample
data. It should still work if you swap it back with your own code.You could simplify your code by updating the term
state-value as the user types, causing a re-render and inside the newly executed roomList()
, filter and return the appropriate rooms that match term
.
roomList = () => {
const { rooms, term } = this.state;
if (!term) {
return rooms.map(function(currentRoom, i) {
return <Room room={currentRoom} key={i} />;
});
} else {
return rooms
.filter(room => {
return room.nb_guests == term;
})
.map(matchingRoom => {
return <Room room={matchingRoom} />;
});
}
};
onSearchHandler = e => {
this.setState({
term: e.target.value
});
};
Upvotes: 2