How show uploaded file in vue-filpond - laravel

i have file pond in my vue template
<file-pond
name="file"
ref="pond"
label-idle="click to upload..."
allowMultiple="true"
:server="uploadSrv"
:files="documents"
/>
This is a form, send this form using Laravel and validate other fields, if failed, i redirect back to this form with old value. One of this old value is added documents list.
User can add files and i see green bar with info about uploaded files. But when i click submit the form and back, cause of error i dont know how to show all uploaded files. Access to this files i have by this.old.documents
export default {
props: ['old', 'errors',],
data() {
return {
documents: [],
uploadSrv: {
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
},
process: {
url: '/file/process',
onload: (response, data) => { return response },
},
};
},
methods: {
},
components: {
FilePond,
},
mounted() {
if (this.old?.documents !== undefined) {
for (var i = 0, len = Object.values(this.old.documents).length; i < len; i++) {
this.documents.push({
source: Object.values(this.old.documents)[i].url,
options: {
type: 'local'
}
})
}
}
}
}
I am not using file preview, just wanna see files list

I did it, i tried to do complicated but way is so simple, just need in controller get documents from database and make array
$abc = Files::where('token', 'gj2trq81hxf177ukl3cs61y7y72uhki5h')->get();
foreach($abc as $f) {
$arr[] = [
'source' => 'https://some_image.jpg',
'options' => [
'type' => 'limbo'
]
];
}
limbo is very important, thats mean your files will be on the list without upload again, if u use local your files will upload again by filepond so u can have double files.

Related

Revert of Filepond is not working on Live server but works on local Server while using laravel

It was all good and working when i was testing my code on local server.
But always when i test the same code on live server it gives errors.
Actually, I am working with Filepond using Laravel and creating a website.
This is Edit Blade Js
<pre>
<script>
// Register the plugin with FilePond
FilePond.registerPlugin(
FilePondPluginMediaPreview,
FilePondPluginImagePreview,
FilePondPluginFileValidateType,
FilePondPluginFileValidateSize,
FilePondPluginFilePoster
);
const inputElement1 = document.querySelector('input[id="card_image_id"]');
const inputElement2 = document.querySelector('input[id="video"]');
const workimages = document.querySelector('input[id="workimages"]');
const pond1 = FilePond.create(inputElement1, {
acceptedFileTypes: ['image/*'],
fileValidateTypeDetectType: true,
maxFileSize: 10000000, //10 mbs max size
allowFileSizeValidation: true,
onaddfilestart: (file) => {
isLoadingCheck();
},
onprocessfile: (files) => {
isLoadingCheck();
},
});
const pond2 = FilePond.create(inputElement2, {
acceptedFileTypes: ['video/*'],
fileValidateTypeDetectType: true,
maxFileSize: 35000000, //35 mbs max size
allowFileSizeValidation: true,
onaddfilestart: (file) => {
isLoadingCheck();
},
onprocessfile: (files) => {
isLoadingCheck();
},
});
const pond3 = FilePond.create(workimages, {
acceptedFileTypes: ['image/*'],
fileValidateTypeDetectType: true,
maxFileSize: 10000000, //10 mbs max size
allowFileSizeValidation: true,
onaddfilestart: (file) => {
isLoadingCheck();
},
onprocessfile: (files) => {
isLoadingCheck();
},
});
FilePond.setOptions({
server: {
process: '/tempupload',
revert: '/tempdelete/{{ $fileid }}',
// fetch: '/tempfetch',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}',
'work_id': '{{ $work->id }}'
},
},
});
</script>
</pre>
This is web routes
<pre>
Route::delete('tempdelete', [WorkController::class, 'tempdelete'])->name('tempdelete');
</pre>
This is controller
<pre>
public function tempdelete()
{
$this->WorkService->tempdelete();
return response()->json(null, 204);
}
</pre>
This is Service
<pre>
public function tempdelete()
{
$work_id = (request()->header('work-id'));
$temporaryfile = TemporaryFile::where('fid', request()->getContent())->first();
if ($temporaryfile) {
$filesexist_in_workimages = Workimage::where([
'size' => $temporaryfile->size,
'name' => $temporaryfile->filename,
'work_id' => $work_id,
])->first();
if (isset($filesexist_in_workimages)) {
if (File::exists($filesexist_in_workimages->folder)) {
File::delete($filesexist_in_workimages->folder);
}
$filesexist_in_workimages->delete();
}
if (isset($temporaryfile->folder)) {
if (File::exists($temporaryfile->folder . $temporaryfile->filename)) {
File::delete($temporaryfile->folder . $temporaryfile->filename);
}
}
$temporaryfile->delete();
}
}
</pre>
The point is that this code works perfectly for deleting a file on local server but shows this error on live server
On Console:
<pre>
DELETE http://brokenclient1.000webhostapp.com/tempdelete net::ERR_EMPTY_RESPONSE
</pre>
On Network:
Failed to load responce, No data found for source with given identifier
When i try to dd on controller or service it does not even works to show dd.
This problem is not connected with FilePond. Are you using Postman or Insomnia to check your API and connection? Check your server settings. Try this solution provided in this link
Laravel Project ERR_EMPTY_RESPONSE
This is typical server error response or sometimes Internet Service Provider error.

