How to send array without "[]" using jQuery $.ajax? - ajax

If a html form has multiple inputs with the same name, a Servlet will understand it as Array:
Form:
<form>
User 1:<input name="user" />
User 2:<input name="user" />
User 3:<input name="user" />
<input type="submit" />
</form>
Servlet:
String[] user = request.getParameterValues("user");
But if I use jQuery to make an ajax call, and send a array as a parameter, it adds "[]" in the property name
Javascript:
$.ajax({
...
data:{
user: ["value1", "value2", "value3"]
}
});
Inspecting the header of the request, the data were sent:
Form Data
user[]=value1&user[]=value2&user[]=value3
I know I can add [] at the end of parameter of getParameterValues, but I prefer that jQuery does not send the []
How can I do this?

You need to set the traditional option to true if you wish to use the traditional style of param serialization:
$.ajax({
...
data:{
user: ["value1", "value2", "value3"]
},
traditional: true
});
Using this your request will look like:
user=value1&user=value2&user=value3

Related

Upload image in strapi repeatable components

I have user_feedback in repeatable component in user table, how can I upload image to the newly added user feedback in strapi v3.
What currently I am doing
const data = await strapi.services["users"].update(
{ id: id },
{
...updatedData,
}
);
const newFeedback =
data.feedback_prototype_phase[data.feedback_prototype_phase.length - 1];
await strapi.entityService.uploadFiles(data, files, {
id: data.id,
model: "user.user_feedback",
field: "image",
});
Edited this answer, Its best to
Upload the image to Media-Folder, via http://localhost:1337/api/upload
Then use the same URL http://localhost:1337/api/upload and include this in your request as the doc says in https://docs.strapi.io/developer-docs/latest/plugins/upload.html#examples
<form>
<!-- Can be multiple files if you setup "collection" instead of "model" -->
<input type="file" name="files" />
<input type="text" name="ref" value="api::restaurant.restaurant" />
<input type="text" name="refId" value="5c126648c7415f0c0ef1bccd" />
<input type="text" name="field" value="cover" />
<input type="submit" value="Submit" />
</form>
<script type="text/javascript">
const form = document.querySelector('form');
form.addEventListener('submit', async (e) => {
e.preventDefault();
await fetch('/api/upload', {
method: 'post',
body: new FormData(e.target)
});
});
</script>```
Your ref-id will be the ID of your entry, by entry It means the ID of your table's row or in no-sql you would say your document id.
Your ref is your service name as it suggests, your table name per say
Your field is the name of the field of the entry you want to upload the media too
Your files is simple the files that you want to upload
I would highly recommend you to use the template code given on docs then modify it, Instead of working on it directly. Thats what I did.

I can't send file through an ajax PUT request, using Laravel

I have a form with an input of type file hidden. An image tag works as the clickable trigger to select the file itself, with js to trigger it (that works), but I want to automatically make a PUT request as one chooses an image instead of having to click a submit button on the form, every time the image is changed on the input field. I'm using ajax for that, but at the controller endpoint that processes the request, I don't seem to have any file. If I put other fields such as textual they seem to pass into the controller through the request just fine, though.
My route:
Route::put('/coins/image/{key}', [CoinController::class, 'image'])->name("coins.image");
My controller (no actual image-updating code yet; just what I'm doing to check for the file):
public function image(int $key)
{
dump(request()->file('file'));
dump(request()->file);
dump(request());
}
My HTML and JS in the following snippet:
function promptImageForUpload(elemId)
{
$('#' + elemId).click();
}
function uploadImage(event, imgId, key)
{
event.preventDefault();
var inputElem = event.target;
var imageFile = inputElem.files[0];
var imgElem = $('#' + imgId);
var form = $(inputElem).parent();
var formData = new FormData(form[0]);
formData.append('file', imageFile);
$.ajax({
url: "/coins/image/" + key,
type: "PUT",
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
data: formData,
enctype: 'multipart/form-data',
processData: false,
contentType: false,
success: function(response) {
var reader = new FileReader();
reader.onload = function(e) {
imgElem.attr("src", e.target.result);
};
reader.readAsDataURL(imageFile); // convert to base64 string
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="card-body">
<form data-key="0" id="coin-header-0_form" method="POST" action="#" enctype="multipart/form-data">
<input type="file" name="file" id="coin-header-0_file" style="z-index:-1; width: 100%; height: 100%; display: none;" onchange="uploadImage(event, 'coin-header-0_preview', 0)">
<input type="hidden" name="_method" value="PUT">
<meta name="csrf-token" content="7c3s2NmosdK9qzrS10xGAB0rYXw5g41azRjcmPQC">
<img src="http://snapbuilder.com/code_snippet_generator/image_placeholder_generator/60x40/007730/DDDDDD/this%20pict" width="50px" height="50px" alt="icon" id="coin-header-0_preview" onclick="promptImageForUpload('coin-header-0_file');">
</form>
</div>
For now, I am force-updating the preview of the image on the ajax success instead of retrieving it from the updated entity upon successful update, to avoid a second query.
I have the method set to PUT for spoofing in the ajax request and the xsrf token set the headers as well.
Enctype is set to multipart/form-data for files too. I have no clue as to why I don't see the uploaded file anywhere in the request.
Using Laravel Framework 8.25.0, jquery 3.5.1.
Please let me know if any more info is needed, anyone.
I couldn't find any solution on any stackoverflow entry or elsewhere that regards this subject.
Any help is greatly appreciated since I don't really how else to look at this in a debugging approach.
HTML forms do not support PUT, PATCH or DELETE actions. So, when defining PUT, PATCH or DELETE routes that are called from an HTML form, you will need to add a hidden _method field to the form. The value sent with the _method field will be used as the HTTP request method:
<form action="/foo/bar" method="POST">
<input type="hidden" name="_method" value="PUT">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>
You may use the method_field helper to generate the _method input:
{{ method_field('PUT') }}
In the same way, this check may also affect ajax forms. Then in your form switch to the POST method and set the PUT parameter for it to work.

Why is my data being appended to my url after editing an item?

I'm building a simple recipe collections app, and I'm running into a really weird scenario where when I edit a recipe item, the new data gets appended to my localhost:3000/ url. For example my original recipe item data was:
"Title: test",
"Ingredients: test",
"Cooking Directions: test"
But then after I edited the data, the new data also appended to my localhost:3000/ url. data appended to localhost url screenshot. My goal is not append this data to my url and stay at localhost:3000. Thanks and any help would be appreciated.
Here is my put request code:
updateRecipe = (e) => {
console.log(this.props.uniqueID);
const recipe = {
title: this.state.title,
ingredients: this.state.ingredients,
summary: this.state.summary
}
const url = `http://localhost:5000/recipes/${this.props.uniqueID}`;
axios.put(url, recipe)
.then(res => this.setState({
recipes: [...this.state.recipes, res.data],
},
() => console.log('recipe edited: ', res.data)
));
}
<form className="form-container" onSubmit={this.updateRecipe}>
<TextField
style={inputStyle}
className="form-input-title"
type="text"
onChange={this.onChangeHandler}
name="title"
id="standard-basic"
label="Title"
value={this.state.title}
/>
<TextField
style={inputStyle}
className="form-input-ingredients"
type="text"
onChange={this.onChangeHandler}
name="ingredients"
id="standard-basic"
label="Ingredients"
value={this.state.ingredients}
/>
<TextField
id="outlined-multiline-static"
label="Directions"
multiline
rows={6}
variant="outlined"
onChange={this.onChangeHandler}
name="summary"
className="form-input-directions"
style={inputStyle}
value={this.state.summary}
/>
<Fab style={style} className="add-recipe-button" color="primary" aria-label="add" type="submit">
<AddIcon />
</Fab>
</form>
This is the default behaviour if you use onSubmit handler for form.If this is not what you are looking for dont use onSubmit handler on the form instead use onClick handler for the submit button to call for updateRecipe functionality.Then Url is not modified.

