vue axios post how to submit formdata array? - vue.js

I need to submit an ARRAY data because the backend can only recognize such data
Expected effect:
&row[weigh]=0
&row[status]=normal
code:
row:{
weigh: 0,
status: 'normal'
}
actual effect:
row:{
weigh: 0,
status: 'normal'
}
When I submit the data, the console displays JSON instead of Array, but the backend cannot get it
What I need is to be consistent with the results from the form submission below
<form method="POST" >
<input name="row[a]" type="text" value="">
<input name="row[b]" type="text" value="">

public register(rowObject: RowObject): AxiosPromise<any> {
return axios.post('http://localhost/api/register', rowObject);
}
This way you can pass the data in Post method.
rowObject = {
weigh: 0,
status: 'normal'
}

Try this code.
let row = {
weigh: 0,
status: 'normal'
};
let finalArr = [];
Object.keys(row).forEach((key) => {
finalArr.push(`row[${key}]=` + row[key]);
});
console.log(finalArr.join('&'));
// outputs: row[weigh]=0&row[status]=normal

Your code also should pass an array just like this.
data = [
{weigh: 0},
{status: 'normal'}
]
then when you send it to server for example using axios, your code should look like this
axios.post('/api endpoint', {row:data})
.then(response => {
// response here
});

ok
const formData = new FormData()
Object.keys(this.form).forEach(e => {
formData.append(`row[${e}]`, this.form[e])
})

Related

Cancel a previous axios request on new request in Vue Js

I am trying to implement a search which loads user data from the backend on every word change using #input and populate in datalist, now for every change a new request is generated while the old request is still processing/pending this causes some problems. I am looking to cancel old request on every new request that will take place.
Html code in vue js
<input type="text" class="form-control" placeholder="Search Name" v-model="forms.name" list="getname" #input="inputData()" required> <datalist id="getInput" > <option v-for="option in options">{{option}}</option> </datalist>
Function to load data
axios.get('Url/GetUser/'+ this.forms.name).then((response) => {if(response.data.error){ this.errorNya = response.data; this.loading2 = false;}else{ this.errorNya.username = ""; this.options = response.data; this.loading2= false; this.disableButton = true; }
I have referred the documentation and other sources for this question, and i found a solution which suited me best.
this.cancelFunc();
//Below line creates a cancel token for this request
let axiosSource = axios.CancelToken.source();
this.request = { cancel: axiosSource.cancel };
//then we pass the token to the request we want to cancel.
axios.get('/Url/GetUser/'+ this.forms.username, {cancelToken: axiosSource.token,}).then((response) => {
if (response.data.error) {
this.errorNya = response.data;
this.loading2 = false;
} else {
this.errorNya.username = "";
this.options = response.data;
this.loading2 = false;
this.disableButton = true;
}
},
cancelFunc() {
if (this.request)
this.request.cancel();
},
i know this will not be the best way to do this, but this solved my problem.

Updating the image in laravel 8 + inertia, validation error even the fields are filled

I'm working with Laravel 8 + inertiajs. I can create a product with or without an image. But when I try to update a product and upload a new image, the validation looks for the required field even they're already filled.
here is my input field:
<input name="images" type="file" #input="form.images = $event.target.files[0]" />
in my vue:
props: {
product: Object,
categories: Array
},
data() {
return {
form: this.$inertia.form({
name: this.product.name,
category_id: this.product.category_id,
description: this.product.description,
date: this.product.date,
images: this.product.images
})
}
},
methods: {
update() {
this.form.put(this.route('products.update', this.product.id, {
preserveState: true
}))
},
}
})
my update controller:
public function update(UpdateProductRequest $request, Product $product)
{
$inputs = $request->validated();
if ($request->hasFile('images')) {
$filename = $request->images->getClientOriginalName();
$file = $request->images->storeAs(('images'), $filename);
$product->images = $file;
$inputs['images'] = $product->images;
}
$product->name = $inputs['name'];
$product->category_id = $inputs['category_id'];
$product->description = $inputs['description'];
$product->date = $inputs['date'];
$product->update();
session()->flash('flash.banner', 'Product Updated Successfuly');
session()->flash('flash.bannerStyle', 'success');
return redirect()->route('products.index');
}
multipart/form-data request is not natively supported in some languages for the put,patch or delete methods. The workaround here is to simply upload files using post instead.
Some frameworks, such as Laravel and Rails, support form method spoofing, which allows you to upload the files using post, but have the framework handle the request as a put or patch request. This is done by including a _method attribute in the data of your request.
Inertia.post(`/users/${user.id}`, {
_method: 'put',
avatar: form.avatar,
})

Unable to put value using :value wiht v-model together in VueJS 2

In a page i am fetcing data from API and showing the data in the text field. After that user can change the data and submit the form. I am uanble to show data using :value in the inout field. Its showing conflicts with v-model on the same element because the latter already expands to a value binding internally
I tried to mount the data after it loads. But it is still not showing.
<input v-model="password" :value="credentials.password">
created() {
let txid = this.$route.params.id
this.$axios.get(this.$axios.defaults.baseURL+'/v1/purno/internal/users/'+ txid, {
}).then((response) => {
if (response.data.status == 'error') {
toast.$toast.error('Something Went Wrong at!', {
// override the global option
position: 'top'
})
} else if (response.data.status == 'success') {
if(response.data.data.found ==true) {
this.credentials = response.data.data;
})
}
}
})
});
},
data(){
return {
credentials:[],
password:null
}
},
mounted(){
this.password = this.credentials.password
}
How can i solve this problem? Thanks in advance
Please complete it within the request callback
this.credentials = response.data.data;
this.password = this.credentials.password;
like this in the then callback fn. Try it!
conflicts with v-model on the same element because the latter already expands to a value binding internally error message tells it all
v-model="password" is same as :value="password" #input="password = $event.target.value" (for text and textarea - see here)
So using it together with another :value makes no sense...

