    001    // Copyright 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    package org.apache.tapestry5.corelib.components;
    015
    016    import org.apache.tapestry5.BindingConstants;
    017    import org.apache.tapestry5.CSSClassConstants;
    018    import org.apache.tapestry5.Field;
    019    import org.apache.tapestry5.MarkupWriter;
    020    import org.apache.tapestry5.ValidationTracker;
    021    import org.apache.tapestry5.annotations.Environmental;
    022    import org.apache.tapestry5.annotations.HeartbeatDeferred;
    023    import org.apache.tapestry5.annotations.Parameter;
    024    import org.apache.tapestry5.corelib.internal.InternalMessages;
    025    import org.apache.tapestry5.dom.Element;
    026
    027    /**
    028     * Presents validation errors of a single field. Must be enclosed by a
    029     * {@link org.apache.tapestry5.corelib.components.Form} component.
    030     *
    031     * @since 5.2.0
    032     * @tapestrydoc
    033     */
    034    public class Error
    035    {
    036        /**
    037         * The for parameter is used to identify the {@link Field} to present errors of.
    038         */
    039        @Parameter(name = "for", required = true, allowNull = false, defaultPrefix = BindingConstants.COMPONENT)
    040        private Field field;
    041
    042        /**
    043         * The CSS class for the div element rendered by the component. The default value is "t-error-single".
    044         */
    045        @Parameter(name = "class")
    046        private String className = CSSClassConstants.ERROR_SINGLE;
    047
    048        @Environmental(false)
    049        private ValidationTracker tracker;
    050
    051        void beginRender(final MarkupWriter writer)
    052        {
    053            if (tracker == null)
    054                throw new RuntimeException(InternalMessages.encloseErrorsInForm());
    055
    056            Element element = writer.element("div");
    057
    058            updateElement(element);
    059
    060            writer.end();
    061        }
    062
    063        @HeartbeatDeferred
    064        private void updateElement(final Element element)
    065        {
    066            final String error = tracker.getError(field);
    067
    068            if (error == null)
    069            {
    070                element.remove();
    071            }
    072            else
    073            {
    074                element.forceAttributes("class", className);
    075                element.text(error);
    076            }
    077        }
    078
    079    }