#javascript #jquery #dropzone.js #dropzone
Вопрос:
Я пишу веб-приложение, в котором мне нужно инициализировать несколько зон доступа на основе содержимого сервера, в настоящее время у меня есть код, аналогичный этому:
<script src="/js/dropzone.min.js"></script>
<script>
Dropzone.autoDiscover = false;
window.dropzones = {};
function checkDropzones(container) {
var possibleDropzones = container.querySelectorAll('.needs-to-be-dropzoned');
possibleDropzones.forEach(function (zone) {
if (zone.id.length === 0) {
zone.id = 'dropzone_filled_' (new Date()).getTime();
window.dropzones[zone.id] = new Dropzone(
'#' zone.id,
{
paramName: 'image',
addRemoveLinks: true,
}
);
}
})
}
function renderServerContent() {
window.customSections.forEach(function (custom_section) {
var container = document.getElementById(custom_section);
$.ajax({
method: 'GET',
url: '/customRenderUrl?section=' custom_section,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
success: function (response) {
container.innerHTML = container.innerHTML response.component;
if (response.component_type === 'image_uploader') {
checkDropzones(container);
}
// ... other marginal stuff ...
},
dataType: 'json'
})
})
}
// ... other scripts ...
window.customSections = [/* server stuff */];
renderServerContent();
</script>
В принципе, у меня есть некоторые вещи, которые будут отображаться динамически с сервера, поэтому я отправляю запрос на компонент предоставляемых данных, и когда я получаю ответ обратно, я проверю, если вставлять контент содержит элемент .needs-to-be-dropzoned
, если да, то назначить ему время,-на основании удостоверения личности (компонент рендеринга имеет задержку между каждым компонентом, так что идентификаторы уникальны) и, например, зоны для перемещения. Это хорошо работает только с одной зоной выпадения, но когда несколько находятся на одной странице, это не приведет к ошибкам, а будет работать только для последнего элемента на странице.
Содержимое сервера выглядит примерно так:
<form
class="col-12 container-fluid pb-2 dropzone needs-to-be-dropzoned"
method="POST"
action="/imageUploadUrl"
>
<input type="hidden" name="_token" value="..." >
<div class="dz-default dz-message">
Upload files
</div>
<div class="fallback">
<input name=image" type="file" />
</div>
</form>
Если я запущу a console.dir(window.dropzones)
, я получу 2 объекта:
Object { dropzone_filled_1624370363574: {…}, dropzone_filled_1624370363803: {…} }
dropzone_filled_1624370363574: Object { element: form#dropzone_filled_1624370363574.col-12.container-fluid.pb-2.dropzone.needs-to-be-dropzoned.dz-clickable, version: "5.9.2", clickableElements: (1) […], … }
dropzone_filled_1624370363803: Object { element: form#dropzone_filled_1624370363803.col-12.container-fluid.pb-2.dropzone.needs-to-be-dropzoned.dz-clickable, version: "5.9.2", clickableElements: (1) […], … }
Что я делаю не так или упускаю?
Комментарии:
1. » Я присваиваю ему случайный идентификатор » —
'dropzone_filled_' (new Date()).getTime()
это не случайно. Какую отладку вы пробовали? Вы проверили, действительно ли ваши идентификаторы отличаются при создании? Какwindow.dropzones
выглядит, например, чтоconsole.dir(window.dropzones);
показывает?2. Да, извините, я не имел в виду случайность строго, я имел в виду случайность, потому что формы не имеют идентификатора перед его назначением, кстати, между рендерингом каждого компонента есть небольшая задержка, поэтому
getTime
они будут назначать разные идентификаторы.window.dropzones
Содержит различные объекты dropzones, я исправлю вопрос3. Как я уже сказал, dropzones, похоже, работают,
window.dropzones
содержит два объекта dropzone, но работает только последний инициализированный4. Странный. Мне удалось заставить ваш код работать в JSFiddle . Созданы 2 выпадающие зоны, и обе работают. Единственные изменения, которые я внес, связаны с подделкой вызова AJAX на JSFiddle, используя их специальный /echo/json/ URL -адрес, и подделкой ответа сервера, который, предположительно, выглядит как ваш. Посмотрите, может быть, что-то выскочит на вас, но пока я в тупике!
Ответ №1:
Я предпринимал различные попытки исправить это, и, наконец, исправил это, завернув все вызовы сервера в обещания, дождался решения всех обещаний и только после этого проверил наличие выпадающих зон. Код примерно такой:
<script src="/js/dropzone.min.js"></script>
<script>
Dropzone.autoDiscover = false;
window.dropzones = {};
window.containersToCheck = [];
function checkDropzones(container) {
var possibleDropzones = container.querySelectorAll('.needs-to-be-dropzoned');
possibleDropzones.forEach(function (zone) {
if (zone.id.length === 0) {
zone.id = 'dropzone_filled_' (new Date()).getTime();
window.dropzones[zone.id] = new Dropzone(
'#' zone.id,
{
paramName: 'image',
addRemoveLinks: true,
}
);
}
})
}
function renderServerContent() {
return new Promise(function(resolve, reject) {
window.customSections.forEach(function (custom_section) {
var container = document.getElementById(custom_section);
$.ajax({
method: 'GET',
url: '/customRenderUrl?section=' custom_section,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
success: function (response) {
container.innerHTML = container.innerHTML response.component;
if (response.component_type === 'image_uploader') {
window.containersToCheck.push(container);
}
resolve();
// ... other marginal stuff ...
},
dataType: 'json'
})
})
});
}
// ... other scripts ...
window.customSections = [/* server stuff */];
var promises = [];
promises.push(renderServerContent());
// other renderings
Promise.all(promises).then(function (results) {
window.containersToCheck.forEach(function(container) {
checkDropzones(container);
});
})
</script>
Таким образом, все зоны выпадения работают.