As a followup to my last email, it appears the Struts default design
pattern for checkboxes (submitting false values with hidden value) is the
cause.  An easy fix for this would be to allow the developer to override
this design pattern by a s:checkbox parameter (e.g. requiredValue).  The
default would be "true" - which keeps backwards compatibility, but by
setting to "false", the hidden checkbox value would not be created in the
document.  It seems like this would be an easy and beneficial addition to
the Struts community.  I don't think the "submit false checkboxes" design
pattern is necessary or appropriate at all times.

Below is the changed code from the overridden checkbox.ftl.  In this
example, I simply added an <#if> clause around the <input hidden
__checkbox> element and checked for a new parameter called "requiredValue"
(dynamicParameter in this example).  Of course the permanent solution would
be for "requiredValue" to be an actual parameter of the <s:checkbox> tag.

[checkbox.ftl]
<!-- Code Snippet -->
<#if (parameters.dynamicAttributes['requiredValue']!"true")?boolean>
    <input type="hidden" id="__checkbox_${parameters.id?html}"
name="__checkbox_${parameters.name?html}"
value="${parameters.fieldValue?html}"<#rt/>
    <#if parameters.disabled!false>
             disabled="disabled"<#rt/>
    </#if>
    />
</#if>

Thoughts?  Any reason this would cause issues elsewhere?

On Sun, Oct 1, 2017 at 1:37 PM, Burton Rhodes <burtonrho...@gmail.com>
wrote:

