Skip to content

Instantly share code, notes, and snippets.

@sody
Created September 14, 2012 08:27
Show Gist options
  • Save sody/3720750 to your computer and use it in GitHub Desktop.
Save sody/3720750 to your computer and use it in GitHub Desktop.
Tapestry Fixed Control Name Fixin
@SupportsInformalParameters
public abstract class AbstractField implements Field {
@SetupRender
final void setup() {
String id = clientId;
if (formSupport == null)
throw new RuntimeException(String.format("Component %s must be enclosed by a Form component.",
resources.getCompleteId()));
assignedClientId = jsSupport.allocateClientId(id);
String controlName = formSupport.allocateControlName(id);
formSupport.storeAndExecute(this, new Setup(controlName));
formSupport.store(this, PROCESS_SUBMISSION_ACTION);
}
}
<t:form t:id="afterForm">
<t:zone t:id="afterZone" t:mixins="FixedControlName">
<t:label for="afterCountrySelect"/>
<t:select t:id="afterCountrySelect"
value="country"
model="countryModel"
zone="prop:afterZoneId"
label="message:label.country"/>
<t:label for="afterCitySelect"/>
<t:select t:id="afterCitySelect"
value="city"
model="cityModel"
label="message:label.city"/>
</t:zone>
</t:form>
<div class="t-zone" id="beforeZone_139c3db913f">
<input value="..." name="t:formdata" type="hidden"/>
<label for="beforeCountrySelect_139c3db913f">Country</label>
<select id="beforeCountrySelect_139c3db913f" name="beforeCountrySelect_139c3db913f">
<!-- Options goes here -->
</select>
<label for="beforeCitySelect_139c3db913f">City</label>
<select id="beforeCitySelect_139c3db913f" name="beforeCitySelect_139c3db913f">
<!-- Options goes here -->
</select>
</div>
<t:form t:id="beforeForm">
<t:zone t:id="beforeZone">
<t:label for="beforeCountrySelect"/>
<t:select t:id="beforeCountrySelect"
value="country"
model="countryModel"
zone="prop:beforeZoneId"
label="message:label.country"/>
<t:label for="beforeCitySelect"/>
<t:select t:id="beforeCitySelect"
value="city"
model="cityModel"
label="message:label.city"/>
</t:zone>
</t:form>
<div class="t-zone" id="beforeZone">
<input value="..." name="t:formdata" type="hidden"/>
<label for="beforeCountrySelect">Country</label>
<select id="beforeCountrySelect" name="beforeCountrySelect">
<!-- Options goes here -->
</select>
<label for="beforeCitySelect">City</label>
<select id="beforeCitySelect" name="beforeCitySelect">
<!-- Options goes here -->
</select>
</div>
public class Select extends AbstractField
@BeforeRenderTemplate
void options(MarkupWriter writer) {
selectedClientValue = tracker.getInput(this);
if (selectedClientValue == null)
selectedClientValue = value == null ? null : encoder.toClient(value);
// ...
SelectModelVisitor renderer = new Renderer(writer);
model.visit(renderer);
}
}
public abstract class AbstractTextField extends AbstractField
@BeginRender
void begin(MarkupWriter writer) {
String value = tracker.getInput(this);
if (value == null) {
value = fieldValidationSupport.toClient(this.value, resources, translate, nulls);
}
writeFieldTag(writer, value);
// ...
}
}
public class Select extends AbstractField
protected void processSubmission(String controlName) {
String submittedValue = request.getParameter(controlName);
tracker.recordInput(this, submittedValue);
// ...
}
}
public abstract class AbstractTextField extends AbstractField
protected void processSubmission(String controlName) {
String rawValue = request.getParameter(controlName);
tracker.recordInput(this, rawValue);
// ...
}
}
public class FixedControlName {
/**
* This parameter defines namespace for control names. It will use {@code fixed} namespace by default.
*/
@Parameter(defaultPrefix = BindingConstants.LITERAL, value = "fixed", allowNull = false)
private String namespace;
@Inject
private Environment environment;
private boolean insideForm;
@BeforeRenderBody
void changeFormSupport() {
final FormSupport existingFormSupport = environment.peek(FormSupport.class);
insideForm = existingFormSupport != null;
if (insideForm) {
// replace FormSupport with hacked wrapper
environment.push(FormSupport.class, new FormSupportAdapter(existingFormSupport) {
private final IdAllocator allocator = new IdAllocator("_" + namespace);
@Override
public String allocateControlName(final String id) {
return allocator.allocateId(id);
}
});
}
}
@AfterRenderBody
void restoreFormSupport() {
if (insideForm) {
// remove hacked FormSupport wrapper
environment.pop(FormSupport.class);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment