I'm trying to reduce some repetitive GSP code in my Grails app. The following code works as expected:
<g:textField name="recordValues.0.name" value="${recordValues?.get(0)?.name}"/>
<g:textField name="recordValues.0.age" value="${recordValues?.get(0)?.age}"/>
[edit]recordValues.0.age is actually a Map not a class property, as I originally stated.
However when I try to dynamically set a bunch of these with a list enum, the value attribute is not evaluated:
<g:each in="${fields}" var="prop">
<g:textField name="recordValues.0.${prop}" value="${recordValues?.get(0)?.prop}"/>
</g:each>
It appears the value attribute is looking for the property Map key called "prop" and is not evaluating it as a variable. I've tried recordValues?.get(0)[prop] with and without ? between but it didn't compile.
Is there some dynamic method I can call with the variable as an argument or an even easier solution?
Sorted it myself in the end. Thanks to codespace for making me check the code again and noticing it was a Map I was trying to reference, not an object property. The fact I was using an enum confused the issue as using the regular map.get(var) did not work, I needed map.get(var.name()) instead (maybe I'll encode it as a String field inside the enum to avoid this).
Here's the solution:
<g:each in="${fields}" var="prop">
<g:textField name="recordValues.0.${prop}" value="${recordValues?.get(0)?.get(prop.name())}"/>
</g:each>
Related
I've been experimenting with Ashley Grant's post: https://bl.ocks.org/AshleyGrant/07e645e46f7cc945b4e43c4ec80c6424
and was wondering if anyone knows how to go one step further and apply a value converter after using the 'dynamicExpression' Binding Behavior. Something like this:
<input type="text" value.bind="model & dynamicExpression:field.expression | formatNumber:'$###,###.00'" />
Thanks,
The documentation here http://aurelia.io/docs/binding/binding-behaviors#introduction states that value converters only observe the values passing by, but behaviors have full access to binding context.
I guess if you rewrite your formatNumber as a behavior - you can chain them.
I would like to know how can I know when to pass the value of attributes with an expression ${} and where not.
For example, in the next tag call why template and model attribute values are passed without ${} but collection attribute value is passed with ${}.
<g:render template="displaybook" model="['book':book,'author':author]" collection="${books}" />
I would like to learn how to read the grails tags documentation in this topic.
The ${} is only used for expressions that need to be evaluated, not for string literals.
<g:render template="displaybook" model="['book':book,'author':author]" collection="${books}" />
"displaybook" is a literal string, not a variable reference, so it doesn't make sense to put it in ${}.
"books" is a variable reference, so it does make sense to put it in ${}.
There is special handling when passing a literal collection like ['book':book,'author':author]. The parser will recognize the surrounding [...] and will evaluate the contents as an expression, not a string literal, so the ${} isn't necessary there.
I hope that helps.
See, if as the above answer says, you use ${} to evaluate something, for example this: "${book.author.name.toString()}", will return "Stephen King" for example, but if you put it like this "book.author.name.toString()" it will simply give you "book.author.name.toString()" this as a result. In addition, the symbol [something: 4, otherSomething: "what up"] is the same as this in java:
LinkedTreeMap<String,Object> map = new LinkedTreeMap<String,Object>();
map.put("something",4);
map.put("otherSomething","whats up");
It's just a veryyyyy easier way of creating a map without all the casting work, and stuff (that's one of the reasons groovy is so cool).
You can also do something like this:
def map = [:]
public void getObject(key){
if(map."${key}")
println(map."${key}") //this will print the object not the key, getObject("mobile") would print cellphone not "mobile" understand? That's awsome!
}
That means you can use runtime keys from variables =D.
That's it hope I have helped
I have a foreach element in my flow, which has a variable named "counter" set. Inside the foreach, I have a component, and I'm trying to get access to the "counter" variable from within the component. What is the proper way to get a hold of this variable from inside the component? Does it require adding a parameter to the method? I already have a parameter to take in the payload.
Any variable from the mule flow can be accessed inside a Component by using the
muleMessage.getInvocationProperty("counter");
muleMessage can be obtained from MuleEventContext of the onCall(MuleEventContext arg0) method. Assuming that you have implemented Callable interface of mule.
If not, try getting the message from org.mule.RequestContext.getEvent().getMessage()
This is RequestContext is deprecated as of now.
Hope this helps.
If we set the counter value in a property, we can get that property in inbound properties of message inside the component.
some thing like this
<set-variable variableName="counter" value="10" />
<set-property propertyName="testout" value="#[counter]" doc:name="Property" />
Thanks-
I followed the example here: Why does <h:inputText required="true"> allow blank spaces? to create a "Global" converter to trim all input fields. However, the converter is not being invoked when input fields are submitted.
#FacesConverter(forClass=String.class)
...
<p:inputText value="#{controller.inputValue}"/>
but when I change to:
#FacesConverter("StringTrimmer")
...
<p:inputText value="#{controller.inputValue}" converter="StringTrimmer"/>
it works.
Using Mojarra 2.1.7 and PrimeFaces 3.2
A converter with a forClass will only be invoked whenever the type of the property is an instance of the specified class. In your particular case, that can only mean that the #{controller.inputValue} is not of type String.
If you checked that the bound variable is of type String and the converter still doesn't get called, you may also check the following:
If the input component is encapsulated inside a composite component, you may have this issue. In that case, converters would not be called correctly, resulting in your custom method to be never reached. Calling the converter explicitly on the input component solves this.
If you add both value="someName" and forClass="someClass" to the #FacesConverter annotation, the forClass attribute will be ignored. This has been reported here.
This didnt work because the inputValue was not actually of type String. Once changed to type String-- it worked.
I see that mvc is finding the names of the variables passed to it from the lambda function in an Html.DisplayFor method:
#Html.HiddenFor(model => myModel.propA.propB)
could generate HTML something like:
<input id="myModel_propA_propB" type="hidden" value="" >
it is obviously using reflection, but it is beyond me. could someone fill me in?
ALSO, is it possible to create an HTML helper function that takes a fully property reference instead of a lambda function to accomplish something similar? ie.
#Html.HiddenFor(myModel.propA.propB)
...and the helper could be passed the full "myModel.propA.propB" reference and not just the value of propB? is a lambda function an odd .net workaround to accomplish this sort of task or is it actually the preferred approach across all programming disciplines.
Actually, it is traversing the Expression tree you pass into helper method in order to get the property names. In practice, it would look something like:
MemberExpression memberExpression = (MemberExpression) expression.Body;
propertyName = memberExpression.Member.Name;
Of course that is not complete - for instance, you would have to walk up the chain of Expressions when there are multiple property invocations in the expression passed in, you would have to account for other expression types being passed in than MemberExpression, etc., etc. - but you get the idea. Remember that an Expression is a code expression represented as data. Also, since MVC is open source, you could look up the exact code they use to arrive at the html name in the sources, if you want.
To address your second question, the answer is no. Passing "just the property" without the lambda (which will be an Expression<Func<T,object>>), will not work, because then the function can only see the value passed in - and nothing about how the calling code arrived at that value.