ListToArray for submitted form - coldfusion

I have a web form with multiple elements with the same name for example:
<textarea name="instructions"><cfoutput>#struct.instructions# </cfoutput> </textarea>
Form is built in html/coldfusion/js and the database to store the data is MS Access.
In the script that I am using to process form submission I am using ListToArray method to get all fields with a given name.
<cfset arrayInstr = ListToArray(Form.instructions)>
Ok and here is the problem. If the submitted text contains comas ListToArray will interpret it as multiple elements.
For example if I try to submit a string "Bla bla bla bla" everything will be fine, but if string will be "bla, bla, bla" only "bla" will be submitted to database.
Is there other way to process multiple fields with the same name?
I would like to avoid giving unique names.
thank you,
Janusz

If you give the form field names like instructions1, instructions2, instructions3, it is easy to perform whatever logic you need in a loop.
for( var i = 1; i <=3; i++ ){
var theValue = form["instructions" & i];
//do whatever you need to do with theValue//
}
I think that is much easier to deal with than using JavaScript to add delimters to the form fields.

Q: Is there other way to process multiple fields with the same name?
A: Not directly
Javascript sees the items as a array. What you would need to do is have Javascript loop through all the values and create a string with a different delimiter and put that into a hidden field. The distinction between different <textarea>'s and commas would be maintained.

You can create an array of the individual form fields by using the getHTTPRequestData function.
<cfset Variables.RequestData = getHTTPRequestData()>
<cfset Variables.RequestContent = Variables.RequestData.Content>
<cfset Variables.FormScope = []>
<cfloop index="Variables.CurrentItem" list="#Variables.RequestContent#" delimiters="&">
<cfset ArrayAppend(Variables.FormScope, URLDecode(ListLast(Variables.CurrentItem, "=")))>
</cfloop>

Related

Coldfusion ignores posted html array fields

