Как сделать выделение изображений с помощью ejs и express?

Я использую node, express, moongoDB и EJS для создания сайта блога с настраиваемой системой управления сообщениями. Все это работает хорошо, но теперь я пытаюсь использовать загруженные Cloudinary изображения из моей mongoDB, чтобы добавить несколько изображений в сообщения на странице загрузки / редактирования. Теоретически это работает очень просто, так как мне просто нужно добавить идентификаторы изображений или URL-адреса к выбранному документу публикации, но выбор того, какой пост и какие изображения на одной странице, вызывает у меня головную боль. Я изо всех сил пытаюсь использовать интерфейсные JS и EJS в гармонии с этим, поскольку выбор должен быть сделан во внешнем интерфейсе и отправлен в серверную часть через форму html, я полагаю, с массивом, который включает мои выборы изображений. Мой код создает массив с именем imageSelection для хранения изображений, выбранных пользователем с помощью JS, а затем он пытается преобразовать JSON в строку и отправить массив на сервер для обработки.

Я смог сохранить изображения в массиве с помощью JS и использовать foreach для циклического перебора изображений из моей базы данных для отображения параметров с помощью EJS. Тогда я могу только понять, как отправлять статические данные POST, но это не работает так, как мне нужно, поскольку я хочу опубликовать массив выбора изображения после его преобразования в строку. Кажется, я не могу использовать простой JS для преобразования и публикации данных, которые я храню в своем массиве в ванильном JS, потому что мне нужно вызвать функцию, а затем вставить данные в отправленное значение. Я не уверен, что это единственная проблема с моим кодом здесь.

У меня есть предварительный просмотр выбранных изображений, которые должны отображаться, но я не могу использовать свой прежний код, потому что он работает с EJS, и ему нужно работать с простым JS для доступа к моему массиву imageSelection.

    <form action="/post-add-imgs" method="post">
  <div class="dropdown">
    <button class="btn btn-primary" type="button" data-toggle="dropdown">Select a Post
    <span class="caret"></span></button>
    <ul class="dropdown-menu  hover_img">
      <%  posts.forEach(function(post){ %>
        <li><a href="#"><%=post.title%></a></li>
        <% }); %>
    </ul>
    </div>

  <div class="uploads-gallery">
    <%  images.forEach(function(image){ %>
      <a href="#" onclick=" addImage(<%=image.url%>); "><img src="<%=image.url%>" alt="preview image" 
  height="100" /></a>
      <% }); %>
  </div>

  <input type="hidden" name=" imageSelection " value="json.stringify(imageSelection);">
  <button type="submit" name="button">Add image choice</button>
  </form>

Есть ли способ использовать ejs для отображения выбранных изображений, а затем опубликовать их после json.stringify? Нужно ли мне для этого использовать ajax?

Спасибо за помощь и мудрые слова.


person Jacob Siler    schedule 16.11.2019    source источник


Ответы (1)


Я не совсем уверен, что понимаю ваш вопрос, но давайте посмотрим, смогу ли я помочь с тем, что, как мне кажется, я знаю. Я думаю, вам нужно иметь возможность выбрать некоторые изображения, которые отображаются через файл .ejs, сохранить URL-адрес изображения в массиве через клиентский JS, а затем отправить этот массив в запросе POST на сервер Express.

Вот как я бы сделал это, взяв за основу ваш код:

Клиентская сторона

Я создал файл .ejs, который отображал некоторые изображения, которые мой сервер Express отправлял в локальной переменной images:

<div id="image-container">
  <% images.forEach((image) => { %>
     <a href="#"><img src="<%= image.url %>"></a>
  <% }) %>
</div>

<button id="add-image-button">Add Image Choice</button>

Затем у меня есть файл .js, который добавляет изображения, которые были нажаты, в массив imageSelection с помощью прослушивателя событий на <div>, который обертывает изображения:

const imageContainer = document.getElementById('image-container');
const imageSelection = [];

