Is it possible to use usebean on conditions in JSP? - spring

I have a application which allows user to make a search.
Based on the search criteria entered, a service call to DAO function is made (pattern jsp event -> interceptors -> processors -> services -> DAO -> database) and list of results is returned back which gets displayed in myView.jsp
Code as below is used to read the TO data in JSP:
<jsp:usebean id="myTO" type="com.myPackage.MyTO" scope="session"/>
and in the body something like
<%= myTo.getSomething() =%>
Each item on the list is clickable for details. So on clicking item 2 on the list, another call will be made with item 2's id to fetch more details on item 2.
Depending on type of item, the details are fetched in different TO's. e.g. Type1TO, Type2TO.
So detailed data on item is returned in one such TO.
Issue is: I am displaying the details in the same JSP. So the returnURL of the second request gets forwarded to myView.JSP
So I have put a line like
<jsp:usebean id="type1TO" type="com.myPackage.Type1TO" scope="session"/>
However this gives error during the first call of list search when above Type1TO does not yet exist. Error is something like "unable to find type1TO in scope session"
How could I solve this issue ???
Is there a way to put jsp:usebean tag in an if condition in the place where it is to be used in the body ?? Or any other solution to this ??
I am new to JSP and dealing with legacy JSP. So very advanced JSP (complex EL) might not be feasible.

The following are the usages of the <usebean>:
<jsp:useBean id=”connection” class=”com.myco.myapp.Connection” /> . In this example the bean with the id is made available either by creating or finding the existing one in the session
<jsp:useBean id=”connection” class=”com.myco.myapp.Connection”>
<jsp:setProperty name=”connection” property=”timeout” value=”33”>
</jsp:useBean>. In this example, the bean is created or found, and instatiated with the setProperty if it is being created.
<jsp:useBean id=”wombat” type=”my.WombatType” scope=”session”/>. In this example the existing bean is found and made available with the given type.

If translated to Servlet, your first code snippet will look like:
getAttribute("myTO");
Whether to use a single attribute or 'multiple attributes with if-else logic' depends on your particular case. Without understanding your particular situation, I can see the following options:
Option 1
Wherever you are setting myTO attribute, ensure you set the value to the same variable, so that you don't have to use if-else logic in jsp.
Option 2
Use scripts
<%
com.myPackage.MyTO toObject = session.getAttribute("myTo");
if (toObject == NULL) {
toObject = session.getAttrbute("type1TO");
}
%>

Related

JSTL getting value in EL from another EL value

In my JSP page, I am iterating over a list of objects using the c:forEach tag. Each object in this iteration has a name field, and I am trying to use that name field to reference other objects that I have added to my Spring model. However, when I do this, I am getting an exception saying the property of the second object cannot be found on a String. Let me illustrate with a simplified example.
<c:forEach items="${companyList}" var="company" varStatus="num">
<c:set var="monthStats" value="${company.name}_month" />
<tr>
<td>Properties This Month</td>
<td>${monthStats.properties}</td>
</tr>
....
</c:forEach>
All of the objects are located inside a Spring Model object and have been set like this
model.addAttribute(company.getName() +"_month", currentMonthStats);
I have also tried throwing out the <c:set tag and trying
${(company.name + "_month").properties}
as well as
${${company.name + "_month"}.properties}.
Those havent worked either. Also, I wasn't quite sure how to word my title, so if it could worded better let me know so that other people can find this if they have the same issue.
You're basically asking for double-evaluation, and it doesn't work like that.
I'd modify the data delivered to the view layer to be something a little less odd, so you can access it in a non-pathological manner, like by putting the month stats into a map accessed by the company name (or id), or directly associated them in a DTO, etc.

Can we dynamically set the value of "list" attribute of <apex:relatedList> component?

