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    }