imageContainer.addEventListener('click', (e) => {
  if (!imageSelection.includes(e.target.src)) {
    imageSelection.push(e.target.src);
  }
});

И, наконец, когда пользователь нажимает кнопку «Добавить выбор изображения», изображения в массиве «imageSelection» отправляются через запрос выборки в конечную точку 'http://localhost:3001/post-images '. К addImageButton прикреплен eventListener, который прослушивает событие 'click', поэтому вам не нужен элемент <form>:

const addImageButton = document.getElementById('add-image-button');

addImageButton.addEventListener('click', async () => {
  const url = 'http://localhost:3001/post-images';
  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(imageSelection)
  });
  const myJson = await response.json();
  console.log(JSON.stringify(myJson));
});

На стороне сервера

На стороне Express у меня есть настройка обработчика маршрута для запроса POST / post-images, который просто отправляет данные POST-ed запрашивающей стороне:

router.post('/post-images', (req, res, next) => {
  res.json(req.body);
});

Итак, для ваших целей этот шаблон позволяет пользователю выбирать изображения, а затем нажимать кнопку, и URL-адреса этих изображений отправляются на сервер. Если это не то, что вы ищете, уточните, и я постараюсь помочь.

Сейчас суббота, 16.11.2019, 21:34 по Гринвичу, пока я редактирую это, и я выхожу из дома и не смогу помогать еще 20 часов или около того, так что не ожидайте ответ до 17:30 по Гринвичу в воскресенье, 17.11.2019.

Я поместил свой код в репозиторий git здесь, просто следуйте инструкциям в README, и вы должен иметь возможность проверить это на вашей машине. В данном примере вы хотите проверить следующие файлы:

  • просмотры / index.ejs
  • общедоступные / javascripts / main.js
  • маршруты / index.js

Вот изображение внешнего интерфейса с записанным ответом после выбора первых двух изображений:

введите здесь описание изображения