Download after completing the request - vue-json-excel

I'm using the vue-json-excel library that helps me download data from a json.
where in the view of the vue I have:
<div class="column is-narrow" #click="btDispatch">
<json-excel
class = "button is-primary"
:data = "routes"
:fields = "json_fields_routes"
:name = "`descarga-rutas.xls`">
<span class="icon"><i class="fa fa-download"></i></span><span>Descargar entregas</span>
</json-excel>
Where:data = "routes" is the json that will be downloaded:
data () {
return {
json_fields_routes: {
ruta_id: 'id',
fecha: 'date',
estado_codigo: 'route_state',
estado: 'estado',
vehĂ­culo: 'vehicle',
conductor_codigo: 'worker.id',
conductor_nombre: 'worker.name',
hora_inicio: 'date_start_web',
hora_fin: 'date_end_web',
entregas: 'dispatches_count',
pendientes: 'pendientes',
entregados: 'entregados',
parciales: 'parciales',
no_entregados: 'noEntregados',
},
json_meta: [
[
{
key: 'charset',
value: 'utf-8',
},
],
],
}
}
According to the documentation, I must do this to download Excel and it works correctly. The problem I have is that it is downloaded when there is existing data, but I am working with data that comes from the server and previously loaded the data in the load () but it takes a long time when there is a large amount of data to enter that section of the page, so I prefer that the download button compile the data and then download.
So far I have:
methods: {
btRoute() {
this.axios.post('/routesdownload/filter_route/', this.params)
.then((response) => {
this.routes = response.data.results;
for (let i = 0; i < this.routes.length; i++) {
this.routes[i].pendientes = this.filterByStatus(this.routes[i].dispatches, 1);
this.routes[i].entregados = this.filterByStatus(this.routes[i].dispatches, 2);
this.routes[i].parciales = this.filterByStatus(this.routes[i].dispatches, 3);
this.routes[i].noEntregados = this.filterByStatus(this.routes[i].dispatches, 4);
this.routes[i].date = moment(this.routes[i].date).format('YYYY/MM/DD');
if (this.routes[i].date_start_web && this.routes[i].date_end_web != null) {
this.routes[i].date_start_web
= moment(this.routes[i].date_start_web).format('YYYY/MM/DD HH:mm:ss');
this.routes[i].date_end_web
= moment(this.routes[i].date_end_web).format('YYYY/MM/DD HH:mm:ss');
} else {
this.routes[i].date_start_web = '-';
this.routes[i].date_end_web = '-';
}
if (this.routes[i].route_state === 1) {
this.routes[i].estado = 'Borrador';
} else if (this.routes[i].route_state === 2) {
this.routes[i].estado = 'Publicado';
} else if (this.routes[i].route_state === 3) {
this.routes[i].estado = 'Iniciado';
} else {
this.routes[i].estado = 'Terminado';
}
}
});
},
}
But this simply brings the data and the weapon according to the need, but how could you after completing the application, call the function you download with this library? I could do it with a callback or a promise, but how can I call that download function?
I suposed it's a little late response, but the new version of vue-json-excel support a callback prop to fetch data before download the file.
<json-excel
class = "button is-primary"
fetch = "MyCallbackFetchData"
:fields = "json_fields_routes">
Descargar Archivo
</json-excel>
The callback can run with the async...await option so you can use asyncrounous calls like:
methods:{
async MyCallbackFetchData(){
return await axios.get('myapiurl');
}
}
IMPORTANT: This option only works when the prop data it's undefined. If data it's defined then the file it's generate with that information.
Well, apparently, the library does not have that functionality.
then to the component I put a ref:
<json-excel
ref="droute"
class = "button is-primary"
:data = "routes"
:fields = "json_fields_routes"
:name = "`descarga-rutas.xls`">
<span class="icon"><i class="fa fa-download"></i></span><span>Descargar entregas</span>
</json-excel>
and when the promise ends(has the data loaded):
this.$refs.droute.$el.click();
I call the component and download.
In my case, i'm using two button, one for load data and one for donwload. and also its much easier to implement