I am trying to design a generalized detail page for an object.
In the controller class I find the list of all child relations of that object.
I then want to create for each child relations found and for accomplishing this I will have to dynamically set the value of list attribute within it.
For example :
<apex:relatedList subject={!ObjName} list="{!relatedListName}" />
But the problem here is that list attribute only accepts String literal, so can't implement it. Please suggest a way for this requirement to be accomplished.
Yes, you can dynamically set the value of the "list" attribute on a relatedlist tag, and you do so via Dynamic Visualforce. This question has since been asked and concisely answered here on the Salesforce Stack exchange for any future browsers:
https://salesforce.stackexchange.com/questions/7531/apexrelatedlist-list-dontexistinallorgs-c-only-solveable-with-dynamic
Here is the general solution:
In a custom controller, add a function to dynamically generate the RelatedList markup. I will assume from your wording that you have already accessed the full list of child relationships in your controller, so in order to spit out all the lists in one block, I would use something like this:
public Component.Apex.OutputPanel getDynamicList()
{
Component.Apex.OutputPanel outPanel = new Component.Apex.OutputPanel();
for(String id : childNames) {
Component.Apex.RelatedList relList = new Component.Apex.RelatedList();
relList.list = id;
outPanel.childComponents.add(relList);
}
return outPanel;
}
In the middle there, you can dynamically set any string to the "List" value, and by iterating through your list of strings, you are adding related list objects over and over again. (To simply add one list, remove the for loop, and make the "id" string value whatever specific relationship you wish to display).
Then on your visualforce page, you can render this block out using a dynamic visualforce tag:
<apex:dynamicComponent componentValue="{!DynamicList}" />
(as you may know, the formulaic value field will dig up the getter automatically)
Great success!
I would suggest trying apex:dataTable or apex:repeat to build your own list display. You will likely need a wrapper class to handle passing attributes and values from the sObject to the page.

How to show feedback/error messages in a backbone application

