Handling js upload files and displayling list of files by vue component.

This commit is contained in:
krzysiej
2022-06-01 14:56:56 +02:00
parent 26bd59f3bb
commit 1a5445a84a
7 changed files with 69 additions and 41 deletions

View File

@@ -30,10 +30,14 @@ export default class extends Controller {
_onChange(event) { _onChange(event) {
// The dropzone just changed // The dropzone just changed
console.info(event);
console.info('onchange'); console.info('onchange');
axios.post(document.URL, new FormData(event.target.closest('form')), {
event.target.closest('form').submit(); headers: {
'Content-Type': 'multipart/form-data'
}
}).then(() => {
event.target.querySelector('.dropzone-preview-button').click()
})
} }

View File

@@ -1,6 +1,5 @@
import Vue from 'vue'; import Vue from 'vue';
import Book from './pages/book' import Book from './pages/book'
import App from "./pages/files";
Vue.component('Book', Book); Vue.component('Book', Book);

View File

@@ -1,5 +1,5 @@
import Vue from 'vue'; import Vue from 'vue';
import App from './pages/files' import Files from "./pages/files";
Vue.component('Files', Files);
new Vue().$mount('#app'); new Vue().$mount('#app');

View File

@@ -1,24 +1,58 @@
<template> <template>
<div> <div>
<h1>Files</h1>
<h1>hello {{ world }}</h1> <div v-if="files.length">
<MessageComponent></MessageComponent> <table class="table">
<thead>
<tr>
<th>Id</th>
<th>File name</th>
<th class="text-end">File size</th>
<th>Extension</th>
<th>Download</th>
<th>Remove</th>
</tr>
</thead>
<tbody>
<tr v-for="file in files">
<td>{{ file.id }}</td>
<td>{{ file.fileName }}</td>
<td class="text-end">{{ formatSize(file.fileSize) }}</td>
<td>{{ file.extension }}</td>
<td><a :href="'/file/'+ file.id" class="link-secondary">download</a></td>
<td><a :href="'/file/delete/'+file.id" class="link-danger">remove</a></td>
</tr>
</tbody>
</table>
</div>
</div> </div>
</template> </template>
<script> <script>
import MessageComponent from "../components/message";
import axios from 'axios'; import axios from 'axios';
export default { export default {
name: 'Files', name: 'Files',
components: {MessageComponent},
data() { data() {
return { return {
world: "świecie 2" files: []
} }
}, },
mounted() { mounted() {
this.getFiles();
},
methods: {
formatSize: function (bytes) {
if (bytes == 0) {
return "0.00 B";
}
var e = Math.floor(Math.log(bytes) / Math.log(1024));
return (bytes / Math.pow(1024, e)).toFixed(2) + ' ' + ' KMGTP'.charAt(e) + 'B';
},
getFiles: function () {
axios.get(document.URL + '/files').then(response => this.files = response.data)
}
} }
} }
</script> </script>

View File

@@ -14,6 +14,7 @@ use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Techtube\Bookinfo\BookFinder; use Techtube\Bookinfo\BookFinder;
#[Route('/book')] #[Route('/book')]
@@ -114,6 +115,13 @@ class BookController extends AbstractController
]); ]);
} }
#[Route('/{id}/files', name: 'app_book_file', methods: ['GET'])]
public function files(Book $book): JsonResponse
{
return $this->json($book->getFiles(), context: [AbstractNormalizer::IGNORED_ATTRIBUTES => ['book']]);
}
#[Route('/{id}/edit', name: 'app_book_edit', methods: ['GET', 'POST'])] #[Route('/{id}/edit', name: 'app_book_edit', methods: ['GET', 'POST'])]
public function edit( public function edit(
Request $request, Request $request,

View File

@@ -20,14 +20,15 @@ class FileType extends AbstractType
[ [
'mapped' => false, 'mapped' => false,
'data_class' => null, 'data_class' => null,
'required' => false, 'required' => true,
'attr' => [ 'attr' => [
'data-controller' => 'mydropzone', 'data-controller' => 'mydropzone',
'accept' => ".pdf, .epub, .mobi", 'accept' => ".pdf, .epub, .mobi",
'placeholder' => 'Drag and drop or browse' 'placeholder' => 'Drag and drop or browse'
] ]
] ]
); )
;
} }
public function configureOptions(OptionsResolver $resolver): void public function configureOptions(OptionsResolver $resolver): void

View File

@@ -34,36 +34,12 @@
</tbody> </tbody>
</table> </table>
<table class="table"> <div id="app">
<thead> <files></files>
<tr> </div>
<th>Id</th>
<th>File name</th>
<th class="text-end">File size</th>
<th>Extension</th>
<th>Download</th>
<th>Remove</th>
</tr>
</thead>
<tbody>
{% for file in book.files %}
<tr>
<td>{{ file.id }}</td>
<td>{{ file.fileName }}</td>
<td class="text-end">{{ file.fileSize | bytes_format }}</td>
<td>{{ file.extension }}</td>
<td><a href="{{ path('app_file_download', {id: file.id }) }}" class="link-secondary">download</a></td>
<td><a href="{{ path('app_file_delete', {id: file.id}) }}" class="link-danger">remove</a></td>
</tr>
{% else %}
<tr>
<td colspan="6">no files found</td>
</tr>
{% endfor %}
</table>
{{ form_start(file_form) }} {{ form_start(file_form) }}
{{ form_widget(file_form) }} {{ form_widget(file_form) }}
<button class="btn btn-primary">{{ button_label|default('Save') }}</button>
{{ form_end(file_form) }} {{ form_end(file_form) }}
<a href="{{ path('app_book_index') }}">back to list</a> <a href="{{ path('app_book_index') }}">back to list</a>
@@ -72,3 +48,9 @@
{{ include('book/_delete_form.html.twig') }} {{ include('book/_delete_form.html.twig') }}
{% endblock %} {% endblock %}
{% block javascripts %}
{{ parent() }}
{{ encore_entry_script_tags('files') }}
{% endblock %}