when I'm using the POST endpoint from Sveltekit, I get a "flat" object as output. How can I get a "structured" Object instead ?
Let's assume the following code:
index.svelte
<div class="container">
<form method="post">
<label for="firstname">Firstname</label>
<input type="text" name="firstname" />
<label for="lastname">Lastname</label>
<input type="text" name="lastname" />
<label for="dog">Dog 1</label>
<input type="text" name="dog" />
<label for="dog">Dog 2</label>
<input type="text" name="dog" />
<!-- ... -->
<button>Save</button>
</form>
</div>
index.js
export async function post({request}){
const data = Object.fromEntries(await request.formData());
console.log(data);
return{}
}
Ouput (what I'm calling "flat" object)
{ firstname: 'foo', lastname: 'bar', dog: 'teckel', dog: 'labrador' }
Instead of that output, how should I proceed to get the following one in my index.js
Expected output:
{
firstname: 'foo',
lastname: 'bar',
dogs: [ { dog: 'teckel' }, { dog: 'labrador' } ]
}
There are libraries that can perform a transform like this more or less automated. Some use conventions in the field names to parse the data into arrays and nested structures, others additionally use schemas to do type conversions or validation. E.g. to achieve an array of objects like this, one might set the names like this:
<label for="dog">Dog 1</label>
<input type="text" name="dogs[][dog]" />
<label for="dog">Dog 2</label>
<input type="text" name="dogs[][dog]" />
The [] Indicates that the field is part of an array, [dog] indicates that a property called dog is set on the element (.dog would also be reasonable).
So instead of calling Object.fromEntries you have to either parse the data yourself or find a library that does it for you. (Note that StackOverflow is not a place for library recommendations.)
Personally, I would avoid the synchronous form post and send JSON asynchronously instead, that way you can send in a fixed structure and receive that exact structure. Of course this requires binding/reading the form values yourself.
Related
There is 3 instances of 'authenticity_token' in this html:
<form class="edit_checkout" action="/942252/checkouts/624527ae778897e534d917b52af2eb28" accept-charset="UTF-8" method="post"><input type="hidden" name="_method" value="patch" /><input type="hidden" name="authenticity_token" value="5vK3h2ocwaKm0hZ+AH3HAtnffe9l7hQHIMDfrMPusFhxtSV6IbLBfWOnBboOBysF7NyDPQ7GNxdfcWUPOk5WSQ==" />
<form class="edit_checkout" action="/942252/checkouts/624527ae778897e534d917b52af2eb28" accept-charset="UTF-8" method="post"><input type="hidden" name="_method" value="patch" /><input type="hidden" name="authenticity_token" value="Fkw7j/Wv0Xxhna1aWNh8FsZhNnXz4zu0vFuTV0q9WJ6BC6lyvgHRo6Tovp5WopAR82LIp5jLGKTD6in0sx2+jw==" />
<form class="edit_checkout" data-payment-form="" action="/942252/checkouts/624527ae778897e534d917b52af2eb28" accept-charset="UTF-8" method="post"><input type="hidden" name="_method" value="patch" /><input type="hidden" name="authenticity_token" value="Bs1PNacx4rK5TJcl+VDO+RXnR69DixOH+osJ/yxuQQeRit3I7J/ibXw5hOH3KiL+IOS5fSijMJeFOrNc1c6nFg==" />
The actual token (the value I want) is the value attribute and in this case I want the 3rd instance of 'authenticity_token'.
All 3 instances start with <form class="edit_checkout" but the third is followed by data-payment-form="" instead of action="/ . so I know the one I want is the one that includes data-payment-form
I tried using this code in Cheerio:
$('form.edit_checkout input['name="authenticity_token"']')
But that returns the first auth token on the first line and I need the auth token on the third line.
Thanks!
How about:
let input = $('[name="authenticity_token"]')[2]
Then to get the value:
let value = $(input).attr('value')
ref:
https://cloud.google.com/nodejs/docs/reference/storage/1.5.x/File#getSignedPolicy
I am trying to upload files to my bucket using signed policies. Using the example from the documentation I get a response from my bucket object for 3 items.
"policyString": "{\"expiration\":\"2019-10-18\",\"conditions\":[[\"eq\",\"$key\",\"image.jpg\"],{\"bucket\":\"my-bucket\"},[\"eq\",\"$Content-Type\",\"image/jpeg\"],[\"content-length-range\",0,1024]]}",
"policyBase64": "[some-long-string]",
"policySignature": "[some-long-string]"
In the documentation it also shows you how to upload objects using curl.
ref:
https://cloud.google.com/storage/docs/object-basics#upload-object-json
How do you assemble what I get back as a signed policy and the upload api
https://www.googleapis.com/upload/storage/v1/b/[BUCKET_NAME]/o?uploadType=media&name=[OBJECT_NAME]
to upload a file to my bucket using axios? Is there other headers to attach?
Here is what I did to take a stab at it but I'm not sure.
const options = {
headers: {
'Authorization': ?
'Content-Type': file.type
}
}
axios.put(concatenatedPolicySignatureUrl, file, options)
.then(response => {
console.log('success!');
}
Signed policy strings only work with the XML API, which means POSTs to https://storage.googleapis.com/bucket/object (and not www.googleapis.com/upload).
For more on exactly how to generate and use the policy, see https://cloud.google.com/storage/docs/xml-api/post-object#policydocument
An example of setting up an HTTP form that would allow a user to upload an object using a policy string is below, although you could also trigger an equivalent POST request via JavaScript:
<form action="http://travel-maps.storage.googleapis.com" method="post" enctype="multipart/form-data">
<input type="text" name="key" value="">
<input type="hidden" name="bucket" value="travel-maps">
<input type="hidden" name="Content-Type" value="image/jpeg">
<input type="hidden" name="GoogleAccessId" value="1234567890123#developer.gserviceaccount.com">
<input type="hidden" name="acl" value="bucket-owner-read">
<input type="hidden" name="success_action_redirect" value="http://www.example.com/success_notification.html">
<input type="hidden" name="policy" value="eyJleHBpcmF0aW9uIjogIjIwMTAtMDYtMTZUMTE6MTE6MTFaIiwNCiAiY29uZGl0aW9ucyI6IFsNCiAgWyJzdGFydHMtd2l0aCIsICJrZXkiLCAiIiBdLA0KICB7ImFjbCI6ICJidWNrZXQtb3duZXItcmVhZCIgfSwNCiAgeyJidWNrZXQiOiAidHJhdmVsLW1hcHMifSwNCiAgeyJzdWNjZXNzX2FjdGlvbl9yZWRpcmVjdCI6ICJodHRwOi8vd3d3LmV4YW1wbGUuY29tL3N1Y2Nlc3Nfbm90aWZpY2F0aW9uLmh0bWwiIH0sDQogIFsiZXEiLCAiQ29udGVudC1UeXBlIiwgImltYWdlL2pwZWciIF0sDQogIFsiY29udGVudC1sZW5ndGgtcmFuZ2UiLCAwLCAxMDAwMDAwXQ0KICBdDQp9">
<input type="hidden" name="signature" value="BSAMPLEaASAMPLE6SAMPLE+SAMPPLEqSAMPLEPSAMPLE+SAMPLEgSAMPLEzCPlgWREeF7oPGowkeKk7J4WApzkzxERdOQmAdrvshKSzUHg8Jqp1lw9tbiJfE2ExdOOIoJVmGLoDeAGnfzCd4fTsWcLbal9sFpqXsQI8IQi1493mw=">
<input name="file" type="file">
<input type="submit" value="Upload">
</form>
I'm trying to send a single String to my Spring backend. I don't want to make an extra Object just for that string.
<form name="f" th:action="#{/restaurant_SaveLayout}" method="post">
<input type="hidden" value="trdz234"/>
<button type="submit"></button>
</form>
Spring tells me that I the RequestParam is not present.
#PostMapping("/restaurant_SaveLayout")
public String restaurant_SaveLayout (#RequestParam String circles) {
return "restaurant_ShowArr";
}
I also don't want to send anything via GET.
You missed to set the name of the input.
<form name="f" th:action="#{/restaurant_SaveLayout}" method="post">
<input type="hidden" name="circles" value="trdz234"/>
<button type="submit"></button>
</form>
I have 2 versions of my code, one is not working and the other it is.
My question is "why the not working one is not working?"
here is the JSfiddle http://jsfiddle.net/fhjF7/
The not working version:
Controller:
function Ctrl($scope) {
$scope.username = "username";
$scope.users = [ "Matteo", "Marco", "Michele" ];
};
HTML:
<h1> Not working example</h1>
<div ng-controller="Ctrl">
<div ng-repeat="user in users">
<input type="radio" ng-model="username" name="usern" ng-value="user" />
<strong>{{user}}</strong>
</div>
<div>selected: {{username}}</div>
</div>
and here is the working one, which is almost identical but replacing the string variable with an object:
Controller:
function usersCtrl($scope) {
$scope.names = {username: "username"};
$scope.users = [ "Matteo", "Marco", "Michele" ];
};
HTML:
<h1> Working example</h1>
<div ng-controller="usersCtrl">
<div ng-repeat="user in users">
<input type="radio" ng-model="names.username" name="username" ng-value="user" />
<strong>{{user}}</strong>
</div>
<div>selected: {{names.username}}</div>
</div>
It is because of the way javascript manages function parameters.
The easy way to understand it is that String, Number, and Boolean parameters are always sent byValue, while Objects and Functions are always sent byRef, that is why when you use the dot inside an ng-model it means you are doing a reference to an object which will propagate, while if you don't use a dot inside the ng-model, you are referencing a String, Number or Boolean which is actually a copy of the real variable.
More information here https://egghead.io/lessons/angularjs-the-dot and https://github.com/angular/angular.js/wiki/Understanding-Scopes
Ng-repeats create their own isolate scopes, so that's why the string is not being preserved as it's not pass by reference. If you want to update the model use
<input type="radio" ng-model="$parent.username" name="usern" ng-value="user" />
$parent gives you access to the parents scope which is outside the ng-repeat and should be the one you want.
The answer for your not working code : http://jsfiddle.net/ashuslove/fhjF7/30/
HTML :
<h1> Not working example</h1>
<div ng-controller="Ctrl">
<div ng-repeat="user in users">
<input type="radio" ng-model="names.usern" name="usern" ng-value="user" />
<strong>{{user}}</strong>
</div>
<div>selected: {{names.usern}}</div> //Changed line here
</div>
The function :
function Ctrl($scope) {
$scope.names = {usern: "usern"}; //Also need to change this
$scope.users = [ "Matteo", "Marco", "Michele" ];
};
so, i have a Mongoose Schema, something like:
Person: {
name: String,
address: {
street: String,
number: String,
city: String
}
}
Is there a way, to code our form so that i can map directly from req.body to the Person instance? considering the sub-division in address.
I tried:
<form>
<input name="name">
<input name="address.street">
<input name="address.number">
<input name="address.city">
</form>
and it doesn't work...
Try this:
<form>
<input name="name">
<input name="address[street]">
<input name="address[number]">
<input name="address[city]">
</form>
See this post on application/x-www-form-urlencoded encoding.