I'm working on a simple CRUD proof of concept with Rails/Backbone/JST templating. I've been able to find a lot of examples up to this point. But after much searching and reading, I've yet to find a good example of how to handle these scenarios:
info message: new item successfully added to list (shown on list screen)
info message: item successfully deleted from list
error message: problem with field(s) entry
field level error message: problem with entry
The Backbone objects are:
Collection (of "post" Models) -> Model ("post" object) -> List/Edit/New Views (and a JST template for each of these views)
So, I'm looking for a high level description of how I should organize my code and templates to achieve the level of messaging desired. I already have a handle on how to perform my validation routine on the form inputs whenever they change. But not sure what do with the error messages now that I have them.
Here is the approach I'm considering. Not sure if it's a good one:
Create a "Message" Model, which maps to a "View", which is a sub-view (if that's possible) on my existing views. This view/model can display page level messages and errors in the first three scenarios I mention above. Not sure if it's feasible to have a "sub-view" and how to handle the templating for that. But if it's possible, the parent templates could include the "message" sub-template. The message view could show/hide the sub-template based on the state of the message model. Feasible? Stupid?
For the fourth scenario, the model validation will return an error object with specific messages per each erroneous field each time a "model.set" is called by form field changes. I don't want to interrupt the "model.set" but I do want to display the error message(s) next to each field. I want to know how to factor my edit/new template and Post model/view in such a way that I don't violate the MVC pattern. I.e. I don't want to put references to DOM elements in the wrong plage.
Sorry if this is vague. If you're inclined to help, let me know what code snippets could be helpful (or other details) and I'll provide them.
You create a global eventbus. When ever an error appears trigger an event. Your view that should show the message listen to the events on this eventbus. Doing so, your error message view dont needs to know all of your collection and vice versa. The eventbus is simple:
var eventBus = _.extend({}, Backbone.Events);
Add it to your collection and trigger it when ever add was called:
var myCollection = Backbone.Collection.extend({
initialize: function([],eventbus){
this.bind('add', function(obj){eventbus.trigger('added', obj)}
}
})
Take also a look at the article: http://lostechies.com/derickbailey/2011/07/19/references-routing-and-the-event-aggregator-coordinating-views-in-backbone-js/

Richfaces 4 autocomplete component AJAX Value Update

Trying to migrate a Richfaces 3.3 project to 4. Got to a rich:suggestionBox component and converting it to a rich:autocomplete component, but having major troubles.
Requirements are: fill in part of the autocomplete, it presents user with suitable options. When the user selects something from the dropdown, the component should update it's value, disable itself, and also calculate/update the default value in a secondary field, which the user is able to edit. So far I have this:
<a4j:jsFunction name="jsFunc"
execute="autoComplete"
render="species_name individualUserStr"
actionListener="#{individualsBean.selectedIndividualElem.assignDefaultNickname}"/>
<rich:autocomplete
autocompleteMethod="#{individualsBean.speciesForBox}"
mode="cachedAjax"
layout="table"
var="sp"
id="species_name"
value="#{individualsBean.selectedIndividualElem.userCommonName}"
fetchValue="#{sp.commonName}"
disabled="#{individualsBean.selectedIndividualElem.userCommonName != null
and individualsBean.selectedIndividualElem.userCommonName ne ''}"
onselectitem="jsFunc()"
>
...
</rich:autocomplete>
<h:inputText value="#{individualsBean.selectedIndividualElem.ssi.individualUserStr}"
id="individualUserStr"
maxlength="28"
styleClass="inputTextMediumRF">
</h:inputText>
Right now, when the user selects something the jsFunc is called, assignDefaultNickname is called and everything works fine, except for the fact that the calculation in assignDefaultNickname, used to determine the value of the secondary field, individualUserStr, depends upon the value of species_name, but species_name is not submitted until I submit the form, so the calculation done in assignDefaultNickname is incorrect.
I need to somehow call the setter on individualsBean.selectedIndividualElem.userCommonName, before assignDefaultNickname is called, but I cannot figure out how to do this. There seems to be problems with AJAX and this autocomplete function; that's part of the reason why I have to use this round-a-bout jsFunction component to even call the method in the first place.
Any suggestions on how to solve this?
Found the solution to my own question. Basically, needed to learn how to use the execute attribute. The lesson to any other JSF 2.0 n00bs out there is to use execute to selectively reprocess the page. With execute you can make a white-space separated list of component IDs that should have their values re-bound to the backing bean, in case they need to be used in the listener responding to an AJAX event. In my case, this meant changing the jsFunction tag as follows:
<a4j:jsFunction name="jsFunc"
execute="species_name individualUserStr"
render="species_name individualUserStr"
actionListener="#{individualsBean.selectedIndividualElem.assignDefaultNickname}"/>
As you can see, the jsFunction now, when it is calling the assignDefaultNickname function will first update the values bound to both the auto-complete and the inputText components and THEN run assignDefaultNickname.

Is it possible to pass argument from visualforce apex tag?

I have a function searchWorkByName that takes "key" as an argument and use SQOL to retrieve the data.
In visualforce side, I have a link that calls searchWorkByName but would like to be able to pass argument such as character 'a'
example, (this throws an error)
<apex:commandLink value="search!" action="{!searchWorkByName('aaa')}" />
Is it possible to do so if not what is the alternatives?
apex class
public class SearchWorkTest {
public PageReference searchWorkByName(String key) {
//find record of work names starting from provided key character
workNames = [select name from work__c where work__c.name like 'key%'];
return Page.searchResult;
}
}
visualforce
<apex:page standardController="work__c" extenstions="SearchWorkTest">
<!-- Is it possible to pass argument like 'foo' ? -->
<apex:commandLink value="search!" action="{!searchWorkByName}" />
</apex:page>
You can pass in parameters from a page into a function like this:
<apex:commandLink value="search!" action="{!searchWorkByName}">
<apex:param name="key" value="val"/>
</apex:commandLink>
Obviously, the value of the parameter in this case is fixed. If you want something dynamic (i.e. user types something and that is passed to the function), I'm not 100% sure how you'd do that, but I think it might be possible. However, the solution already posted skins the cat for you, but I thought I'd follow up with an alternative in case it's any use.
No, you cannot pass arguments to actions like that.
1 option is to make this variable a normal form field that user can type text/select from dropdown/whatever - if you'll use same name for a variable in Apex (and make it publicly visible by setters/getters), this will work without problems. Check out my answer at How do I integrate Salesforce with Google Maps? to get started.
Second option - if this search must be somehow done programatically without user having to click anything, if the data for example comes from page itself (i.e. is read in <apex:repeat> tag)... you could make a small helper page & controller and call them as components. There is no problem with passing data to components. Check documentation for <apex:component> and <apex:componentBody>. But I think first answer os most useful for you.
Good luck!

Resources