Is there a construct to unwrap or access previously defined field in freemaker? - freemarker

I have a ftl file with content:
{
<#-- processor_tool is an existing field -->
"processor_tool" : {
<#if Trigger?has_content>
"vendor_trigger": "${VendorTrigger}"
</#if>
...
},
<#-- processor_all is new entry to the ftl file -->
"processor_all" : {
"timeout" : "${timeout}"
<#-- add all fields from "processor_tool" declared above -->
}
}
For the new entry, "processor_all", I want to add some new fields, and add all the fields that are present in "processor_tool" (an existing entry in the ftl file). Can I use some construct to unwrap the values inside "processor_tool" to "processor_all".
I could copy-paste the declarations inside "processor_tool", but this would voilate DRY and will require update at two places if there is a change in "processor_tool".

There are several ways to not repeat yourself. You could use a macro or you can opt to assign keys and values to a sequence and use those, or use a combination.
A small demo:
<#assign mySeq = {"attr1": "value1", "attr2": "value2"}>
<#assign mySeq += {"attr3": "value3"}>
<#macro myMacro myParam>
<#list myParam as propName, propValue>
${propName} = ${propValue}<#sep>,</#sep>
</#list>
</#macro>
<#myMacro myParam = mySeq/>
<#myMacro myParam = mySeq/>
You can try this at https://try.freemarker.apache.org/

Related

formatting data in Freemarketnet

Am using freemarketnet to replace macros with proper content. for that am sending json object from mvc controller to view. In view i want to read the json in object format.
Here is my code in view
<#import "../Shared/Master.ftl" as layout />
<#assign TitleContent in layout>
Home Page
</#assign>
<#assign Recipient = controller.ViewData.data>
${Recipient}
In my controller.cs
dynamic obj = JObject.Parse("{'contact':{ 'cx_outstandingamountid':{
'cx_outstandingamount':'ytest' } } }");
ViewData["data"] = obj;
return View();
Now the view is rendering as
{'contact':{ 'cx_outstandingamountid':{'cx_outstandingamount':'ytest' } } }
But i want to render as 'ytest'. for this i tried
${Recipient.contact.cx_outstandingamountid.cx_outstandingamount}
but it did not work. Can anyone help me?
We need to use eval to parse the json in freemarker. Refer here.
<#assign recip=controller.ViewData.data>
<#assign Recipient = recip?eval>
${Recipient.contact.acsi_outstandingamountid.acsi_outstandingamount}

Display tag external sort overriden?

I am using display tag and spring mvc.
Basically, i have a simple table like this. Note the use of external.
<display:table id="tableId" name="data" sort="external" defaultsort="1" sort="external">
<display:column property="id" title="ID" sortable="true" sortName="id" />
<display:column property="firstName" sortable="true" sortName="firstName" title="First Name" />
<display:column property="lastName" sortable="true" sortName="lastName" title="Last Name" />
<display:column property="address" sortable="true" sortName="address" title="Email Address"/>
</display:table>
On the controller side, i get the sorted column index and the sort order.
String c = request.getAttribute(new ParamEncoder("tableId").encodeParameterName(TableTagParameters.PARAMETER_SORT));
To get the order (ASC/DESC):
String order = request.getAttribute(new ParamEncoder("tableId").encodeParameterName(TableTagParameters.PARAMETER_ORDER)));
All this is working fine. For the last step i used customized comparator to sort my list and put it back into the attribute "data" mapped himself to the table (see display tag "name" property).
public void populateModel(Model model, HttpRequest request){
String c = request.getAttribute(new ParamEncoder("tableId").encodeParameterName(TableTagParameters.PARAMETER_SORT));
// here the comparator is computed with column and order value eg
Comparator comp = new DefaultComparator();
if(c == 1){
comp = new NumericComparator();
}
List<Employe> list = Collection.sort(dao.getEmployee(), comp );
model.addAttribute("data", list);
// here the list is sorted properly
return "mypage";
}
Unfortunatly the display in the final jsp does not care about order in the list. It seem's something is overriding to a default and alphanumeric sorter...so even if i use my NumericComparator the column is still wrong sorted and i assume the "list" object has been sorted back by the librairie before the display.
To summup:
Get display tag indexes : ok
Sort the list and put it back to jsp : ok (list is sorted depending on display tag params in the controller)
Display the sorted list in the jsp side with display tag : KO (the library do not care about list order, sorting it with default sort)
Display the sorted list in the jsp side without display tag : OK
Any got the explanation about this, is there something wrong or missing ?

