Formatting column number in a dynamyc view panel in a xpage - xpages

I'm using dynamic view panel in XPages. The problem that formatting the number does not follow the format defined in view column.
I searched and found that the way to format the number is through a customizer bean. I've Got some code examples of this bean, though none of them had an example with formatting a column containing a number.
Does anyone have an example of this treatment formatting?
Thanks a lot!

Here's a code snippet from a getValueAsString() method from an ExtendedViewColumnConverter class that handles number formatting based on the user locale.
The code assumes that the variable currentLocale contains the user locale. currentLocale is an instance of java.util.Locale.Locale and I assume that you have logik that handles this e.g. as part of a user bean. If not, then one way of getting the current locale is to do this:
Locale currentLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
You should of course have an already working customizer bean (that extends DominoViewCustomizer).
public static class ExtendedViewColumnConverter extends ViewColumnConverter {
...
#Override
public String getValueAsString(final FacesContext context, final UIComponent component, final Object value) {
if (value instanceof Number) {
NumberFormat nf = NumberFormat.getInstance(currentLocale);
DecimalFormat df = (DecimalFormat) nf;
df.setRoundingMode(RoundingMode.HALF_UP);
switch (this.colDef.getNumberFmt()) {
case ViewColumn.FMT_GENERAL: {
// no further formatting needed
break;
}
case ViewColumn.FMT_FIXED: {
df.setMinimumFractionDigits(this.colDef.getNumberDigits());
df.setMaximumFractionDigits(this.colDef.getNumberDigits());
break;
}
default: {
// no further formatting needed
break;
}
}
return df.format(value);
}
}
...
}

Related

Binding to Properties of Nested CustomViews in a ViewController

Given I have the following setup (simplified version, removed logic to add to parent view and constraints etc).
public class TestViewModel : MvxViewModel
{
string _text;
public string Text
{
get => _text;
set
{
_text = value;
RaisePropertyChanged(() => Text);
}
}
}
public class TestViewController : MvxViewController<TestViewModel>
{
CustomViewA customViewA;
public TestViewController()
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
var bindingSet = this.CreateBindingSet<TestViewController, TestViewModel>();
bindingSet
.Bind(customViewA)
.For(v => v.Text)
.To(vm => vm.Text);
bindingSet.Apply();
}
}
public class CustomViewA : UIView
{
CustomViewB customViewB;
public string Text
{
get => customViewB.Text;
set => customViewB.Text = value;
}
}
public class CustomViewB : UIView
{
UITextField textField;
public string Text
{
get => textField.Text;
set => textField.Text = value;
}
}
Why is it that the bindings do not work? Only if I would make the UITextField in CustomViewB public and directly bind to it in the ViewController rather than the public property that directs to the Text property it seems to work. Like so:
bindingSet
.Bind(customViewA.customViewB.textField)
.For(v => v.Text)
.To(vm => vm.Text);
What am I missing here?
It depends on the requirements you have.
Binding in one direction should work (view model-to-view), I have tested your code and when the ViewModel property changes, the change is propagated to CustomViewA and from there to CusomViewB and finally to the UITextField.
However, the problem is with the opposite direction (view-to-view model). When the user updates the text field, its Text property changes. However, there is nothing notified about this change.
Although the property Text points to the text field, it is not "bound" to it, so when TextField's Text changes, the property itself doesn't know about it and neither does the MvvmCross binding.
In fact, MvvmCross binding in the control-to-view model direction is based on the ability to observe an event that tells the binding to check the new value of the bining source. This is already implemented for UITextField's Text, and it hooks up the EditingChanged event (see source code).
You can still make custom bindings work in the view-to-view model direction by implementing them manually. This is described in the documentation.

How do I assign contents of a string to a text field in Unity 4.6?

