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.
014package org.apache.tapestry5.corelib.components;
015
016import org.apache.tapestry5.BindingConstants;
017import org.apache.tapestry5.CSSClassConstants;
018import org.apache.tapestry5.Field;
019import org.apache.tapestry5.MarkupWriter;
020import org.apache.tapestry5.ValidationTracker;
021import org.apache.tapestry5.annotations.Environmental;
022import org.apache.tapestry5.annotations.HeartbeatDeferred;
023import org.apache.tapestry5.annotations.Parameter;
024import org.apache.tapestry5.corelib.internal.InternalMessages;
025import 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 */
034public 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}