Primefaces 5 dynamic DataTable pre-Sort

I'm trying to build a fully dynamic DataTable with Primefaces 5.0.
I've got a Config-Object for eachs column and I want the DT to sort by one of them from the beginning.
Here's my DT:
<p:dataTable id="ticketTable"
widgetVar="ticketTable"
value="#{ticketBean.ticketDataModell}"
var="ticket"
lazy="true"
paginator="true"
rows="20"
sortBy="#{dataPortletConfigBean.sortByKey}"
>
The sortByKey is a String. It's the name of the Variable I want to sort by.
So I want to replace something like sortBy="key" with sortBy="#{bean.GiveMeAKey}".
But it doesn't work.
I get this: could not resolve property: sortByKey of: [...]
How can I get this to work?
Thanks
I got it working now.
First: The Problem.
I wanted to give the Data-Table the possibilty to have a default-sort (on load).
Thats what the sortBy-Tag in <p:dataTable> does or should do.
As long ass you write your sort-field in the DT-Tag e.g. sortBy="name" it works.
But when you pass a ValueExpression as for Example sortBy="#{bean.giveMeSomeKey}". He just cuts the '#{', everything bevor the '.' and the last '}' away an tries to sort by the field with the name of his result String. In this case 'giveMeSomeKey'.
That makes a default sorting with dynamic values impossible. (At least in PF 5.0)
Second: The Resolve.
I checked out the PF 5.0-Sources and modified the DataTableTemplate-File. (It's a template, wich is filled when PF is being built. It will later be compiled into the DataTable-Class).
There I modified the Method protected String resolveSortField().
Before:
protected String resolveSortField() {
UIColumn column = this.getSortColumn();
String sortField = null;
ValueExpression tableSortByVE = this.getValueExpression("sortBy");
Object tableSortByProperty = this.getSortBy();
if(column == null) {
sortField = (tableSortByVE == null)
? (String) tableSortByProperty
: resolveStaticField(tableSortByVE);
}
After:
protected String resolveSortField() {
UIColumn column = this.getSortColumn();
String sortField = null;
ValueExpression tableSortByVE = this.getValueExpression("sortBy");
Object tableSortByProperty = this.getSortBy();
if(column == null) {
sortField = (tableSortByVE != null)
? tableSortByVE.getExpressionString().contains("[")
? resolveDynamicField(tableSortByVE)
: resolveStaticField(tableSortByVE)
: (String) tableSortByProperty;
}
After building and including it into my project it worked.
So now I can tell my DT:
<p:dataTable [...] sortBy="#{ticket[dataPortletConfigBean.sortByKey]}"
And it will default-sort my DT After the (String)key I pass him with sortByKey, as long as it is a field in my Ticket.
It's not the perfect solution, but it works.
I tested your requirement and it worked fine.
Check if your property sortByKey in dataPortletConfigBean is returning a string like in:
public String getSortByKey() {
return "ticket.number";
}
Also ensure that the targeted column defines the sortBy attribute:
<p:column sortBy="#{ticket.number}" headerText="Number">
#{ticket.number}
</p:column>
I don't remember if this was available in PF 5.0 but now in 5.1 you can use the sortField attribute present in datatable. This was implemented for this exact purpose:
From Primefaces documentation:
sortField: Name of the field to pass lazy load method for
sorting. If not specified, sortBy expression is
used to extract the name.
After that you have to define a similar value for each column using the field attribute. If the columns are not dynamic just the sort then the field attribute will be the same value as the column itself has.
Snippet of code:
<p:dataTable var="repo" value="#{repoStrategy.flaggedRepos}" sortOrder="${repoStrategy.sortOrder}" sortField="${repoStrategy.sortBy}"
style="width: 100%" paginator="true" rows="10" rowIndexVar="rowIndex" >
<p:column headerText="Name" sortBy="#{repo.name}" field="repo.name">
#{repo.name}
</p:column>

creating link with knockoutjs

i have an observable array in my viewmodel "IdOfInvitedSocialCompaigns" , this property contain array of id , and i want to create link like this :
#Html.ActionLink("Compaign","Confirmation", new {socialbuzzCompaignId = id})
how can i built link like this with knockoutjs, here is a part of viewmodel :
function DashboardViewModel() {
var self = this;
self.IdOfInvitedSocialCompaigns = ko.observableArray([]);
}
You might be able to build the partially Razor generated URL directly into your binding markup if you get the escaping right, but it'd be messy. I'd probably define a base URL property on DashboardViewModel which gets populated by the page on DOM ready like so:
dashVM.urls.confirmCampaignUrl = '#(Url.Action("Campaign", "Confirmation"))';
and then have a function which gets a specific URL:
self.getCampaignConfirmationUrl = function(id) {
return self.urls.confirmCampaignUrl + '/' + id;
};
bound like so:
<!-- ko foreach: IdOfInvitedSocialCompaigns -->
<a data-bind="attr: { href: dashVM.getCampaignConfirmationUrl($data) }">Confirm</a>
<!-- /ko -->

Displaying Spring MVC validation errors in Freemarker templates

I'm trying to display a list of global validation errors in my freemarker template if a controller returns binding errors. I can display errors that are associated with a field, but I want to detect when an error has occurred within a specific bean and display a message at the top of the page. I've tried using the example below which produces no output:
<#spring.bind "webPage" />
....
<#if spring.status.error>
There were problems with the data you entered:
<ul>
<#list spring.status.errorMessages as error>
<li>${error?html}</li>
</#list>
</ul>
</#if>
The line below always returns 0, despite there being errors with the submitted form:
${spring.status.errorMessages?size}
My controller code is below:
#RequestMapping(method = RequestMethod.POST)
public ModelAndView save(#ModelAttribute("webPage") #Valid WebPage page, BindingResult result, Model model) {
if (!model.containsAttribute("site")) {
throw new IllegalArgumentException("Model must contain site attribute.");
}
Site site = (Site) model.asMap().get("site");
if (!result.hasErrors() && !page.isNew()) {
this.pageService.save(page, site);
} else if (!result.hasErrors() && page.isNew()) {
this.pageService.create(page, site);
}
return createMav(result);
}
The createMav method is below:
public ModelAndView createMav(BindingResult result) {
ModelAndView mav = new ModelAndView();
mav.setViewName(getPrimaryControllerView());
mav.addAllObjects(result.getModel());
return mav;
}
Is there a way to achieve this using Freemarker + Spring MVC?
I found a roundabout way to do this using the standard MVC JSP taglib. I make this available to Freemarker:
<#assign form=JspTaglibs["http://www.springframework.org/tags/form"] />
I then use the following macro to display global error message:
<#macro formErrors>
<#assign formErrors><#form.errors path="*" /></#assign>
<#if formErrors?has_content>
<div id="errors">
<#spring.message "admin.error.globalMessage" />
</div>
</#if>
</#macro>
I just place the following line where ever I want this error message to appear (this has to be contained within the form element that submits to the controller):
<#form.form method="POST" commandName="webPage">
<#formErrors />
....
</#form.form>
You can write as follows:
<#if spring.status.error>
<ul>
<#list spring.status.errors.globalErrors as error>
<li>${error.defaultMessage}</li>
</#list>
</ul>
</#if>
More info at BindStatus and Errors classes.
Try something like this:
<#spring.bind "webPage" />
<#if (spring.status.errors.allErrors?size > 0) >
<#spring.message "my.global.error.code"/>
</#if>
See the documentation: http://static.springsource.org/spring/docs/current/spring-framework-reference/html/view.html#view-velocity-forms. It has an example of what you want to do.

Resources