> Got it.  I'll use that for now.  Don't you think that is a bit of a hack?
> Do you think this be fixed or reported as a "bug"?
>
> On Sun, Oct 1, 2017 at 7:54 AM, Yasser Zamani <yasser.zam...@live.com>
> wrote:
>
>> Hello Burton,
>>
>> Thank you; I examined your example and found out this behavior is
>> because of something in Struts named "automatic checkbox detection",
>> CheckboxInterceptor.
>>
>> When your `choices` count is bigger than 1, you'll see your desired
>> behavior because CheckboxInterceptor does nothing with following message
>> where value.isMultiple() is true:
>>
>> ```java
>> if(value.isMultiple()) {
>>      LOG.debug("Bypassing automatic checkbox detection due to multiple
>> checkboxes of the same name: {}", name);
>> } else if(!parameters.contains(checkboxName)) {
>>      extraParams.put(checkboxName, new Request(checkboxName,
>> this.uncheckedValue));
>> }
>> ```
>>
>> But what happens when your `choices` count is one and you don't click on
>> that one (your current example): Actually W3C says unchecked checkbox
>> wont be posted, so, the above else will be executed (because
>> !parameters.contains(checkboxName) is true) and CheckboxInterceptor sets
>> a new parameter, "itemsFail->false". Then OGNL cannot convert `false` to
>> an array of Integer into your action, so, the result will be changed to
>> `input`.
>>
>> I searched how to also post unchecked check boxes and found out that
>> following makes your example working:
>> ```jsp
>> <s:iterator var="choice" value="%{choices}">
>>      <s:hidden value='0' name='itemsFail'/><!-- I added this; a default
>> -->
>>      <s:checkbox name="itemsFail" fieldValue="%{choice}"
>> value="%{isItemsFailSelected(#choice)}"/> <s:property
>> value="%{#choice}"/>
>> </s:iterator>
>> ```
>>
>> Hope these help!
>> Yasser.
>>
>> On 10/1/2017 6:57 AM, Burton Rhodes wrote:
>> > Well shoot - after further testing it seems the issue is still
>> present.  I
>> > isolated the issue in a simple mvn webapp (see link below).  Essentially
>> > Struts conversion fails when: 1) setting form input element to a
>> > List<Integer>, 2) there is only one checkbox in the list, 3) the
>> checkbox
>> > is not checked when the form is submitted.  The situation arises for me
>> > when I need to display a list of checkboxes, but I can't use
>> > <s:checkboxlist/> tag because the page requires a more advanced html
>> > layout.  Thus I am forced to display the checkbox list using an
>> > <s:iterator/> and the <s:checkbox/> tag.  If the displayed list so
>> happens
>> > to have only one element, and the user doesn't check it, the conversion
>> > fails.
>> >
>> > I am using now Struts Version 2.5.13.
>> >
>> > *Test Struts Webb App*
>> > *Download*: https://www.dropbox.com/s/x27o9a8qky9nwta/listTest.zip?dl=0
>> > *Action*: mvn jetty:run
>> > *Url*: http://localhost:8080/ListConverterTest.action
>> >
>> > On Fri, Sep 29, 2017 at 10:56 AM, Burton Rhodes <burtonrho...@gmail.com
>> >
>> > wrote:
>> >
>> >> Sorry for the delay.  I have upgraded to the newest version and
>> everything
>> >> seems to be working.  Thanks!
>> >>
>> >> On Mon, Sep 25, 2017 at 2:34 AM, Lukasz Lenart <
>> lukaszlen...@apache.org>
>> >> wrote:
>> >>
>> >>> 2017-09-25 5:04 GMT+02:00 Burton Rhodes <burtonrho...@gmail.com>:
>> >>>> When extending the StrutsTypeConverter, is there anyway to figure
>> out if
>> >>>> the "toClass" is a List<Integer> or a List<String>?  I have found
>> that
>> >>> when
>> >>>> converting data from a submitted webpage that has a value of a List
>> in a
>> >>>> single variable, the standard struts conversion fails.  For example:
>> >>>> <s:hidden name="integerList" value="%{integerList}" /> display as
>> >>> <s:hidden
>> >>>> name="integerList" value="[1,2,3,4,5]" />.  When the form submits,
>> this
>> >>>> value will not convert properly back into the List.  In addition, the
>> >>>> conversion fails if you have a list of checkboxes and the user only
>> >>> checks
>> >>>> one -  hence only a single variable being converted to a List.
>> >>>>
>> >>>> I have solved this issue by creating a MyListConverter, but I have to
>> >>>> declare the converter on each action in a [-conversion.properties]
>> file
>> >>>> which is now becoming a bit cumbersome since this is such a common
>> >>>> occurrence. I have also declared some on my model/entity beans, but
>> >>>> still.... I would love to have a more global "List" converter, such
>> as:
>> >>>>
>> >>>> [xwork-conversion.properties]
>> >>>> java.util.List=com.afs.web.converter.MyListConverter
>> >>>>
>> >>>> Thus any List that is encountered, I could attempt "my conversion"
>> and
>> >>> send
>> >>>> up the chain of command if the resulting List is not of
>> List<Integer> or
>> >>>> List<String>.
>> >>>>
>> >>>> [Psuedo_Code]
>> >>>> public class MyListConverter extends StrutsTypeConverter {
>> >>>>      public Object convertFromString(Map context, String[] values,
>> Class
>> >>>> toClass) {
>> >>>>          // Is toClass List<Integer>, then try "my" conversion
>> >>>>
>> >>>>          // Else is toClass List<String?, then try "my" conversion
>> >>>>
>> >>>>          // Else return performFallbackConversion(context, o,
>> toClass);
>> >>>>      }
>> >>>> }
>> >>>>
>> >>>> Any ideas?  Or am I going about this incorrectly?
>> >>>
>> >>> What version of Struts do you use? I think this was resolved in 2.5.13
>> >>> or 2.5.12 - I meant conversion of list of built-in types (ints,
>> >>> doubles, etc), to convert your own type just register it (as for the
>> >>> List above).
>> >>>
>> >>>
>> >>> Regards
>> >>> --
>> >>> Ɓukasz
>> >>> + 48 606 323 122 <+48%20606%20323%20122> http://www.lenart.org.pl/
>> >>>
>> >>> ---------------------------------------------------------------------
>> >>> To unsubscribe, e-mail: user-unsubscr...@struts.apache.org
>> >>> For additional commands, e-mail: user-h...@struts.apache.org
>> >>>
>> >>>
>> >>
>> >
>>
>
>

Reply via email to