0% found this document useful (0 votes)
4 views

image problem

Uploaded by

hspandit071
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

image problem

Uploaded by

hspandit071
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 5

### 1. **Models/Listing.

js**
No change is needed here, as the model seems fine for handling the image URL. But
I'll make sure the `image.url` is always passed correctly.

```javascript
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const Review = require("./review.js");

const listingSchema = new Schema({


title: {
type: String,
required: true,
},
description: {
type: String,
},
image: {
url: {
type: String,
default: "https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-
736885_1280.jpg",
},
},
price: {
type: Number,
},
location: {
type: String,
},
country: {
type: String,
},
reviews: [
{
type: Schema.Types.ObjectId,
ref: "Review",
},
],
});

listingSchema.post("findOneAndDelete", async (listing) => {


if (listing) {
await Review.deleteMany({ _id: { $in: listing.reviews } });
}
});

const Listing = mongoose.model("Listing", listingSchema);


module.exports = Listing;
```

### 2. **Edit.ejs**
Make sure that the `image.url` field is correctly populated when editing. In your
form, you are handling the image URL input correctly. However, let's ensure that
the field is updated after editing.

```ejs
<%= layout("/layouts/boilerplate") %>
<div class="row mt-3">
<div class="col-8 offset-2">
<h3>Edit your Listing</h3>
<form method="POST" action="/listings/<%= listing._id %>?_method=PUT"
noValidate class="needs-validation">
<div class="mb-3">
<label for="title" class="form-label">Title</label>
<input name="listing[title]" value="<%= listing.title %>" type="text"
class="form-control" required>
<div class="valid-feedback">Title looks good</div>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea name="listing[description]" class="form-control" required><%=
listing.description %></textarea>
<div class="invalid-feedback">Please enter a short description</div>
</div>
<div class="mb-3">
<label for="image" class="form-label">Image URL</label>
<input name="listing[image][url]" value="<%= listing.image.url %>"
type="text" class="form-control" required>
<div class="invalid-feedback">Please enter a valid link</div>
</div>
<div class="row">
<div class="mb-3 col-md-4">
<label for="price" class="form-label">Price</label>
<input name="listing[price]" value="<%= listing.price %>"
type="number" class="form-control" required>
<div class="invalid-feedback">Price should be valid</div>
</div>
<div class="mb-3 col-md-8">
<label for="country" class="form-label">Country</label>
<input name="listing[country]" value="<%= listing.country %>"
type="text" class="form-control" required>
<div class="invalid-feedback">Country name should be valid</div>
</div>
</div>
<div class="mb-3">
<label for="location" class="form-label">Location</label>
<input name="listing[location]" value="<%= listing.location %>"
type="text" class="form-control" required>
<div class="invalid-feedback">Location should be valid</div>
</div>
<button class="btn btn-dark edit-btn mt-3">Edit</button>
</form>
</div>
</div>
```

### 3. **Show.ejs**
Ensure the image is displayed by properly accessing the `image.url` in the `img`
tag. The rest of your code for the show page looks good.

```ejs
<%= layout("/layouts/boilerplate") %>
<div class="row">
<div class="col-8 offset-3 mt-3">
<h3><%= listing.title %></h3>
</div>
<div class="card col-6 offset-3 show-card listing-card">
<img src="<%= listing.image.url %>" class="card-img-top show-img"
alt="listing_image">
<div class="card-body">
<p class="card-text">
<%= listing.description %><br>
&#8377; <%= listing.price.toLocaleString("en-IN") %><br>
<%= listing.location %><br>
<%= listing.country %>
</p>
</div>
</div>
<br>
<div class="btns">
<a href="/listings/<%= listing._id %>/edit" class="btn btn-dark col-1
offset-3 edit-btn">Edit</a>

<form method="POST" action="/listings/<%= listing._id %>?_method=DELETE">


<button class="btn btn-dark offset-5">Delete</button>
</form>
</div>

<div class="col-8 offset-3 mb-3">


<hr>
<h4>Leave a Review</h4>
<form action="/listings/<%= listing.id %>/reviews" method="POST" novalidate
class="needs-validation">
<div class="mb-3 mt-3">
<label for="rating" class="form-label">Rating</label>
<input type="range" min="1" max="5" id="rating"
name="review[rating]" class="form-range">
</div>
<div class="mb-3 mt-3">
<label for="comment" class="form-label">Comments</label>
<textarea name="review[comment]" id="comment" col="30" rows="5"
class="form-control" required></textarea>
<div class="invalid-feedback">Please add some comments for
review</div>
</div>
<button class="btn btn-outline-dark">Submit</button>
</form>

<hr>

<p><b>All Reviews</b></p>
<div class="row">

<% for(review of listing.reviews) { %>


<div class="card col-5 ms-3 mb-3">
<div class="card-body">
<h5 class="card-title">Jane Doe</h5>
<p class="card-text"><%= review.comment %></p>
<p class="card-text"><%= review.rating %> Stars</p>
</div>
<form class="mb-3" method="POST" action="/listings/<%= listing._id
%>/reviews/<%= review._id %>?_method=DELETE">
<button class="btn btn-sm btn-dark">Delete</button>
</form>
</div>
<% } %>
</div>
</div>
</div>
```

### 4. **Routes.js**
No changes are needed for the routes. The current route handling for `GET`, `POST`,
and `PUT` for listings should work fine. The image URL is updated in the database
when the form is submitted.

```javascript
const express = require("express");
const router = express.Router();
const wrapAsync = require("../utils/wrapAsync.js");
const ExpressError = require("../utils/ExpressError.js");
const { listingSchema, reviewSchema} = require("../schema.js");
const Listing = require("../models/listing.js");

const validateListing = ((req, res, next) => {


let {error} = listingSchema.validate(req.body);
if(error) {
let errMsg = error.details.map((el) => el.message).join(",");
throw new ExpressError(400, errMsg);
} else {
next();
}
});

// Index Route
router.get("/", wrapAsync(async (req, res) => {
const allListings = await Listing.find({});
res.render("listings/index.ejs", { allListings });
}));

// New Route
router.get("/new", (req, res) => {
res.render("listings/new.ejs");
});

// Show Route
router.get("/:id", wrapAsync(async (req, res) => {
let {id} = req.params;
const listing = await Listing.findById(id).populate("reviews");
res.render("listings/show.ejs", { listing });
}));

// Create Route
router.post("/", validateListing, wrapAsync(async (req, res, next) => {
const newListing = new Listing(req.body.listing);
await newListing.save();
res.redirect("/listings");
}));

// Edit Route
router.get("/:id/edit", wrapAsync(async (req, res) => {
let {id} = req.params;
const listing = await Listing.findById(id);
res.render("listings/edit.ejs", { listing });
}));

// Update Route
router.put("/:id", validateListing, wrapAsync(async (req, res) => {
let {id} = req.params;
await Listing.findByIdAndUpdate(id, { ...req.body.listing });
res.redirect(`/listings/${id}`);
}));

// Delete Route
router.delete("/:id", wrapAsync(async (req, res) => {
let {id} = req.params;
let deletedListing = await Listing.findByIdAndDelete(id);
console.log(deletedListing);
res.redirect("/listings");
}));

module.exports = router;
```

You might also like