I am working on a C# class that imports text data from a web site. That works OK. Where I'm losing it is how to display the text in Unity 4.6 once I have all the text in a string variable. Any advice is appreciated.
Unity 4.6 UI system has component named Text. You can watch video tutorial here. Also I suggest you to check out its API.
As always, you have two options on how to add this component to the game object. You can do it from editor (just click on game object you want to have this component in hierarchy and add Text component). Or you can do it from script using gameObject.AddComponent<Text>().
In case you are not familiar with components yet, I suggest you to read this article.
Anyway, in your script you'll need to add using UnityEngine.UI; at the very top of it, because the Text class is in UnityEngine.UI namespace. Ok, so now back to script that will set the value of Text component.
First you need variable that refers to Text component. It can be done via exposing it to editor:
public class MyClass : MonoBehaviour {
public Text myText;
public void SetText(string text) {
myText.text = text;
}
}
And attaching gameObject with text component to this value in Editor.
Another option:
public class MyClass : MonoBehaviour {
public void SetText(string text) {
// you can try to get this component
var myText = gameObject.GetComponent<Text>();
// but it can be null, so you might want to add it
if (myText == null) {
myText = gameObject.AddComponent<Text>();
}
myText.text = text;
}
}
Previous script is not a good example, because GetComponent is actually expensive. So you might want to cache it’s reference:
public class MyClass : MonoBehaviour {
Text myText;
public void SetText(string text) {
if (myText == null) {
// looks like we need to get it or add
myText = gameObject.GetComponent<Text>();
// and again it can be null
if (myText == null) {
myText = gameObject.AddComponent<Text>();
}
}
// now we can set the value
myText.text = text;
}
}
BTW, the patter of ‘GetComponent or Add if it doesn’t exist yet’ is so common, that usually in Unity you want to define function
static public class MethodExtensionForMonoBehaviourTransform {
static public T GetOrAddComponent<T> (this Component child) where T: Component {
T result = child.GetComponent<T>();
if (result == null) {
result = child.gameObject.AddComponent<T>();
}
return result;
}
}
So you can use it as:
public class MyClass : MonoBehaviour {
Text myText;
public void SetText(string text) {
if (myText == null) {
// looks like we need to get it or add
myText = gameObject.GetOrAddComponent<Text>();
}
// now we can set the value
myText.text = text;
}
}
make sure you import the ui library - using UnityEngine.UI
gameObject.GetComponent<Text>().text - replace .text with any other field for UI Text
I assume that the issue is creating dynamic sized "textbox" rather than just assigning the string to a GUIText GameObject. (If not - just put a GUIText GameObject into your scene, access it via a GUIText variable in your script and use myGUIText.text = myString in Start or Update.)
If I am correct in my assumption, then I think you should just be using a GUI Label:
http://docs.unity3d.com/ScriptReference/GUI.Label.html
If you need to split the string up to place text into different labels or GUITexts, you will need to use substrings

JSF round value from string

