It looks like this solution below might work, but I haven't got very far with it yet.
In my builder class I've added an inner class called Editor:
com.example.MyBuilder(.Editor):
...
public static class Editor {
private final String id;
public Editor(final String id) {
this.id = id;
}
public String getId() {
return id;
}
}
...
Then in the descriptor Java class, provide a JavaScript function to create one of these with a unique ID:
com.example.MyBuilder.DescriptorImpl:
private int lastEditorId = 0;
@JavaScriptMethod
public synchronized Editor createEditor() {
return new Editor(String.valueOf(lastEditorId++));
}
Then in my jelly file I call that method and pass the returned object into st:include
, loading a new jelly file to render the fields:
com/example/MyBuilder/config.jelly:
<st:include page="editor.jelly" it="${descriptor.createEditor()}" />
(Although this appears to have to be inside an f:entry
element - or perhaps other elements, I haven't tried - otherwise it doesn't seem to get included when a new build step for this builder is added to the job config.)
And finally I create that new editor.jelly
file to render the fields (which has to be in a folder whose name reflects the Editor
class, as the it
object being passed into st:include
is of type Editor
):
com/example/MyBuilder/Editor/editor.jelly:
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<l:ajax>
<f:entry title="Field">
<f:textbox field="field" id="field-${it.id}"/>
<p id="message-${it.id}"></p>
</f:entry>
<script>
setTimeout(function(){
var field = document.getElementById('field-${it.id}');
var p = document.getElementById('message-${it.id}');
p.textContent = "Initial value: "+field.value;
}, 50);
</script>
</l:ajax>
</j:jelly>
(The call to setTimeout
is due to the fact that when adding new build steps, the elements haven't been added to the DOM by the time that the script executes, so the script execution has to be deferred slightly).
However, this breaks the link between the f:entry
elements and the equivalent fields in the builder class, and I'm not sure what to do about that. So this is an incomplete answer.
EDIT: I'm not sure if the f:entry
elements would have worked or not, as I had forgotten to add the field to the builder class when I was testing it, which was (at least one reason) why I did not see any data saved from this field when I tried this. However, I am now using the solution from my other answer, so I have not gone back to test whether it would have worked or not.