I am posting an html form which multiple input names look like that: left_impedance_TYMP[]
However when accessing them in coldfusion, it ignores empty fields.
FORM["left_impedance_TYMP[]"]
Inspecting POST request seems correct.
Is there a solution on this?
When you have multiple form fields of the same name, with or without brackets, both a GET and a POST ignore empty fields values.
Form:
<form action="brackets_process.cfm" method="GET">
<input type="text" name="foo" value="A"><br>
<input type="text" name="foo" value="B"><br>
<input type="text" name="foo" value="C"><br>
<input type="text" name="foo" value="D"><br>
<button>Submit</button>
</form>
Processing:
<cfdump var="#url#" label="URL">
<p></p>
<cfdump var="#form#" label="FORM">
A GET querystring brackets_process.cfm?foo=A&foo=B&foo=C&foo=D
A POST brackets_process.cfm
If you add brackets to foo[], the querystring is encoded and the struct key contains the brackets.
brackets_process.cfm?foo%5B%5D=A&foo%5B%5D=B&foo%5B%5D=C&foo%5B%5D=D
A POST is still a list of submitted values.
Converting POST data to an array.
PHP automatically converts field names that end with a bracket to an array. ColdFusion has an application.cfc setting this.sameformfieldsasarray=true; that #Alex linked. Problem is that its a global setting and could change a considerable amount of existing functionality.
With that setting on, a POST converts the values to an array.
A GET sticks to a list. So if you leave out a value (B), the value of url["foo[]'] is a list with 4 elements, where the 2nd element is empty.
Leaving a value (B) out of a POST, however, returns an array with 4 elements, where the 2nd value is empty.
So you need to determine if you want to make a global change that affects all current functionality or if you can add some conditional logic that checks the number of elements in a list vs. the expected number of fields.
I've written code in the past that named fields something like name="fieldName.#counterValue#", then parsed the field names to set positional values in a list or array to account for empty values.

returning query results as a formatted fieldname and fieldvalue types

I am trying to get the query results to give me the query results as: ArrayofStructs but
in the way i wanted,
[
{"fieldname" : "Action",FieldValue":"Update"},
{"fieldname" : "MainTitle",FieldValue":"Please Update Database"}
]
the above example if just for one row, but i had 10 rows and i am trying the output like above, how can i do in coldfusion, if its not like the above case, i could have gone with arrayofstructs but this is really annoying
here is my query
SELECT pagetitle as Action,
Title as MainTitle,
FROM QoQueries
ORDER BY pageTitle asc
I am using ACF 2021
as you have noticed, its really outputting the column names and field values as separate instead of key/pair
I would use a QueryReduce call to get the ArrayOfStruct output in the query result.
<cfset result = myQuery.reduce(function(result=[], values){
local.temp = [];
for(local.key in arguments.values){
local.temp.append({
fieldname: local.key,
FieldValue: arguments.values[local.key]
});
}
arguments.result.append(local.temp);
return arguments.result;
})>
I agree with rrk. Using a reduce() will be fairly quick and efficient, and it should be able to do what you want.
Looking back at that code, I realize it's pretty much doing the same thing as mine. The reason it's getting two nested arrays is because of appending into local.temp = []. If you remove that logic, you should be able to create just the single Array of Structs you were looking for.
One other thing I changed is using the Arrow Functions. They aren't much different than writing out the full function, but they're much more compact and cleaner. They take a little getting used to, but the more I've used them, the more I like them.
I also try to avoid explicit loops if I can. Using things like reduce() can be significantly faster when working with larger datasets.
My code below will work in CF2018 or higher, and since you indicated CF2021, you should be good to go.
<cfscript>
res = myQuery.reduce( (prev, nxt) => {
prev.append({"FIELDNAME":nxt.Action,"FIELDVALUE":nxt.MainTitle});
return prev;
}, []
);
</cfscript>
The fiddle is a little more fleshed out. https://cffiddle.org/app/file?filepath=89565618-18ae-49e0-bed0-bdb9fb6a4162/04567bb5-ec53-4097-a941-bb2b5f42a499/ec51b428-ec53-4606-a828-8dcce9b954b0.cfm
Lastly, a couple of notes. I'm not completely sure how you're consuming this data, so these recommendations may not even be relevant. Also, your code seems to indicate that you're performing a Query of Query. That may also not be needed (as well as the ORDER BY in it). You may already have the data available in your page, and it can be pulled out from the original query data.
Since the question is tagged Lucee, rrk's solution looks like a good way to go. For an Adobe Coldfusion solution, you could use nested loops. The code below will simply output field/value pairs with each query row on a single line.
<cfoutput>
<cfloop query = "myQuery">
<cfloop list = "#myQuery.columnlist#" index = ColumnName>
#ColumnName# #myQuery[ColumnName][currentrow]#
</cfloop>
<br>
</cfloop>
</cfoutput>
You can see the results with two rows of sample data here.

Updates doesn't take affect in django orm, Is there something wrong in my code?

I need to update multiple rows in a url_field in one of my models, each product_id has its own corresponding new values to be loading. What's wrong with my code? No errors are returned.
idlist= ["",""]
url = ["https://www.sample.com","https://www.sample2.com"]
i = 0
while i < len(item_idlist):
Model.objects.filter(item_id=idlist[i].update(product_url=url[i]))
i += 1
I expect that every iterations will update my data inside the model.
You could use a for loop combined with zip:
for id, url in zip(idlist, urls):
m = Model.objects.filter(item_id=id)
m.update(product_url = url)
Careful with your parentheses. Your update() should be after your filter(). Not inside.
Are you sure about your idlist ? Because you are filtering with an empty string. So you filter() will return nothing, and update nothing.
You can update your data structure like this. Associate an id with a new url into a dictionary.
idlist_url = {
1: "https://www.sample.com",
2: "https://www.sample2.com"
}
for id, new_url in idlist.items():
Model.objects.filter(item_id=id).update(product_url=new_url)

Django pass CommaSeparated values to GET paramater

We know that django has CommaSeperated model field. But how can we pass commaSeparated string to Django GET parameter.
Whenever i try to pass something like below as GET parameter:
1,2,3,4
I receive using below code in django view
request.GET.get('productids','')
It ends up like below in django view.
'1,2,3,4'
Its ends up adding quotes around the array.
Please any Django experts help me with this issue.
You can use getlist
param_list = request.GET.getlist('productids')
If you're passing it as a single parameter then you can construct it
param_list = [int(x) for x in request.GET.get('productids', '').split(',')]
Django converts GET and POST params to string (or unicode). That means, if you're sending a list (array) as a GET param, you'll end up getting a string at the backend.
However, you can convert the string back to array. Maybe like this:
product_ids = request.GET.get('productids', '')
ids_array = list(product_ids.replace(',', '')) # remove comma, and make list
The ids_array would look like this - ['1', '2', '3'].
Update:
One thing worth noting is the ids in ids_array are strings, not integers (thanks to Alasdair who pointed this out in the comments below). If you need integers, see the answer by Sayse.

Coldfusion loop behavior

I'm not really familiar with Coldfusion, but I'm reading through some code and saw this:
<CFLOOP INDEX="element" LIST="#FIELDNAMES#">
<CFSET REP_LIMIT = 0>
<CFSET E_VALUE = EVALUATE(#ELEMENT#)>
I have two questions:
1) Is that setting E_VALUE to be the current index? If so, what's with the EVALUATE? and 2) Is this a poor and/or dangerous use of EVALUATE?
Evaluate is used primarily to evaluate dynamically named variables, such as form variables. If you don't know what form variables might be submitted from a form, you can simply loop through the fieldname by accessing FORM.fieldnames.
(http://cfprimer.blogspot.com/2005/03/avoid-evaluate.html). In 14 years of coding CF, I have seen it used only a handful of times. In my opinion, it's bad practice to set yourself up in such a manner as to not know in advance what form elements will be submitted.
In your example, the index is set to "element". So, while looping, whatever is in your list of "fieldnames" will be an element.
If you wanted to output those fieldnames, you would do something like this:
<cfset fieldnames = "firstname,lastname,email">
<cfoutput>
<cfloop index="element" list="#fieldnames#">
#element#<br>
</cfloop>
</cfoutput>
This would output like this:
firstname
lastname
email