How do I use the field tag in a user defined tag with the Play! Framework?
Right now I have a view like this that works.
#{form @UserCreate.create()}
#{field 'user.email'}
#{text field /}
#{/field}
#{/form}
With a corresponding text tag defined which then uses the field (it is more complicated than this, just boiling down to essentials)
<input type="text" id="${_arg.id}" name="${_arg.name}" value="${_arg.value}">
Ideally I would rather have it so I did not have to declare the field in the view so it would look like this.
#{form @UserCreate.create()}
#{text 'user.email' /}
#{/form}
With a tag that looks like this.
#{field 'user.email'}
<input type="text" id="${field.id}" name="${field.name}" value="${field.val开发者_运维技巧ue}">
#{/field}
But the field.value always returns null because user is not in the tags' template binding. I am not really sure how to approach things at this point. Suggestions?
Hey I have an interesting workaround: Just write the first line of the custom tag
%{user = _user}%
#{field 'user.email'}
<input type="text" id="${field.id}" name="${field.name}" value="${field.value}">
#{/field}
This works for me :)
I don't believe you will be able to do what you want due to the way the #{field} tag works (see its code here).
Probably the best approach is to create a series of fast tags based on Field tag's code, without the part that renders the body (as you won't need it), even if it may mean a bit of code duplication. Once done you can refactor to extract some common sections and reduce the duplication.
I modified the field tag quite a bit myself. I still have to do this to use it :( :(
#{xfield objectId:'groupDbo.name',label:'Group Name', help:'Some help message', length:'50'}
#{text field/}
#{/xfield}
but I don't have to keep repeating this html at least......
<div class="entry">
<div class="spacer"></div>
<span class="label ${_arg.errorClass}">${_arg.label}</span>
<span class="input ${_arg.errorClass}">
<input type="text" class="inputtext" name="${_arg.name}" value="${_arg.value}" maxlength="${_arg.length}">
<a id="newinfo" class="help" title="${_arg.help}">${_arg.help}</a>
<span class="error">${_arg.error}</span>
</span>
<div style="clear: both;"></div>
</div>
This also fixes a bug(in 1.2.x) they have in the field tag in which that don't get private fields which is very annoying....(and adds more fields that should be there and are not)
public class TagHelp extends FastTags {
private static final Logger log = LoggerFactory.getLogger(TagHelp.class);
public static void _xfield(Map<?, ?> args, Closure body, PrintWriter out, ExecutableTemplate template, int fromLine) {
Map<String,Object> field = new HashMap<String,Object>();
Object objId = args.get("objectId");
if(objId == null || !(objId instanceof String))
throw new IllegalArgumentException("'objectId' param must be supplied to tag xfield as a String");
Object label = args.get("label");
if(label == null || !(label instanceof String))
throw new IllegalArgumentException("'label' param must be supplied to tag xfield as a String");
Object length = args.get("length");
if(length == null || !(length instanceof String))
throw new IllegalArgumentException("'length' param must be supplied to tag xfield as a String");
Object help = args.get("help");
if("".equals(help))
help = null;
String _arg = objId.toString();
Object id = _arg.replace('.','_');
Object flashObj = Flash.current().get(_arg);
Object flashArray = new String[0];
if(flashObj != null && !StringUtils.isEmpty(flashObj.toString()))
flashArray = field.get("flash").toString().split(",");
Object error = Validation.error(_arg);
Object errorClass = error != null ? "hasError" : "";
field.put("name", _arg);
field.put("label", label);
field.put("length", length);
field.put("help", help);
field.put("id", id);
field.put("flash", flashObj);
field.put("flashArray", flashArray);
field.put("error", error);
field.put("errorClass", errorClass);
String[] pieces = _arg.split("\\.");
Object obj = body.getProperty(pieces[0]);
if(obj != null){
if(pieces.length > 1){
for(int i = 1; i < pieces.length; i++){
try{
Field f = getDeclaredField(obj.getClass(), obj, pieces[i]);
f.setAccessible(true);
if(i == (pieces.length-1)){
try{
Method getter = obj.getClass().getMethod("get"+JavaExtensions.capFirst(f.getName()));
field.put("value", getter.invoke(obj, new Object[0]));
}catch(NoSuchMethodException e){
field.put("value",f.get(obj).toString());
}
}else{
obj = f.get(obj);
}
}catch(Exception e){
log.warn("Exception processing tag on object type="+obj.getClass().getName(), e);
}
}
}else{
field.put("value", obj);
}
}
body.setProperty("field", field);
body.call();
}
private static Field getDeclaredField(Class clazz, Object obj, String fieldName) throws NoSuchFieldException {
if(clazz == Object.class)
throw new NoSuchFieldException("There is no such field="+fieldName+" on the object="+obj+" (obj is of class="+obj.getClass()+")");
try {
return clazz.getDeclaredField(fieldName);
} catch(NoSuchFieldException e) {
return getDeclaredField(clazz.getSuperclass(), obj, fieldName);
}
}
}
精彩评论