public class product {
private String name;
private String path;
// and getter setter of attributes
}
I want to get the path value from the bean and give this path value in "img src" tag.
I know that print the path attribute value but my question is that use this path value in img tag to upload this image
Assuming ModelDriven with a product as the model:
<img src="<s:property value='path'/>"/>
<%-- You can also use JSP EL --%>
<img src="${path}"/>
If there's an action property instead, use normal bean notation:
<img src="<s:property value='product.path'/>"/>
<img src="${product.path}"/>
Related
To make this simple, let's assume we have a template html file(test.htm) like this:
<div th:fragment="test">
this is a test fragment
</div>
<div th:include=":: test"> <!-- we'll change this line later -->
this is a placeholder
</div>
And the following controller is used to return test.htm:
#Controller
public class HomeController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView get(ModelAndView mav) {
mav.setViewName("/test.htm");
mav.addObject("fragmentName", ":: test"); // we'll use this later
return mav;
}
}
In this case, we can get the following result if we access home index:
this is a test fragment
this is a test fragment
But if we use a variable fragmentName to set th:include value like this:
<div th:fragment="test">
this is a test fragment
</div>
<div th:include="${fragmentName}"> <!-- modified to use a variable value -->
this is a placeholder
</div>
Thymeleaf complains that this template ":: test" cannot be resolved:
There was an unexpected error (type=Internal Server Error, status=500).
Error resolving template [:: test], template might not exist or might not be accessible by any of the configured Template Resolvers (template: "/test.htm" - line 5, col 6)
Here comes the question: is there a way to set the th:include value using a variable?
You can use the Thymeleaf expression preprocessing:
<div th:include="__${fragmentName}__">
this is a placeholder
</div>
Basically you instructed thymeleaf to preprocess first __${fragmentName}__ and after resolving the value to use it in the normal processing phase when evaluates the th:include as if it was a static value th:include=":: test"
As in Struts n JSF, we link a form to a bean(eg. backing bean in JSF).
But in grails, we are using params to set values of the bean. Is there any other way to automatically map a form to the bean?
Grails has the possibility to auto bind values from the params map to a given domain instance / command object. This can be achieved by defining the correct beans as a parameter for your controller methods. Take this example:
Controller:
class AuthorController {
def save(Author author) {
// matching param values are bound to the author instance
assert params.name == "myName"
assert author.name == "myName"
}
}
gsp with form:
<g:form controller="author" action="save">
<g:field name="name" value="myName" />
<g:submitButton name="save" value="Save" />
</g:form>
Sometimes is better to use the Command Objects provided by Grails, the domain class can be wrapped only matching the name of the form fields with the attributes names of the class.
But Command Objects can provide an intermediate layer of validation and abstraction to generate the model bean.
http://grails.org/doc/2.3.0/guide/single.html#commandObjects
I have the following domain classes:
Airport:
class Airport {
String airportName
List<Flight> flights
static hasMany = [flights: Flight]
static mappedBy = [flights: "departureAirport"]
}
Flight:
class Flight {
String flightName
Integer numOfStaff
Airport departureAirport
}
I have in a form the following input fields which is correctly prints the saved airport and it's flights:
<input name="airportName" value="${airportInstance.airportName}" />
<input name="id" value="${airportInstance.id}" />
<input name="version" value="${airportInstance.version}" />
<g:set var="counter" value="${0}" />
<g:each in="${airportInstance?.flights?}" var="f">
<div>
name : <input name="flights[${counter}].flightName" value="${f.flightName}" />
id : <input name="flights[${counter}].id" value="${f.id}" />
numOfStaff : <input name="flights[${counter}].numOfStaff" value="${f.numOfStaff}" />
<g:set var="counter" value="${counter + 1}" />
</div>
</g:each>
I post the form to the following controller action:
#Transactional
def update() {
Airport airportInstance = Airport.get(params.id)
// doesn't work as well
// airportInstance.properties = params
bindData(airportInstance, params)
airportInstance.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(
code: 'default.updated.message',
args: [
message(
code: 'Airport.label',
default: 'Airport'
),
airportInstance.id
]
)
redirect airportInstance
}
'*'{ respond airportInstance, [status: OK] }
}
}
When I modify airportName or some of the flights properties (e.g.: numOfStaff) and I click update (post it to the controller action), Grails does his work correctly and updates my changes.
But if I manually add a new instance in the view e.g.: if there were two flights flights[0] and flights[1] listed by g:each and I add flights[2] it doesn't create a new instance of Flight and doesn't save it.
The same if I try to delete an existing flight from the view and post it to the controllers update action.
I'm using grails version 2.3.9
My questions are:
Am I doing something wrong?
Is it a Grails bug or Grails developers implemented bindData method like this for some reason?
What is the best way in Grails to implement issue like above (I mean giving the name attributes like foo[index].prop where foo is a collection in the entity).
Sorry for the junk html.
Thank you guys, for the answers.
I found the solution. If I declare a controller action like:
def update(Airport airport) {
// ...
}
In this case before the controller action is executed Grails will automatically create an instance of the Airport class and populate its properties by binding the request parameters.
If there is an id request parameter then instead of invoking the domain class constructor to create a new instance a call will be made to the static get method on the domain class and the value of the id parameter will be passed as an argument. Whatever is returned from that call to get is what will be passed into the controller action. This means that if there is an id request parameter and no corresponding record is found in the database then the value of the command object will be null.
See Grails Reference Documentation: http://grails.org/doc/latest/guide/theWebLayer.html#commandObjects
How can I set attributes when my model property is rendered with any Html helper?
Example:
I have my custom data annotation:
[MyCustomAttribute(AnyHtmlProperty = "100")]
public string Name{get;set;}
So, when this property is rendered, I want something like this:
<input type="text" anyHtmlProperty="100" />
You could write an HtmlHelper extension method which accepts an expression. Here's a non-functioning example of what the razor syntax would look like.
#Html.CustomInputFor(x => x.Name)
I'm trying to do something pretty simple, that apparently is not that simple. I have a domain class:
class Regex {
String name
String Regex
}
and another class:
class RegexRef {
int sequenceNumber
Product product
Regex regex
}
Now, in a select, I want to list the RegexRef instances, with the name of the regex as the optionValue as such:
<g:select name="regexRef.id" from="${com.mycompany.RegexRef.list()}" optionKey="id" size="5" optionValue="regex.name" value="${actionRefInstance?.regexRef?.id}" />
but this doesn't work. It throws:
Exception Message: No such property: regex.name for class: com.jetheaddev.RegexRef
I can do this mis-direction in other constructs...
<g:link controller="regexRef" action="show" id="${actionRefInstance?.regexRef?.id}">${actionRefInstance?.regexRef?.regex.name.encodeAsHTML()}</g:link>
and it works fine.
With optionValue="regex.name" the <g:select/> is trying to retrieve the property of RegexRef as:
regexRefInstance."regex.name"
To retrieve the name property on the Regex class do:
<g:select optionValue="${{it.regex.name}}"/>
which will run the optionValue Closure on each entry in the list and retrieve the related name property.