I am trying to upload a file using Fable-Elmish and the React Helpers. However, I can't work out how to convert the form event when a file is selected into something that I can send off to the server using Fetch. This is the view:
R.input [
ClassName "input-control"
Type "file"
OnChange (fun x -> FileUploaded x.target |> dispatch )
] []
The corresponding part of my update function:
| FileUploaded file ->
model, Cmd.ofPromise postCsv file FetchSuccess FetchFailure
And the function to call the api with fetch:
let postData input =
let formData = FormData.Create()
formData.append("file.csv", input?files)
let defaultProps =
[ RequestProperties.Method HttpMethod.POST
; RequestProperties.Body (formData |> unbox)]
promise {
return! Fable.PowerPack.Fetch.fetch ("/api/data") defaultProps
}
How can I can convert the React.FormEvent into the BodyInit that fetch needs?
Your going to need to create a new FormData object and append the file to it.
let formData = FormData.createNew
formData.append("file", file.[0])
Then change your call to postRecord to pass formData instead of file. You need fetch to encode it, but you are just passing the raw array of files.
At least that is my understanding from the fetch example on uploading a file. Also, post record looks wrong to me, is there just a "post" method you could use? postRecord implies it is expecting a record type.
I think Fetch.postRecord is your problem, it sets Content-Type header to application/json, when it should be multipart/form-data.
You need to use raw fetch API, instead of powerpack wrapper, something like this.
Upon testing your code, checking ev.target?value revealed that the event just grabs the name of the selected file. postRecord appears to be used for sending json to an endpoint. You are going to want to port: https://medium.com/ecmastack/uploading-files-with-react-js-and-node-js-e7e6b707f4ef , to what you want to do.
It turns out I wasn't using the FileList API properly. Here's the working solution for the post method:
let postData input =
let formData = FormData.Create()
formData.append("file.csv", input?files?item(0))
let defaultProps =
[ RequestProperties.Method HttpMethod.POST
;RequestProperties.Headers [unbox EncType "multipart/form-data"]
; RequestProperties.Body (formData |> unbox)]
promise {
return! Fable.PowerPack.Fetch.fetch ("/api/data") defaultProps
}
Related
I am trying to post data to API. I am building request every time. and I am adding headers to wrk.format() method. The headers are not accepting event though headers type is string.
headers = {}
s = {}
request = function()
headers["Authorization"] = "key"
for name, value in pairs(headers) do
s[1] = string.format("%s: %s", name, value)
end
print(s[1])
print(type(s[1])
return wrk.format("POST", "/api/", s[1] ,data)
end
throwing error :
PANIC: unprotected error in call to Lua API ([string "wrk"]:0: attempt to index field 'headers' (a string value))
Can anyone help me with this?
Thanks in advance.
You need to pass the entire dictionary to the format function
return wrk.format("POST", "/api/", headers ,data)
in case of mine the headers look like:
headers = {}
headers["Content-Type"] = "application/json"
So I have a field in state bullet_points: [] that is an array of elements.
I have a function in my component that adds/removes elements from this array. To save the changes, clicking submit will sent product: this.state as an argument in a POST request to my backend.
The backend only receives bullet_points if the array IS NOT empty. If I clear the field of all elements, it is never sent to the backend.
What would cause this? Below are the relevant code snippets.
1) Function for add/remove of elements (notice arrow, this is where elements are removed)
updateList(evt) {
evt.preventDefault();
let elements = this.state[evt.target.dataset.type];
let idx = parseInt(evt.target.dataset.index);
let new_element = evt.target.dataset.type == "durations" ? 30 : "";
if (isNaN(idx)) {
elements.push(new_element);
} else {
if (evt.target.dataset.delete) { <----------
elements.splice(idx, 1);
}
else {
elements[idx] = evt.target.value;
}
}
this.setState({ [evt.target.dataset.type]: elements });
}
2) POST request to backend
API.put(`coach/products/${this.props.params.id}`, {
product: this.state
}, function(res) {
this.closeModal();
Alert.success('<p class="small-body-text">Your changes have been saved</p>', {
position: "top-right",
effect: "scale",
timeout: 5000
});
}.bind(this));
Many libraries that serialize and post data do not send key/value pairs if the value is an empty array. For example: jQuery has this behavior. There are essentially two ways you can handle this:
1) On the backend, check for the existence of the key in the post parameters. If it doesn't exist, treat it like an empty array.
2) If you really want to send an empty array (maybe there's a difference between sending an empty array and not sending the key/value at all?), then send the array with a single empty string or some other value that cannot possibly be valid input but that you will check for to mean that the array is empty.
One tricky thing I've run into before - if you're testing with rspec, rspec's post method does not remove the key/value if the value is an empty array; it sends the data as is. So you may want to add additional tests that represent what the client data looks like after it has been serialized.
I am trying to use the swagger parser to parse and retrieve information in the "swagger.json" (io.swagger.parser.SwaggerParser;)
Below is an excerpt of the "swagger.json".
I am trying to retrieve "$ref" : "#/definitions/abc".
"responses" : {
"200" : {
"description" : "abc",
"schema" : {
"$ref" : "#/definitions/abc"
}
},
This is the code to parse it.
SwaggerParser sparse = new SwaggerParser();
Swagger swagger = sparse.read("swagger.json");
// This next line is what I am having a problem with.
swagger.getPath("/endpointurl").getGet().getResponses().get("200").getSchema();
At this point, the ".getSchema()" in the above line has only "getType()" in it I can call. It doesn't have "get$ref()". This is because ".getSchema()" returns a "Property" (io.swagger.models.properties.Property). It doesn't have "get$ref()".
get$ref() is available in "RefProperty" (io.swagger.models.properties.RefProperty)
But ".getSchema()" doesn't return a "RefProperty".
Typecast the result of ".getSchema()" to a "RefProperty" also doesn't work. It ends up in this error.
java.lang.ClassCastException: io.swagger.models.properties.ArrayProperty cannot be cast to io.swagger.models.properties.RefProperty
Has anyone tried parsing a "swagger.json" and was able to retrieve the "$ref": line under "schema" in the "response" block?
Any idea how might I be able to do that?
I figured out a way to do that. Maybe not the best way to do it, but it retrieves the information in "#ref".
Object obj = xxxxx.getSchema(); // xxxxx is whatever your code that gives you ".getSchema()". Mine is in a map and I don't want to distract people.
ArrayProperty arrProp = new ArrayProperty();
arrProp = (ArrayProperty)obj; // .getSchema() returns an ArrayProperty
RefProperty refProperty = (RefProperty) arrProp.getItems(); // .getItems() will return the RefProperty type you need to call ".get$ref()".
String refStr = refProperty.get$ref(); // Voila, there's your content in "#ref".
String simpleRefStr = refProperty.getSimpleRef();
I had to do a few type castings. If you have a more elegant way of doing this, please post here.
i want to convert my excel hyperlink's path to open links with PHPExcel.
$links = $objPHPExcel->getActiveSheet()->getHyperlinkCollection();
This method will return an array of hyperlink objects, indexed by cell address; and you could then use array_filter() with an appropriate callback and the ARRAY_FILTER_USE_KEY flag set to extract those within a specific range.
my var_dump($links); output :
But i dont know how to loop the array of objects with array_filter() function..
I try :
$test = str_replace($links, "file", "mnt");
var_dump($test);
and i got the error above.. Any ideas please ?
The collection is an array of objects, indexed by cell address; and the PHPExcel_Cell_Hyperlink object has a set of documented methods for accessing and setting its data:
foreach($links as $cellAddress => $link) {
// get the URL from the PHPExcel_Cell_Hyperlink object
$url = $link->getUrl();
// change the URL however you want here
$url = str_replace($url, "file", "mnt");
// Set the new value for the link
$link->setUrl($url);
}
If you want to modify just those URLs for cells in column N, then you can wrap them in an if test:
foreach($links as $cellAddress => $link) {
// Test for column N
sscanf($cellAddress, '%[A-Z]%d', $column, $row);
if ($column == 'N') {
// get the URL from the PHPExcel_Cell_Hyperlink object
$url = $link->getUrl();
// change the URL however you want here
$url = str_replace($url, "file", "mnt");
// Set the new value for the link
$link->setUrl($url);
}
}
I fetched the results of a query in the model. Next i right away added a .to_json and assumed I will get a correct JSON object. But JQuery was not able to parse the json
def self.get_all_specials(year)
data_array=AttributeCalendarAnnual.find(:all, :conditions=>["created_at between ? and ?",Date.civil(Date.today.year), Date.civil(Date.today.next_year.year)], :order=>["created_at asc"])
return data_array.to_json
end
But the result I get is not a valid JSON it seems.
EDIT
The output :
[{"created_at":"2012-01-17T17:38:27Z","id":1,"in_market_end_date":"2012-01-31T23:59:59Z","in_market_start_date":"2012-01-18T00:00:00Z","initiative_id":1,"is_mail_count_selected":true,"is_mailer_selected":true,"is_market_selected":true,"is_offer_selected":true,"mail_count":1,"mailer_start_date":"2012-01-25T00:00:00Z","offer_selection_end_date":"2012-01-12T23:59:59Z","offer_selection_start_date":"2012-01-09T00:00:00Z","updated_at":"2012-01-17T17:38:27Z"},{"created_at":"2012-01-17T20:21:37Z","id":2,"in_market_end_date":"2012-01-28T23:59:59Z","in_market_start_date":"2012-01-24T00:00:00Z","initiative_id":3,"is_mail_count_selected":true,"is_mailer_selected":true,"is_market_selected":true,"is_offer_selected":true,"mail_count":5,"mailer_start_date":"2012-01-30T00:00:00Z","offer_selection_end_date":"2012-01-21T23:59:59Z","offer_selection_start_date":"2012-01-09T00:00:00Z","updated_at":"2012-01-17T20:21:37Z"}]
if you are simply outputting the escaped object to your page and hoping JS will parse it this will not work because it will be interpreted as a string. Instead try feeding the string into a function like this:
function parseJSON(txt, escape) {
if (escape === true) {
txt = unescape(txt);
}
return new Function("return " + txt)();
}
var result = parseJSON(someString);