Make AJAX Request on Blur for single Input

I'm pretty new to Angular and having a form like this (about 15 Inputs and Selects):
<div id="configForm" data-ng-controller="seutpController">
<form name="configForm" data-ng-submit="update()" novalidate>
<input id="id" type="hidden" data-ng-model="config.id" />
<input id="company" type="text" data-ng-model="config.company" data-ng-blur="test()"/>
<input id="street" type="text" data-ng-model="config.street" data-ng-blur="test()" />
</form>
<input type="submit" />
</div>
What's already working:
Making an AJAX Call on Submit which updates the Database with all values from the config object. No big Deal.
What I'd like to do:
Making an AJAX Call (on Blur), but I'd like to send only the one key/value pair which was changed by the user like:
$http({
url: 'api/setConfig.php',
method: 'POST',
data: {'company': 'value'}
})
Do I have to send $event as function param like ng-blur="test($event)" and get the Elements Id and Value from there?
Thanks # all!
Edit
Is it a possible option using $watchCollection and watching on the $scope.config object?
I would say it's probably best to send the $event, since that would be the most extendable solution. I've done something similar in the past:
<input name="title" ng-blur="ctrl.onFieldChanged($event)" type="text" ng-model="ctrl.title"/>
In my method, I named the input the same name as the ng-model its bound to, just for convenience. In the controller, here's what I do:
this.onFieldChanged = function ($event) {
var data = {};
data[$event.currentTarget.name] = self[$event.currentTarget.name];
$http({
url: '...',
method: 'POST',
data: data
});
};
Hope this helps.
In the view
onblur=test(config.company,'name')
In the controller
$scope.test = function(value,name){
$http({
url: '...',
method: 'POST',
name: value
});
Hope it helps

ajax call to do action when onclick checkbox in ofbiz

I want to use checkboxes with options say id1,id2.when i choose id1 a ajax will run through javascript and call the appropriate action and return the response.i dont want to reload the page.please post some freemarker, controller.xml, java codes to do this.
Based on my understanding of the question, the following script might be helpful you:
in ftl file itself/ in seperate js file you add the following script:
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery("#id1").click(function(){
if(jQuery(this).is(":checked")) {
var reqUrl= "checkbox1_Url";
sendAjaxRequest(reqUrl);
}
});
jQuery("#id2").click(function(){
if(jQuery(this).is(":checked")) {
var reqUrl= "checkbox2_Url";
sendAjaxRequest(reqUrl);
}
});
});
function sendAjaxRequest(reqUrl){
jQuery.ajax({
url : reqUrl,
type : 'POST',
data : {'var1': 'val1', 'var2' : 'val2'}, //here you can pass the parameters to
//the request if any.
success : function(data){
//You handle the response here like displaying in required div etc.
},
error : function(errorData){
alert("Some error occurred while processing the request");
}
});
}
</script>
In freemarker,
<input type="checkbox" id="id1" name="checkbox1" />
<input type="checkbox" id="id2" name="checkbox2" />
In controller.xml:
<request uri="checkbox1_Url">
<!-- fire if any events are here -->
<response name="success" type="view" value="ViewName1" />
<response name="error" type="view" value="errorViewName" />
</request>
<request uri="checkbox2_Url">
<!-- fire if any events are here -->
<response name="success" type="view" value="ViewName2" />
<response name="error" type="view" value="errorViewName" />
</request>
<view-map name="ViewName1" type="screen" page="component://.../widget/screensFileName#screenName"/>
<view-map name="ViewName2" type="screen" page="component://.../widget/screensFileName#screenName"/>
You define two screens in widgets as specified in the above path(page="...." attribute of view-map tag).
jQuery(function() {
jQuery('input[type = checkbox]').bind('click',function() {
var categoryId ="";
if(jQuery(this).is(':checked')) {
categoryId = jQuery(this).val();
}
var reqUrl= "categoryurl";
sendAjaxRequest(reqUrl, categoryId);
});
});
function sendAjaxRequest(reqUrl, categoryId){
jQuery.ajax({
url : reqUrl, // Here the Url will have to return the all products related to
//passed category
type : 'POST',
data : {'categoryId': categoryId}, //here you can pass the parameters to
//the request if any.
success : function(data){
//You handle the response here display all products in a div etc.
},
error : function(errorData){
alert("Some error occurred while processing the request");
}
});
}
<input type="checkbox" id="id1" name="checkbox1" value="yandamuri_cat"/><label for="id1">YandaMuri</label>
<input type="checkbox" id="id2" name="checkbox2" value="chetanBhagat_cat"/><label for="id2">Chetan Bhagath</label>
In Controller.xml:
<request uri="categoryurl">
<!-- fire if any events are here -->
<response name="success" type="view" value="ViewName" />
<response name="error" type="view" value="errorViewName" />
</request>
<view-map name="ViewName" type="screen" page="component://.../widget/screensFileName#screenName"/>
Define a screen in appropriate location/path specified in above page attribute of viw-map tag.
Here, the screen may be without decorator, so that the response will come without decorator and so you can display them in the current page, without reloading. Entire page.
I guess this might help you.

Resources