    001    // Copyright 2007, 2008, 2010, 2011 The Apache Software Foundation
    002    //
    003    // Licensed under the Apache License, Version 2.0 (the "License");
    004    // you may not use this file except in compliance with the License.
    005    // You may obtain a copy of the License at
    006    //
    007    // http://www.apache.org/licenses/LICENSE-2.0
    008    //
    009    // Unless required by applicable law or agreed to in writing, software
    010    // distributed under the License is distributed on an "AS IS" BASIS,
    011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012    // See the License for the specific language governing permissions and
    013    // limitations under the License.
    014
    015    package org.apache.tapestry5.corelib.components;
    016
    017    import org.apache.tapestry5.BindingConstants;
    018    import org.apache.tapestry5.ComponentResources;
    019    import org.apache.tapestry5.Field;
    020    import org.apache.tapestry5.MarkupWriter;
    021    import org.apache.tapestry5.RadioContainer;
    022    import org.apache.tapestry5.annotations.Environmental;
    023    import org.apache.tapestry5.annotations.Mixin;
    024    import org.apache.tapestry5.annotations.Parameter;
    025    import org.apache.tapestry5.corelib.mixins.DiscardBody;
    026    import org.apache.tapestry5.corelib.mixins.RenderDisabled;
    027    import org.apache.tapestry5.corelib.mixins.RenderInformals;
    028    import org.apache.tapestry5.ioc.annotations.Inject;
    029    import org.apache.tapestry5.services.ComponentDefaultProvider;
    030    import org.apache.tapestry5.services.javascript.JavaScriptSupport;
    031
    032    /**
    033     * A radio button (i.e., &lt;input type="radio"&gt;). Radio buttons <strong>must</strong> operate within a
    034     * {@link RadioContainer} (normally, the {@link RadioGroup} component).
    035     * <p/>
    036     * If the value parameter is not bound, then the default value is a property of the container component whose name
    037     * matches the Radio component's id.
    038     *
    039     * @tapestrydoc
    040     * @see RadioGroup
    041     * @see Form
    042     * @see Select
    043     */
    044    public class Radio implements Field
    045    {
    046        @Environmental
    047        private RadioContainer container;
    048
    049        /**
    050         * The user presentable label for the field. If not provided, a reasonable label is generated from the component's
    051         * id, first by looking for a message key named "id-label" (substituting the component's actual id), then by
    052         * converting the actual id to a presentable string (for example, "userId" to "User Id").
    053         */
    054        @Parameter(defaultPrefix = BindingConstants.LITERAL)
    055        private String label;
    056
    057        /**
    058         * The value associated with this radio button. This is used to determine which radio button will be selected when
    059         * the page is rendered, and also becomes the value assigned when the form is submitted.
    060         */
    061        @Parameter(required = true, principal = true, autoconnect = true)
    062        private Object value;
    063
    064        @Inject
    065        private ComponentDefaultProvider defaultProvider;
    066
    067        @Inject
    068        private ComponentResources resources;
    069
    070        @SuppressWarnings("unused")
    071        @Mixin
    072        private RenderInformals renderInformals;
    073
    074        @SuppressWarnings("unused")
    075        @Mixin
    076        private RenderDisabled renderDisabled;
    077
    078        @SuppressWarnings("unused")
    079        @Mixin
    080        private DiscardBody discardBody;
    081
    082        @Inject
    083        private JavaScriptSupport jsSupport;
    084
    085        private String clientId;
    086
    087        private String controlName;
    088
    089        /**
    090         * If true, then the field will render out with a disabled attribute (to turn off client-side behavior). Further, a
    091         * disabled field ignores any value in the request when the form is submitted.
    092         */
    093        @Parameter("false")
    094        private boolean disabled;
    095
    096        String defaultLabel()
    097        {
    098            return defaultProvider.defaultLabel(resources);
    099        }
    100
    101        /**
    102         * Returns the control name provided by the containing {@link org.apache.tapestry5.RadioContainer}.
    103         */
    104        public String getControlName()
    105        {
    106            return controlName;
    107        }
    108
    109        public String getLabel()
    110        {
    111            return label;
    112        }
    113
    114        /**
    115         * Returns true if this component has been expressly disabled (via its disabled parameter), or if the
    116         * {@link RadioContainer container} has been disabled.
    117         */
    118        public boolean isDisabled()
    119        {
    120            return disabled || container.isDisabled();
    121        }
    122
    123        public String getClientId()
    124        {
    125            return clientId;
    126        }
    127
    128        void beginRender(MarkupWriter writer)
    129        {
    130            String value = container.toClient(this.value);
    131
    132            clientId = jsSupport.allocateClientId(resources);
    133            controlName = container.getControlName();
    134
    135            writer.element("input", "type", "radio", "id", clientId, "name", controlName, "value", value);
    136
    137            if (container.isSelected(this.value))
    138                writer.attributes("checked", "checked");
    139        }
    140
    141        void afterRender(MarkupWriter writer)
    142        {
    143            writer.end();
    144        }
    145
    146        /**
    147         * Returns false; the RadioComponent component does not support declarative field validation.
    148         */
    149        public boolean isRequired()
    150        {
    151            return false;
    152        }
    153    }