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 }