001// Copyright 2006-2013 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 015package org.apache.tapestry5.corelib.components; 016 017import org.apache.tapestry5.*; 018import org.apache.tapestry5.annotations.AfterRender; 019import org.apache.tapestry5.annotations.BeginRender; 020import org.apache.tapestry5.annotations.Mixin; 021import org.apache.tapestry5.annotations.Parameter; 022import org.apache.tapestry5.corelib.base.AbstractField; 023import org.apache.tapestry5.corelib.mixins.RenderDisabled; 024import org.apache.tapestry5.dom.Element; 025import org.apache.tapestry5.ioc.annotations.Inject; 026import org.apache.tapestry5.services.compatibility.Compatibility; 027import org.apache.tapestry5.services.compatibility.Trait; 028 029/** 030 * A Checkbox component is simply a <input type="checkbox">. 031 * 032 * @tapestrydoc 033 */ 034public class Checkbox extends AbstractField 035{ 036 /** 037 * The value to be read or updated. If not bound, the Checkbox will attempt to edit a property of its container 038 * whose name matches the component's id. 039 */ 040 @Parameter(required = true, autoconnect = true) 041 private boolean value; 042 043 /** 044 * The object that will perform input validation. The validate binding prefix is 045 * generally used to provide this object in a declarative fashion. 046 */ 047 @Parameter(defaultPrefix = BindingConstants.VALIDATE, allowNull = false) 048 private FieldValidator<Object> validate; 049 050 @Mixin 051 private RenderDisabled renderDisabled; 052 053 @Inject 054 private Compatibility compatibility; 055 056 private boolean bootstrap4; 057 058 void pageLoaded() 059 { 060 bootstrap4 = compatibility.enabled(Trait.BOOTSTRAP_4); 061 } 062 063 @BeginRender 064 void begin(MarkupWriter writer) 065 { 066 String asSubmitted = validationTracker.getInput(this); 067 068 boolean checked = asSubmitted != null ? Boolean.parseBoolean(asSubmitted) : value; 069 070 writer.element("input", "type", "checkbox", 071 "name", getControlName(), 072 "id", getClientId(), 073 "checked", checked ? "checked" : null); 074 075 putPropertyNameIntoBeanValidationContext("value"); 076 077 validate.render(writer); 078 079 removePropertyNameFromBeanValidationContext(); 080 081 resources.renderInformalParameters(writer); 082 083 if (bootstrap4) 084 { 085 final Element element = writer.getElement(); 086 String classAttribute = element.getAttribute("class"); 087 classAttribute = classAttribute != null ? "form-check-input " + classAttribute : "form-check-input"; 088 element.forceAttributes("class", classAttribute); 089 } 090 091 decorateInsideField(); 092 } 093 094 @AfterRender 095 void after(MarkupWriter writer) 096 { 097 writer.end(); // input 098 } 099 100 @Override 101 protected void processSubmission(String controlName) 102 { 103 String postedValue = request.getParameter(controlName); 104 105 boolean translated = postedValue != null; 106 107 // record as "true" or "false" 108 validationTracker.recordInput(this, Boolean.toString(translated)); 109 110 putPropertyNameIntoBeanValidationContext("value"); 111 try 112 { 113 fieldValidationSupport.validate(translated, resources, validate); 114 115 value = translated; 116 } catch (ValidationException ex) 117 { 118 validationTracker.recordError(this, ex.getMessage()); 119 } 120 removePropertyNameFromBeanValidationContext(); 121 } 122 123 /** 124 * Computes a default value for the "validate" parameter using 125 * {@link org.apache.tapestry5.services.FieldValidatorDefaultSource}. 126 */ 127 final Binding defaultValidate() 128 { 129 return defaultProvider.defaultValidatorBinding("value", resources); 130 } 131}