person DanielSchroederDev    schedule 16.11.2019
comment
Это невероятно полезно, и я считаю, что вы хорошо понимаете мою проблему. Этого может быть достаточно для завершения моего решения. Единственный элемент, который мне нужно добавить сейчас, - это селектор сообщений, чтобы я мог выбрать, к какому сообщению в блоге добавить свой выбор изображений. Я планирую сделать это в маршруте POST, взяв проанализированный массив изображений и добавив его в документ mongo для сообщения, которое я выбираю в интерфейсе. Вы были более чем полезны, я искренне ценю вас. - person Jacob Siler; 18.11.2019
comment
Я внедрил ваш код на моем сайте, и он отлично работает, за исключением публикации. Я не совсем уверен, почему, но вот ошибки на странице: Uncaught SyntaxError: Unexpected token '<' :3000/post-images:1 Failed to load resource: the server responded with a status of 404 (Not Found) main.js:24 Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0 - person Jacob Siler; 18.11.2019
comment
@JacobSiler, похоже, вы пытаетесь читать HTML как JSON. Посмотрите, поможет ли эта статья: daveceddia.com/unexpected-token-in -json-at-position-0 - person DanielSchroederDev; 18.11.2019
comment
@JacobSiler на самом деле, если сервер отвечает 404, это может означать, что вы отправляете запрос на выборку по несуществующему маршруту. На какой URL вы отправляете POST-запрос? Мой пример был настроен для моего конкретного сервера на маршруте POST / post-images с URL-адресом localhost: 3001 / post-images. Если у вас нет обработчика маршрута для этого, вы обязательно получите эту ошибку. Обратите внимание, что в запросе на выборку у меня есть переменная url, которая должна указывать на ВАШУ конечную точку, куда должны идти запросы POST. В вашем примере это был / post-add-imgs. - person DanielSchroederDev; 18.11.2019
comment
Вот мой текущий код: const url = "http://localhost:3000/post-images"; И моя попытка обработать маршрут: //When someone picks images. router.post("/post-images", (req, res, next) => { res.json(req.body); console.log("Post route working!"); }); Странно то, что он регистрирует, что маршрут работает правильно, но в консоли bash нет данных. Также выдает ошибку в консоли браузера. Но. Я могу убедиться, что он указывает на файл js, но он отображается с содержимым uploads.ejs в источниках. - person Jacob Siler; 19.11.2019
comment
в моем app.js мне нужно выразить и создать его экземпляр под названием 'app'. Я не использовал express.Router раньше, поэтому я просто потребовал его и назвал его маршрутизатором, чтобы заставить ваш код работать, но я просто изменил его наapp.post"/post-images", ..., и теперь я Могу убедиться, что почтовый маршрут работает, но я все равно получаю код ошибки 404 и неожиданную синтаксическую ошибку в консоли. - person Jacob Siler; 19.11.2019
comment
Что ж, я немного очистил свой код, и теперь ошибок нет, но теперь я снова получаю только пустой набор фигурных скобок. Я проверил, что imageSelection имеет два изображения в массиве, прежде чем нажимать кнопку добавления изображений. - person Jacob Siler; 19.11.2019
comment
Дальнейшее обновление: мне просто нужно было включить app.use(express.json()); в мой узел app.js, и он решил все оставшиеся ошибки! : D Большое спасибо за вашу любезную помощь в решении моих проблем и в этом. Не могу отблагодарить вас, @ Daniel.Schroeder - person Jacob Siler; 19.11.2019
comment
Сейчас я изо всех сил пытаюсь добавить свои изображения в выбранные мной почтовые документы Mongoose. Должен ли я задать для этого совершенно новый вопрос? - person Jacob Siler; 20.11.2019
comment
Мой текущий код: app.post("/post-images", (req, res) => { //const post=req const postImages = req.body; const postID = postImages.shift(); //res.json(postImages); console.log(postID); Post.update( { _id: postID }, { $push: { imageUrls: [{ postImages }] } }, { upsert: true }, function(err, foundPost) { if (!err) { console.log(foundPost); res.redirect("/"); } else { console.log(err); } } ); }); - person Jacob Siler; 20.11.2019
comment
Схема сообщения: const postSchema = { title: String, content: String, imageUrls: [{ type: String }] }; const Post = new mongoose.model("Post", postSchema); И несколько простых изменений в main.js, чтобы добавить текущий идентификатор сообщения для обновления в начало imageSelection, чтобы я мог определить, к какому сообщению добавить изображения в маршруте публикации. addImageButton.addEventListener("click", async () => { const url = "http://localhost:3000/post-images"; if (postValue !== "undefined") { // Unshift post selection to the imageSelection array imageSelection.unshift(postValue); - person Jacob Siler; 20.11.2019
comment
Выше этого в main.js я добавил это, чтобы получать данные из раскрывающегося списка селектора сообщений на моей странице EJS во внешнем интерфейсе. //post selection logic $("#post-dropdown").on("change", function() { postValue = $(this).val(); }); Вот раскрывающийся список сообщений EJS: <!-- The post selection logic --> <hr> <h1>Select a post to add images to:</h1> <select id="post-dropdown" name="post"> <% posts.forEach(function(post){ %> <option value="<%=post.id%>"> <%=post.title%> </option> <% }); %> </select> <hr> - person Jacob Siler; 20.11.2019
comment
@JacobSiler Да, обязательно задайте новый вопрос. Убедитесь, что вы четко объяснили, что пытаетесь сделать. Покажите, каков ожидаемый результат, каков ваш текущий результат, и немного задокументируйте, что вы пытались сделать, чтобы решить проблему. Включите только важные детали проблемы, и только код, который является проблемой. - person DanielSchroederDev; 20.11.2019
comment
Я обязательно сделаю это. Еще раз спасибо за вашу помощь. - person Jacob Siler; 21.11.2019
comment
Я задал новый вопрос здесь: stackoverflow.com/questions/58978242/ - person Jacob Siler; 21.11.2019