Vue Component not showing store data

I am building a trivia maker. I am currently working on the edit page for a question. The edit component, named EditQAForm, grabs the question and answers for that particular question and populates each of it's respective VueX store's form.
I am currently having trouble with the answers portion of this page. When the EditQAForm is mounted it calls the fetchQuestionAnswers, which retrieves all the answers for that particular question. It does this correctly, but then when I try to display any of the answers onto the page, it says that the form is empty despite me seeing in the Vue DevTools that it is not empty.
(Please note I deleted stuff that wasnt relevant to this. So assume all methods you see called do exist)
Here is the mounted for the EditQAForm:
mounted() {
//gets the params from the url
this.routeParams = this.$route.params;
//gets the answers that belong to this question
this.fetchQuestionAnswers(this.routeParams.question_id);
//not important for this problem
//get the question that needs to be edited
this.fetchQuestion(this.routeParams.question_id);
},
How I call it in the computed properties of the EditQAForm:
computed: {
...mapGetters('question', ['formQuestionRoundID', 'questions', 'questionFields']),
...mapGetters('answer', ['answerFields', 'answers']),
//Questions
questionForm: {
get() {
return this.questionFields;
},
},
//Answers
answerForm: {
get() {
return this.answerFields;
},
},
}
Here is the store for the answers
function initialState() {
return {
answers: [],
answer: null,
form: [
{
id: '',
title: '',
question_id: '',
round_id: '',
correct: false,
},
{
id: '',
title: '',
question_id: '',
round_id: '',
correct: false,
},
{
id: '',
title: '',
question_id: '',
round_id: '',
correct: false,
},
]
}
}
const getters = {
answers(state){
return state.answers;
},
answerFields(state){
return state.form;
},
loading(state){
return state.loading;
},
};
const actions = {
fetchQuestionAnswers({ commit, state }, question_id) {
console.log("Form outside axios:");
console.log(state.form);
commit('setLoading', true);
axios.get('/api/question/' + question_id + '/answers')
.then(response => {
commit('SET_ANSWERS_FORM', response.data);
commit('setLoading', false);
}).catch( error => {
console.log(error.response);
});
},
const mutations = {
SET_ANSWERS_FORM(state, answers){
for(let $i = 0; $i < answers.length; $i++)
{
state.form[$i] = {
id: answers[$i].id,
title: answers[$i].title,
question_id: answers[$i].question_id,
round_id: answers[$i].round_id,
correct: answers[$i].correct,
}
}
// state.answers = answers;
},
UPDATE_TITLE(state, payload){
state.form[payload.order].title = payload.title;
},
UPDATE_QUESTION_ID(state,payload){
state.form[payload.order].question_id = payload.questionID;
},
};
What I try outputting:
<div>
<h3 class="pb-3">Is first answer's title not empty?: {{!(answerForm[1].title === '')}}</h3>
<h3 class="pb-3">{{answerForm[0].title }}</h3>
<h3>{{answerForm}}</h3>
</div>
What shows on my screen, alongside what devtools tells me is inside the answerForm array:
I implemented the question portion in a very similar way. The only difference is that the form is not an array in the question store, but besides that it works fine. What am i doing wrong?
I think the problem is here:
state.form[$i] = {
If you use an index to update an array it won't trigger the reactivity system and you'll get a stale version of the rendered components. See https://v2.vuejs.org/v2/guide/list.html#Caveats
There are various ways to fix this. You could use Vue.set or alternatively just create am entirely new array.
Not entirely clear to me why you're doing all that copying in the first place rather than just using state.form = answers, which would also solve the problem.

return data object to vue component using laravel 5.6 and axios

I am trying to build an availability carousel. It will show the days of the week, and what time someone is available. I am using Laravel and vue.js. I have done the web api, and I can get the data object following the route
Route::group(['prefix' => '/{area}'], function () {
Route::get('/{tutor}/availability','Tutor\AvailabilityController#show');
});
with this in my availability controller
public function show(Request $request, Area $area, Tutor $tutor)
{
$availability = $tutor->availability()->get();
return response()->json([
'data' => $availability
], 200);
}
That all works.
But when I try and pull it into Vue, nothing shows up. I can't seem to figure out what I might be missing.
I pulled the vue component into blade using the following, and passing in the area and tutor id
<availability area-id="{{ $area->slug }}" tutor-id="{{ $tutor->slug }}">
</availability>
and in Availability.vue, I think where I am going wrong is pulling the data in with props, but I am really not sure anymore.
<script>
$(document).ready(function() {
$("#availability").owlCarousel();
});
export default {
props: {
areaId: null,
tutorId: null
},
data () {
return {
availability: []
}
},
methods: {
getAvailability () {
axios.get( '/' + this.areaId + '/' + this.tutorId + '/availability').then((response) => {
console.log(response.json());
});
}
},
ready () {
this.getAvailability();
}
}
</script>
Thank you for the help.
Axios response object has data field which contains the response from the server. To get the data use
response.data
Also for Vue 2.0 components use mounted instead of ready for when the component is ready. If you are only loading data from the server (and not manipulating the DOM) you can use created instead.
export default {
props: {
areaId: null,
tutorId: null
},
data () {
return {
availability: []
}
},
methods: {
getAvailability () {
var that = this;
axios.get( '/' + this.areaId + '/' + this.tutorId + '/availability')
.then((response) => {
console.log(response.data); // should print {data: availability_object}
// Set this component's availability to response's availability
that.availability = response.data.data;
//OR
//Add response's availability to the components' availability
that.availability.push(response.data.data);
});
}
},
mounted () {
this.getAvailability();
}
}
</script>

Vue.js 2 & Axios - Filtering an api for a search feature

I'm trying to filter through a collection of films that i'm retrieving using axios. This is so i can compare it to a search string for a search feature. Everything works fine except when using the computed property it returns Cannot read property 'filter' of undefined" but when i check the vue dev tool it says that the computed property contains the array of films which doesn't really add up. The code is as follows.
created(){
this.fetchFilms();
},
methods:{
fetchFilms(page_url){
let vm = this;
// storing the page url
page_url = page_url || '/api/films'
axios.get(page_url)
.then(response => response)
.then(response => {
this.films = response.data;
vm.makePagination(response.meta, response.links);
})
.catch(err => console.log(err));
},
makePagination(meta,links){
let pagination = {
current_page: this.films.meta.current_page,
last_page: this.films.meta.last_page,
next_page_url: this.films.links.next,
prev_page_url: this.films.links.prev
}
this.pagination = pagination;
}
},
computed: {
filteredFilms () {
return this.films.data.filter((film) => {
return film.film_name.toLowerCase().match(this.searchString.toLowerCase())
})
},
}
This is how the data is returned
films:Object
data:Array[10]
links:Object
meta:Object
Any help is appreciated.
You're probably accessing filteredFilms before the request is done. I don't see any code to wait for the request. You could make filteredFilms check if the data is there and return an empty list if it isn't.

Vue.js Retrieving Remote Data for Options in Select2

I'm working on a project that is using Vue.js and Vue Router as the frontend javascript framework that will need to use a select box of users many places throughout the app. I would like to use select2 for the select box. To try to make my code the cleanest I can, I've implemented a custom filter to format the data the way select2 will accept it, and then I've implemented a custom directive similar to the one found on the Vue.js website.
When the app starts up, it queries the api for the list of users and then stores the list for later use. I can then reference the users list throughout the rest of the application and from any route without querying the backend again. I can successfully retrieve the list of users, pass it through the user list filter to format it the way that select2 wants, and then create a select2 with the list of users set as the options.
But this works only if the route that has the select2 is not the first page to load with the app. For example, if I got to the Home page (without any select2 list of users) and then go to the Users page (with a select2), it works great. But if I go directly to the Users page, the select2 will not have any options. I imagine this is because as Vue is loading up, it sends a GET request back to the server for the list of users and before it gets a response back, it will continues with its async execution and creates the select2 without any options, but then once the list of users comes back from the server, Vue doesn't know how to update the select2 with the list of options.
Here is my question: How can I retrieve the options from an AJAX call (which should be made only once for the entire app, no matter how many times a user select box is shown) and then load them into the select2 even if the one goes directly to the page with the select2 on it?
Thank you in advance! If you notice anything else I should be doing, please tell me as I would like this code to use best practices.
Here is what I have so far:
Simplified app.js
var App = Vue.extend({
ready: function() {
this.fetchUsers();
},
data: function() {
return {
globals: {
users: {
data: []
},
}
};
},
methods: {
fetchUsers: function() {
this.$http.get('./api/v1/users/list', function(data, status, response) {
this.globals.users = data;
});
},
}
});
Sample response from API
{
"data": [
{
"id": 1,
"first_name": "John",
"last_name": "Smith",
"active": 1
},
{
"id": 2,
"first_name": "Emily",
"last_name": "Johnson",
"active": 1
}
]
}
User List Filter
Vue.filter('userList', function (users) {
if (users.length == 0) {
return [];
}
var userList = [
{
text : "Active Users",
children : [
// { id : 0, text : "Item One" }, // example
]
},
{
text : "Inactive Users",
children : []
}
];
$.each( users, function( key, user ) {
var option = { id : user.id, text : user.first_name + ' ' + user.last_name };
if (user.active == 1) {
userList[0].children.push(option);
}
else {
userList[1].children.push(option);
}
});
return userList;
});
Custom Select2 Directive (Similar to this)
Vue.directive('select', {
twoWay: true,
bind: function () {
},
update: function (value) {
var optionsData
// retrive the value of the options attribute
var optionsExpression = this.el.getAttribute('options')
if (optionsExpression) {
// if the value is present, evaluate the dynamic data
// using vm.$eval here so that it supports filters too
optionsData = this.vm.$eval(optionsExpression)
}
var self = this
var select2 = $(this.el)
.select2({
data: optionsData
})
.on('change', function () {
// sync the data to the vm on change.
// `self` is the directive instance
// `this` points to the <select> element
self.set(select2.val());
console.log('emitting "select2-change"');
self.vm.$emit('select2-change');
})
// sync vm data change to select2
$(this.el).val(value).trigger('change')
},
unbind: function () {
// don't forget to teardown listeners and stuff.
$(this.el).off().select2('destroy')
}
})
Sample Implementation of Select2 From Template
<select
multiple="multiple"
style="width: 100%"
v-select="criteria.user_ids"
options="globals.users.data | userList"
>
</select>
I may have found something that works alright, although I'm not sure it's the best way to go about it. Here is my updated code:
Implementation of Select2 From Template
<select
multiple="multiple"
style="width: 100%"
v-select="criteria.reporting_type_ids"
options="globals.types.data | typeList 'reporttoauthorities'"
class="select2-users"
>
</select>
Excerpt from app.js
fetchUsers: function() {
this.$http.get('./api/v1/users/list', function(data, status, response) {
this.globals.users = data;
this.$nextTick(function () {
var optionsData = this.$eval('globals.users.data | userList');
console.log('optionsData', optionsData);
$('.select2-users').select2({
data: optionsData
});
});
});
},
This way works for me, but it still kinda feels hackish. If anybody has any other advice on how to do this, I would greatly appreciate it!
Thanks but I'm working on company legacy project, due to low version of select2, I encountered this issue. And I am not sure about the v-select syntax is from vue standard or not(maybe from the vue-select libaray?). So here's my implementation based on yours. Using input tag instead of select tag, and v-model for v-select. It works like a charm, thanks again #bakerstreetsystems
<input type="text"
multiple="multiple"
style="width: 300px"
v-model="supplier_id"
options="suppliers"
id="select2-suppliers"
>
</input>
<script>
$('#app').ready(function() {
var app = new Vue({
el: "#app",
data: {
supplier_id: '<%= #supplier_id %>', // We are using server rendering(ruby on rails)
suppliers: [],
},
ready: function() {
this.fetchSuppliers();
},
methods: {
fetchSuppliers: function() {
var self = this;
$.ajax({
url: '/admin_sales/suppliers',
method: 'GET',
success: function(res) {
self.suppliers = res.data;
self.$nextTick(function () {
var optionsData = self.suppliers;
$('#select2-suppliers').select2({
placeholder: "Select a supplier",
allowClear: true,
data: optionsData,
});
});
}
});
},
},
});
})
</script>

Resources