Thank you. Fixed.
lcOutput = lcOutput + [<option value="] + lcValue + [" ] +;
IIF(llSelected,[selected="selected" ],[]) + [>] +;
lcText +[</option>] + CRLF
+++ Rick ---
Hello,
There is also a problem for passing array from the HtmlDropDown so far as I know you need to pass a array's as reference not value
And also the lcSelectedValue doens't work form the HtmlDropDown ...
Example please...
Here is the code for the selected value
I put all the code in visual classes ... but to work I need to trim the selected value
IF VARTYPE(THIS.cSelectedValue) = "C"
IF ATC(":FORCED",THIS.cSelectedValue) > 0
THIS.cSelectedValue = STRTRAN(THIS.cSelectedValue,":FORCED","",1,-1,1)
llForced = .T.
ENDIF
THIS.cSelectedValue = ALLTRIM(THIS.cSelectedValue)
ELSE
THIS.cSelectedValue = ALLTRIM(TRANSFORM(THIS.cSelectedValue))
ENDIF
I don't see how this relates to the array issue you described below.
Can you please clearly state what your issue is and then perhaps shown an example. The control works as a functions so it can render with a simple command from the command window or a small prg so it should be easy to demonstrate.
+++ Rick ---
How did you pass aarray datasource here ?
FUNCTION HtmlDropDown(lcName,lcSelectedValue,lcDataSource,;
lcDataValueField,lcDataTextField,;
lcAttributes,lcInitialText,lcInitialValue)
IF EMPTY(lcAttributes)
lcAttributes = ""
ENDIF
RETURN HtmlListBox(lcName,lcSelectedValue,lcDataSource,lcDataValueField,;
lcDataTextField,lcAttributes + " !DROPDOWN!",;
lcInitialText,lcInitialValue)
ENDFUNC
Oh I get it. The array is not getting passed through @lcDataSource.
Does anybody still use arrays in FoxPro? 😃 You know because of shit like this:
*** Satisfy compiler - won't compile in project without this
if .F.
LOCAL ARRAY lcDatasource[1]
endif
lnDimensions = ALEN(lcDataSource,2)
IF (lnDimensions = 0)
lnDimensions = 1
lnRows = ALEN(lcDataSource,0)
ELSE
lnRows = ALEN(lcDataSource,1)
ENDIF
FOR lnX = 1 TO lnRows
Gotta love FoxPro design for that sort of madness 😃 All because arrays can't be assigned without copying... Argh, Fox arrays are the scourge of programming. Anyway I disgress...
later...
Ok so I took a look at this and it looks like neither arrays or collections never really worked - not with HtmlDropDown()
or HtmlListBox()
. Apparently nobody was using those features ever since none of that worked and I've never had any reports of issues with it. There were all sorts of problems there that needed fixing. I've fixed them now so this should now work with the following code fixes (large code block alert!):
************************************************************************
* HtmlListBox
****************************************
*** Function: Creates an HTML Listbox from a cursor, collection or
*** array. Pass the cursor as a string alias, collections
*** as a plain object and arrays by references (@laItems).
*** Assume:
*** Pass:
*** Return:
************************************************************************
FUNCTION HtmlListBox(lcName,lcSelectedValue,lcDataSource,;
lcDataValueField,lcDataTextField,;
lcAttributes,lcInitialText, lcInitialValue)
LOCAL lcOutput, lcOldAlias, lcText, lcValue, lnDataMode, llForced
IF EMPTY(lcName)
lcName = SYS(2015)
ENDIF
IF ISNullOrEmpty(lcSelectedValue)
lcSelectedValue = ""
ENDIF
llForced = .F.
IF VARTYPE(lcSelectedValue) = "C"
IF ATC(":FORCED",lcSelectedValue) > 0
lcSelectedValue = STRTRAN(lcSelectedValue,":FORCED","",1,-1,1)
llForced = .T.
ENDIF
ELSE
lcSelectedValue = TRANSFORM(lcSelectedValue)
ENDIF
LOCAL loSelectedValues, lnSelectedCount, lcSelectedValues
loSelectedValues = CREATEOBJECT("Collection")
lcSelectedValues = ""
lnSelectedCount = 0
*** Handle AutoPostback
IF VARTYPE(REQUEST) = "O" AND Request.IsFormVar(lcName) AND !llForced
loSelectedValues = Request.GetFormMultipleCollection(lcName)
lnSelectedCount = loSelectedValues.Count
ELSE
*** On get set single value
* TODO: Handle array model value
loSelectedValues.Add(lcSelectedValue)
lnSelectedCount = 1
ENDIF
*** Create a string list of selected values to match against
*** |value1|value2|
IF lnSelectedCount > 0
lcSelectedValues = "|"
FOR lnX = 1 TO lnSelectedCount
lcSelectedValues = lcSelectedValues + loSelectedValues.Item(lnX) + "|"
ENDFOR
ENDIF
IF ISNULLOREMPTY(lcDataSource)
lcDataSource = ""
ENDIF
IF EMPTY(lcDataValueField)
lcDataValueField = ""
ENDIF
IF EMPTY(lcDataValueField)
lcDataValueField = ""
ENDIF
llIsDropDown = .F.
IF EMPTY(lcAttributes)
lcAttributes = ""
ELSE
IF AT("!DROPDOWN!",lcAttributes) > 0
llIsDropDown = .T.
lcAttributes = STRTRAN(lcAttributes,"!DROPDOWN!","")
ENDIF
ENDIF
lnDataMode = 0 && Cursor
DO CASE
CASE TYPE("lcDataSource.Count") = "N"
lnDataMode = 2 && Collection
CASE TYPE("lcDataSource[1]") # "U"
lnDataMode = 1 && Array
ENDCASE
lcOutput = [<select id="] + lcName + [" name="] + lcName + [" ] +;
IIF(llIsDropDown,[Size="1" ],[Size="5" ]) + lcAttributes + [>] + CRLF
IF VARTYPE(lcInitialText) = "C"
lcValue = ""
IF VARTYPE(lcInitialValue) = "C"
lcValue = [value="] + lcInitialValue + ["]
ENDIF
lcOutput = lcOutput + [<option ] + lcValue + [>] + lcInitialText +[</option>] + CRLF
ENDIF
IF lnDataMode = 0
lcOldAlias = SELECT()
SELECT (lcDataSource)
SCAN
lcValue = TRANSFORM(EVALUATE(lcDataValueField))
IF EMPTY(lcDataTextField)
lcText = lcValue
ELSE
lcText = TRANSFORM(EVALUATE(lcDataTextField))
ENDIF
llSelected = .f.
IF lnSelectedCount > 0 AND AT("|" + lcValue + "|",lcSelectedValues) > 0
llSelected = .T.
ENDIF
lcOutput = lcOutput + [<option value="] + lcValue + [" ] +;
IIF(llSelected,[selected="selected" ],[]) + [>] +;
lcText +[</option>] + CRLF
ENDSCAN
IF !EMPTY(lcOldAlias)
SELECT (lcOldAlias)
ENDIF
ENDIF
*** Array - Assume 1 or 2 dimensional array. 2 dimensions: 1 -value 2 -text
*** 1 dimension value: Value for text and value
*** 1 dimension object: Use lcDataTextField/lcDataValueField for eval
IF lnDataMode = 1
*** Satisfy compiler
if .F.
LOCAL ARRAY lcDatasource[1]
endif
lnDimensions = ALEN(lcDataSource,2)
IF (lnDimensions = 0)
lnDimensions = 1
lnRows = ALEN(lcDataSource,0)
ELSE
lnRows = ALEN(lcDataSource,1)
ENDIF
FOR lnX = 1 TO lnRows
IF lnDimensions >1
lcValue = lcDataSource[lnX,1]
lcText = lcDataSource[lnX,2]
ELSE
IF !EMPTY(lcDataValueField)
loItem = lcDataSource[lnX]
lcValue = EVALUATE("loItem." + lcDataValueField)
IF !EMPTY(lcDataTextField)
lcText = EVALUATE("loItem." + lcDataTextField)
ELSE
lcText = lcValue
ENDIF
ELSE
lcValue = lcDataSource[lnX]
lcText = lcValue
ENDIF
ENDIF
llSelected = .f.
IF lnSelectedCount > 0 AND AT("|" + lcValue + "|",lcSelectedValues) > 0
llSelected = .T.
ENDIF
lcOutput = lcOutput + [<option value="] + lcValue + [" ] +;
IIF(llSelected,[selected="selected" ],[]) + [>] +;
lcText +[</option>] + CRLF
ENDFOR
ENDIF
*** Collection - assume item is an object with two properties
*** Evaluated with lcDataValueField & lcDataTextField
IF lnDataMode = 2
LOCAL loCol
loCol = lcDataSource &&EVALUATE(lcDataSource)
FOR EACH loItem in loCol FOXOBJECT
IF VARTYPE(loItem) = "O"
lcValue = EVALUATE("loItem." + lcDataValueField)
IF !EMPTY(lcDataTextField)
lcText = EVALUATE("loItem." + lcDataTextField)
ELSE
lcText = lcValue
ENDIF
ELSE
lcValue = loItem
lcText = loItem
ENDIF
llSelected = .f.
IF lnSelectedCount > 0 AND AT("|" + lcValue + "|",lcSelectedValues) > 0
llSelected = .T.
ENDIF
lcOutput = lcOutput + [<option value="] + lcValue + [" ] +;
IIF(llSelected,[selected="selected" ],[]) + [>] +;
lcText +[</option>] + CRLF
ENDFOR
ENDIF
lcOutput = lcOutput + "</select>" + CRLF
RETURN lcOutput
ENDFUNC
* HtmlListBox
************************************************************************
* HtmlDropDown
****************************************
*** Function:
*** Assume:
*** Pass:
*** Return:
************************************************************************
FUNCTION HtmlDropDown(lcName,lcSelectedValue,lcDataSource,;
lcDataValueField,lcDataTextField,;
lcAttributes,lcInitialText,lcInitialValue)
IF EMPTY(lcAttributes)
lcAttributes = ""
ENDIF
RETURN HtmlListBox(lcName,lcSelectedValue,@lcDataSource,;
lcDataValueField,lcDataTextField,;
lcAttributes + " !DROPDOWN!",;
lcInitialText,lcInitialValue)
ENDFUNC
* HtmlDropDown
I still need to test a few more scenarios but this should now work for code like this:
*** Selected value to select in listbox
lcSelectedValue = "Item2"
*** Cursor Binding - Key Value
CREATE CURSOR TITEMS (Key varchar(40), Value varchar(100) )
INSERT INTO TItems VALUES ("Item1","First Item #1 Db")
INSERT INTO TItems VALUES ("Item2","Second Item #2 Db")
? HtmlDropdown("lstItemsCursor",lcSelectedValue,"TItems","Key","Value")
*** Array Binding - Single Item
DIMENSION laItems[2]
laItems[1] = "Item1"
laItems[2] = "Item2"
? HtmlDropdown("lstItemsArray",lcSelectedValue,@laItems)
*** Collection Binding - Single Item
loCol = CREATEOBJECT("Collection")
loCol.Add("Item1")
loCol.Add("Item2")
? HtmlDropdown("lstItemsCollection",lcSelectedValue,loCol)
*** Object Binding for arrays and collections
loObj1 = CREATEOBJECT("EMPTY")
ADDPROPERTY(loObj1,"Key","Item1")
ADDPROPERTY(loObj1,"Value","First Item #1")
loObj2 = CREATEOBJECT("EMPTY")
ADDPROPERTY(loObj2,"Key","Item2")
ADDPROPERTY(loObj2,"Value","Second Item #2")
?
? loObj1.Key
? loObj1.Value
? loObj2.Key
? loObj2.Value
?
*** Array of Objects Binding
DIMENSION laItems[2]
laItems[1] = loObj1
laItems[2] = loObj2
? HtmlDropdown("lstItemsArray2",lcSelectedValue,@laItems,"Key","Value")
*** Collection of Objects Binding
loCol = CREATEOBJECT("Collection")
loCol.Add(loObj1)
loCol.Add(loObj2)
? HtmlDropdown("lstItemsCollection",lcSelectedValue,loCol,"Key","Value")
+++ Rick ---
Hello, tks
Just see a litle possible problem with selectedvalue as descibed above
This code will probably ( the 6.21 does ) fail for the selected value
lcSelectedValue = "Item2 "
*** Cursor Binding - Key Value
CREATE CURSOR TITEMS (Key varchar(40)
I am at work to edit any cursor data on the web and selected value comes usually from a field value filled with space. ( I don't tested it with your new code )
If would be also usefull if you add some code like
IF ATC(lcAttributes,"class=") < 1
lcAttributes = lcAttributes + [class="form-control" ]
ENDIF
Selection and Spacing
These controls render values as is including spaces. They always have. So if you render with spaces your selected values have to have spaces too.
*** Selected value to select in listbox
lcSelectedValue = "Item2 "
*** Cursor Binding - Key Value
CREATE CURSOR TITEMS (Key varchar(40), Value varchar(100) )
INSERT INTO TItems VALUES ("Item1 ","First Item #1 Db")
INSERT INTO TItems VALUES ("Item2 ","Second Item #2 Db")
? HtmlDropDown("lstItemsCursor",lcSelectedValue,"TItems","Key","Value")
produces - correctly - the following:
<select id="lstItemsCursor" name="lstItemsCursor" Size="1" >
<option value="Item1 " >First Item #1 Db</option>
<option value="Item2 " selected="selected" >Second Item #2 Db</option>
</select>
If you need things trimmed, use a TRIM(key)
expression rather than the field name.
Adding form-control
I kind of agree that it would be useful, but I think this is not a good idea because a) it would have then to be added to all input controls, and b) it makes it hard to create a plain textbox. Not everybody is using the bootstrap fields and if you're not it would be a PITA to use because you couldn't force attributes to be empty - you always would have to pass something.
So no, I am not adding that at this point 😃
+++ Rick ---