I have a JSF 1.2 view which is kind of a report generator.
Users can select a query, configure some values, then the database is requested and data collected.
After that the data can be viewed in a dataTable and finally is exported to Excel.
Works fine so far.
Depending on the query the columns have different types, one of which is Double.
The Double values should be rounded now...
Since there are many rows (tens or hundreds of thousands) I collect all data as String
to avoid time consuming type conversions.
That's pretty ok because for the export to Excel I need Strings, too (written to Office XML).
But now the rounding comes in. In the dataTable the doubles shall be rounded.
If I had a Double I could easily use f:convertNumber, but I don't have.
My idea would be a String converter which analyzes if it is a numeric value
and then formats the String. (Performace is not so critical because there are
only 30 or so records in the paged dataTable). How would I accomplish this?
Any (other) suggestions? Thanks!
Mark
Edit:
solved for now with
public class ReportStringConverter implements Converter {
DecimalFormat f = new DecimalFormat("#0.00");
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return value;
}
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (isNumeric(value.toString())) {
return f.format(Double.parseDouble(value.toString()));
} else {
return value.toString();
}
}
private boolean isNumeric(String s) {
try {
double d = Double.parseDouble(s);
} catch (NumberFormatException e) {
return false;
}
return true;
}
}
You could use expression language to convert a string to a number by adding 0 to it (example: #{'35.75' + 0}). This allows you to simply use f:convertNumber.
<h:outputText value="#{'35.75' + 0}">
<f:convertNumber pattern="0"/>
</h:outputText>

Managed Beans and TabContainer

I ask this squestion on behalf of one of my developers. Haven't looked into details myself.
Assume you have a simple managed bean (=contact) This bean has a method to get the contacts firstName.
I can open an xpage and bind the bean to a computedText Field #{contact.firstName}
In our application we use a tabContainer to have multiple documents of the same type ( contact ) open.
How do I have to use my bean in the container?
faces-config.xml:
<managed-bean>
<managed-bean-name>person</managed-bean-name>
<managed-bean-class>com.package.Person</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
Java Bean Class:
public class Person implements Serializable {
private String strDocumentID;
private Document docData;
private String strFirstName;
private String strLastName;
private static final long serialVersionUID = 2934723410254681213L;
public Person() {
//setting the DocumentUniqueID of the current in a tab opened document
//attention: there could be more than one open tab, all with different documents
//and even different document types; and it is possible to switch back and forth between tabs
//DocumentId = ???;
//Setting the values from the stored document to the object
//setValues();
}
private void setValues() {
try {
Session session=NotesContext.getCurrent().getCurrentSession();
Database currdb=session.getCurrentDatabase();
docData=currdb.getDocumentByUNID(DocumentId);
setStrFirstName(docData.getItemValueString("FirstName"));
setStrLastName(docData.getItemValueString("LastName"));
} catch (NotesException e) {
throw new FacesException("Could not open document for documentId "+ DocumentId, e);
}
}
public Document getDataDocument() {
return docData;
}
public void setDataDocument(Document docData) {
this.docData = docData;
}
public String getDocumentId() {
return DocumentId;
}
public void setDocumentId(String documentId) {
DocumentId = documentId;
}
public String getStrFirstName() {
return strFirstName;
}
public void setStrFirstName(String strFirstName) {
this.strFirstName = strFirstName;
}
public String getStrLastName() {
return strLastName;
}
public void setStrLastName(String strLastName) {
this.strLastName = strLastName;
}
}
Custom Control with computed field:
person.strFirstName
So, the problem is the constructor of the Person Class. It needs to get the "link" to the opened document when the document is opened in a tab and everytime when switched back to this tab. And this without the use of any Data source, because this is what should be done by the managed bean itself.
So, hope that helped to get a little bit more understanding of the problem.
If not, please ask again.
My advice:
make another meta bean implementing map interface. Alter its getter to instantiate and return your data bean. Binding may be then:
meta[someparamwithunid].field
And save would be:
meta[someparamwithunid].setValues()
Like this:
public class People implments java.util.Map {
Map<String,Person> people = new HashMap<String,Person>();
public Person get(String unid) {
if people.keySet().contains(unid) {
return people.get(unid)
} else {
// make instance and store it in people map, return it
}
// implement other methods
}
With view scope I think there is no problem with concurrency.
Frantisek points into the right direction. Your request bean would not be a person bean, but a people bean. You then can use an expression like
#{people[index].name}
to refer to a specific person. People would be the managed bean and the index could either be the UNID or the tab number. I find the later one easier to implement. you need to have a loadPerson(index) = UNID function to load an existing person. More information on the use of Expression language can be found here:
Sun Oracle JSF documentation or in some Course materials.
Hope that helps.
I'm not sure if this bean will work in the requestScope because you have probably a lot of partial refreshes with the tabcontainer (maybe try change it to a higher level scope).

Problem binding a bean property to an element in JSF

I have an input (JSF) that should be bound to a property in my bean. This property represents another bean and has an auxiliar method that checks if it's null (I use this method a lot).
The problem is that the binding is failing to get the proper getter and setter. Instead of reading the method that returns the bean, it reads the one that return a boolean value.
The property name is guest. The methods are:
getGuest;
setGuest;
isGuest (checks if guest is null).
JSF is trying to bind the object to isGuest and setGuest, instead of getGuest and setGuest.
I cannot rename isGuest to guestIsNull or something, because that would'nt make to much sense (see the class below).
Finally, my question is: how can I bind this property to the object without renaming my methods? Is it possible?
I also accept suggestions of a better method name (but the meaning must be the same).
Entity
#Entity
public class Passenger {
private Employee employee;
private Guest guest;
public Passenger() {
}
#Transient
public boolean isEmployee() {
return null != this.employee;
}
#Transient
public boolean isGuest() {
return null != this.guest;
}
#OneToOne
public Employee getEmployee() {
return this.employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
#OneToOne
public Guest getGuest() {
return this.guest;
}
public void setGuest(Guest guest) {
this.guest = guest;
}
}
JSF
<h:inputText value="#{passenger.employee}" />
<h:inputText value="#{passenger.guest}" />
Change the method name to isGuestNull.
The problem you're seeing is due to the fact that the EL lets you use getFoo or isFoo as the naming style for getter methods that return booleans.
No, that's not possible. You've to rename them.
Another way is to add a single getter returning an enum which covers all cases.
public enum Type {
GUEST, EMPLOYEE;
}
public Type getType() {
return guest != null ? Type.GUEST
: employee != null ? Type.EMPLOYEE
: null;
}
with
<h:something rendered="#{passenger.type == 'GUEST'}">
Binding to any property using any method is possible and quite easy if you create your custom ELResolver (apidocs). elresolvers are registered in faces config, and they are responsible, given an Object and a String defining a property, for determining the value and type of the given properties (and, as the need arises, to change it).
You could easily write your own ELResolver that would only work for your chosen, single type, and use (for example in a switch statement) the specific methods you need to write and read properties. And for other types it would delegate resolving up the resolver chain. It's really easy to do, much easier than it sounds.
But don't do it. The standard naming pattern of properties predates EL by many years. It is part of the JavaBeans™ standard - one of the very few undisputed standards in Javaland, working everywhere - from ant scripts, through spring configuration files to JSF. Seeing methods isPerson and getPerson in one class actually makes me fill uneasy, as it breaks something I always take for granted and can always count on.
If you like DDD and want to have your method's names pure, use an adapter. It's easy, fun, and gives a couple of additional lines, which is not something to sneer at if you get paid for the ammount of code produced:
public class MyNotReallyBean {
public String checkName() { ... }
public String lookUpLastName() { ... }
public String carefullyAskAboutAge() { ... }
public class BeanAdapter {
public String getName() { return checkName(); }
public String getLastName() { return lookUpLastName(); }
public String getAge() { return carefullyAskAboutAge(); }
}
private static BeanAdapter beanAdapter = new BeanAdapter();
private BeanAdapter getBeanAdapter(){ return beanAdapter; }
}

Resources