I have a problem adding to a variable which is a map in velocity that has been passed as an attribute for a macro.
Consider the following code:
#macro ( test $attr )
1 $attr.edd
#set($attr.edd = "edd")
2 $attr.edd
#set($foo = {"bar" : "bar" })
3 $foo.edd
#set($foo.edd = "edd")
4 $foo.edd
#end
#test({"bar" : "bar" })
I would expect the following output:
1 $attr.e开发者_如何学Cdd 2 edd 3 $foo.edd 4 edd
But I get:
1 $attr.edd 2 $attr.edd 3 $foo.edd 4 edd
Can anyone solve this issue for me?
This is pretty gross but I'm guessing the attribute is final (seems a bit odd/dangerous considering the way velocity treats variables) so redefining the variable seems to solve the issue:
#macro ( test $attr )
#set($attr = $attr)
1 $attr.edd
#set($attr.edd = "edd")
2 $attr.edd
#set($foo = {"bar" : "bar" })
3 $foo.edd
#set($foo.edd = "edd")
4 $foo.edd
#end
#test({"bar" : "bar" })
I'm hoping someone else will have a better solution...
Using Map.key is a shortcut in velocity to calling Map.get(key). So when you say $attr.edd velocity is really doing Map.get("edd") behind the scenes and returning you a the value of that map entry.
I think what's happening in your case is that you're trying to assign the string "edd" to the return value of Map.get("edd") which is a just a String and not a reference back to that Map entry. Because of the order of execution $attr.edd is already resolved to the return value of Map.get("edd") before the equals side of the equation executed.
For example what you're doing is just the short hand equivalent of the following:
#set($value = $attr.edd) // Set value to the return value of Map.get("edd") which is null
#set($value = "edd") // Value is just a string so this is like saying String value = "edd"
$value // prints "edd"
$attr.edd // is still null because you you never assigned anything to it.
If you want to change the value of that entry you'll need to use Map.set("edd", "edd"). I don't beleive there is a short hand way to call set so you'll just call $attr.set("edd", "edd") as you would in java code.
There is another caveat however. Velocity doesn't just let you call a method that returns void because the idea is you're using it to display properties and values and thus you should never need a void method.
$attr.set("edd", "edd") // throws and error because it's trying to display a void
When we need to do this we kind of hack it by assigning it to a variable we never use
#set($nothin = $attr.set("edd", "edd"))
$attr.edd // prints edd now
Kind of hacky but the concept behind velocity and MVC in general is that by the time things get to your view layer they should populated with everything they need and treated as read only. However the world is seldom so black and white and this sort of thing is sometimes necessary.
EDIT:
BTW, the reason your last example of setting $foo.edd to "edd" actually prints out edd isn't because you've successfully changed the array value, it's because you've created a new velocity variable named "foo.edd" which is a string.
精彩评论