Displaying Bookshelf.js model in hbs view

I'm new to Bookshelf.js and hbs and would appreciate your help with the following:
I want to pre-fill a handlebars.js view form with data from a Bookshelf.js model.
hbs won't let me use the Bookshelf get method to get the desired attribute value: e.g. {{user.get(age)}}
I converted the model to JSON but am not able to query a specific json attribute in hbs e.g. {{user.age}}.
JSON
{"id":1,"fullName":"Mike","password":"password","email":"mike#email.com","age":38,"gender":"male","created_at":1432736718951,"updated_at":1432736718951}
Do I have to create a helper to extract the attribute value from the model?
function getUserModel(req, res, next) {
User.forge({id: req.user})
.fetch()
.then(function(user){
req.model = user;
return next()
})
.catch(function(err){
debug("Error loading userId[%s]", req.user);
return next(err);
});
}
router.use(ensureAuthenticated)
.use(getUserModel);
router.get('/', function handlePhotoUploadGet(req, res, next) {
var callback = "http://" + req.headers.host + "/cloudinary_cors.html";
var params = {return_delete_token: true, callback: callback,
timestamp: cloudinary.utils.timestamp()};
var dataFormData = cloudinary.utils.sign_request(params);
res.render('photos/upload',
{ title: 'Photo upload',
cloudinary: cloudinary,
dataFormData: JSON.stringify(dataFormData),
user: req.model }
);
});
<input type="text" name="age" aria-label="age" value="{{user.age}}" placeholder="age" class="radius {{#if errors.invalidAttributes.fullName}}error{{/if}}" />
<input type="radio" name="gender" value="male" aria-label="Male" id="male" {{#if_equal user.gender 'male'}}checked{{/if_equal}}><label for="male">Male</label>
In order to answer this question you need to provide the server-side code, to see what you push to response, and client side html as well. Please update your question.
Update:
Change this line:
req.model = user; to this: req.model = user.toJSON();