Ext.net databinding extension method - ext.net

Yeah, I have the unfortunate situation of having to go into a project that makes use of ext.net.
There is a GridPanel with several columns, a couple of these are bound to datetime properties like this:
<ext:DateColumn Header="Started time" DataIndex="DateStarted" Format="yyyy-MM-dd HH:mm:ss" />
Now, I ned to run an extension method, ToUniversalTime(), on the property DateStarted.
It seems I can not change DataIndex="DateStarted" to DataIndex="DateStarted.ToUniversalTime()"

Forgot about this one.
I got an answer from Vladimir Ext.NET - Dev Team, support for this is to be added in version 2.3.

You can use the Renderer tag on your column
<ext:DateColumn Header="Started time" DataIndex="DateStarted" Format="yyyy-MM-dd HH:mm:ss" >
<Renderer Fn="myRenderer" />
</ext:DateColumn >
Call a Direct Method or implement your extension method in JavaScript
var myRenderer = function (value, metadata, record, rowIndex, colIndex, store) {
return stuff here;
};

Related

Programatically Set Attribute with a Value Expression when component is within JSTL forEach loop

First time asking a question so please bear with me.
I have a pure Java custom component that extends UIInput (JSF 2.2, Mojarra) and I am using it like so:
<c:forEach items="#{bean.items}" var="item">
<my:component item="#{item}" />
</c:forEach>
I am trying to avoid unnecessarily specifying the 'value', 'valueChangeListener' and 'validator' attributes on the tag in the .xhtml file.
In my custom component I have overridden the setValueExpression method like so:
#Override
public void setValueExpression(String name, ValueExpression expression) {
super.setValueExpression(name, expression);
if ("item".equals(name)) {
this.setValue(Components.createValueExpression("#{item.myValue}", MyValue.class));
this.addValueChangeListener(new MethodExpressionValueChangeListener(Components.createVoidMethodExpression("#{item.myValueChanged}", ValueChangeEvent.class)));
this.addValidator(new MethodExpressionValidator(Components.createVoidMethodExpression("#{item.validateMyValue}", FacesContext.class, UIComponent.class, Object.class)));
}
}
I'm using OmniFaces there with its Components utility to reduce boilerplate code.
When it comes time to act on any of those three (validate on submit, for example) it results in:
javax.faces.FacesException: javax.el.PropertyNotFoundException: Target Unreachable, identifier 'item' resolved to null
I am pretty sure I know why, I just don't know what to do about it.
I believe when it comes time for the three expressions I am trying to set programatically to be resolved it's trying to find a bean in some scope by the name, 'item' however that doesn't exist since 'item' was a point in time variable within a JSTL forEach loop.
I think there's a special deferred kind of expression that Weld is using for item itself (which I can kinda see when I debug that setValueExpression method) that is aware or otherwise has references to that point in time variable but I'm not doing the same thing when I set up those three expressions and therefore there's no handle to that later on when it comes time for them to be resolved.
I am sure there is a way to wire this together I'm just not seeing it.
Additionally, I know I could just put the three attributes on the tag in the .xhtml like this:
<my:component item="#{item}" value="#{item.myValue}" valueChangeListener="#{item.myValueChanged}" validator="#{item.validateMyValue}" />
Then they would get their special deferred expressions just like item itself does (and indeed everything works as expected this way) but I'd rather not - it's something I'd have to repeat a lot and it just seems like there should be a way to do what I am trying above.
I believe I found the answer.
What I kept seeing in the debugger kept nagging at me, I just wasn't sure how to wire up the same scenario manually, then I found a Stack Overflow post with the following code snip at the very bottom:
VariableMapper varMapper = new DefaultVariableMapper();
varMapper.setVariable(mappingName, component.getValueExpression(mappedAttributeName));
return new ValueExpressionImpl(expression, null, null, varMapper, expectedType);
That was enough to point me in the right direction of re-using the incoming value expression for item itself in a VariableMapper instance which is in turn used to create the three value/method expressions so they each now have a handle & can resolve 'item' later on, when it comes time:
#Override
public void setValueExpression(String name, ValueExpression expression) {
super.setValueExpression(name, expression);
if ("item".equals(name)) {
VariableMapper varMapper = new DefaultVariableMapper();
varMapper.setVariable("item", expression);
ValueExpressionImpl valExprImpl = new ValueExpressionImpl("#{item.myValue}", null, null, varMapper, MyValue.class);
super.setValueExpression("value", valExprImpl);
MethodExpressionImpl meExprImpl = new MethodExpressionImpl("#{item.myValueChanged}", null, null, varMapper, Void.class, new Class<?>[] {ValueChangeEvent.class});
MethodExpressionValueChangeListener mevcl = new MethodExpressionValueChangeListener(meExprImpl);
this.addValueChangeListener(mevcl);
meExprImpl = new MethodExpressionImpl("#{item.validateMyValue}", null, null, varMapper, Void.class, new Class<?>[] {FacesContext.class, UIComponent.class, Object.class});
MethodExpressionValidator mev = new MethodExpressionValidator(meExprImpl);
this.addValidator(mev);
}
}
That seems to have done the trick (and looks so simple now...).

Usage of OmniFaces Param.validatorAttributes

I try to use the OmniFaces #Param annotation to inject a request parameter.
I also make use of its validatorClasses attribute to validate the parameter. Eventually this used validator needs a special attribute to function and I want to pass the value by setting the validatorAttributes attribute. Unfortunately I don't know how. The documentation provides a description but I just don't get it right.
Can someone help please?
Here's some code:
#Inject
#Param(
name = "the_param_name",
validatorClasses = MyFreshValidator.class,
validatorAttributes = ?
)
private MyFreshClass instance;
It would be ideal to give another object of the same class to the validator.
It's indeed slightly hidden in the showcase. If you open the CdiParamBean tab of the "Demo source code" section, then you'll find the managed bean's source code with below examples:
// Like <f:viewParam name="text2" value="#{bean.text2}" validatorMessage="..."><f:validateLength minimum="3">
#Inject #Param(
validatorClasses = LengthValidator.class,
validatorAttributes = #Attribute(name="minimum", value="3"),
validatorMessage = "{1}: Value is too too small! Please enter a minimum of 3 characters.")
private String text2;
// Like <f:viewParam name="date" value="#{bean.date}" converterMessage="..."><f:convertDateTime pattern="yyyyMMdd">
#Inject #Param(
converterClass = DateTimeConverter.class,
converterAttributes = { #Attribute(name="pattern", value="yyyyMMdd") },
converterMessage="{1}: \"{0}\" is not the date format we had in mind! Please use the format yyyyMMdd.")
private Date date;
Here, the #Attribute is the org.omnifaces.cdi.param.Attribute.
I'll look at improving the documentation in a future version.

org.hibernate.LazyInitializationException at com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectManyValuesForModel

Despite of FetchType.EAGER and JOIN FETCH, I get a LazyInitalizationException while adding some objects to a #ManyToMany collection via a JSF UISelectMany component such as in my case the <p:selectManyMenu>.
The #Entity IdentUser, with FetchType.EAGER:
#Column(name = "EMPLOYERS")
#ManyToMany(fetch = FetchType.EAGER, cascade= CascadeType.ALL)
#JoinTable(name = "USER_COMPANY", joinColumns = { #JoinColumn(name = "USER_ID") }, inverseJoinColumns = { #JoinColumn(name = "COMPANY_ID") })
private Set<Company> employers = new HashSet<Company>();
The #Entity Company, with FetchType.EAGER:
#ManyToMany(mappedBy="employers", fetch=FetchType.EAGER)
private List<IdentUser> employee;
The JPQL, with JOIN FETCH:
public List<IdentUser> getAllUsers() {
return this.em.createQuery("from IdentUser u LEFT JOIN FETCH u.employers WHERE u.enabled = 1 AND u.accountNonLocked=0 ").getResultList();
}
The JSF UISelectMany component causing the exception while submitting:
<p:selectManyMenu value="#{bean.user.employers}" converter="#{entityConverter}">
<f:selectItems value="#{bean.companies}" var="company" itemValue="#{company}" itemLabel="#{company.name}"/>
</p:selectManyMenu>
The relevant part of the stack trace:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:566)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:186)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:545)
at org.hibernate.collection.internal.PersistentSet.add(PersistentSet.java:206)
at com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectManyValuesForModel(MenuRenderer.java:382)
at com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectManyValue(MenuRenderer.java:129)
at com.sun.faces.renderkit.html_basic.MenuRenderer.getConvertedValue(MenuRenderer.java:315)
at org.primefaces.component.selectmanymenu.SelectManyMenuRenderer.getConvertedValue(SelectManyMenuRenderer.java:37)
...
How is this caused and how can I solve it?
While submitting, the JSF UISelectMany components need to create a brand new instance of the collection with the submitted and converted values prefilled. It won't clear out and reuse the existing collection in the model as that may either get reflected in other references to the same collection, or may fail with an UnsupportedOperationException because the collection is unmodifiable, such as the ones obtained by Arrays#asList() or Collections#unmodifiableList().
The MenuRenderer, the renderer behind UISelectMany (and UISelectOne) components who's responsible for this all, will by default create a brand new instance of the collection based on collection's getClass().newInstance(). This would in turn fail with LazyInitializationException if the getClass() returns an implementation of Hibernate's PersistentCollection which is internally used by Hibernate to fill the collection property of an entity. The add() method namely needs to initialize the underlying proxy via the current session, but there's none because the job isn't performed within a transactional service method.
To override this default behavior of MenuRenderer, you need to explicitly specify the FQN of the desired collection type via the collectionType attribute of the UISelectMany component. For a List property, you'd like to specify java.util.ArrayList and for a Set property, you'd like to specify java.util.LinkedHashSet (or java.util.HashSet if ordering isn't important):
<p:selectManyMenu ... collectionType="java.util.LinkedHashSet">
The same applies to all other UISelectMany components as well which are directly tied to a Hibernate-managed JPA entity. E.g:
<p:selectManyCheckbox ... collectionType="java.util.LinkedHashSet">
<h:selectManyCheckbox ... collectionType="java.util.LinkedHashSet">
<h:selectManyListbox ... collectionType="java.util.LinkedHashSet">
<h:selectManyMenu ... collectionType="java.util.LinkedHashSet">
See also the VDL documentation of among others <h:selectManyMenu>. This is unfortunately not specified in VDL documentation of <p:selectManyMenu>, but as they use the same renderer for converting, it must work. If the IDE is jerking about an unknown collectionType attribute and annoyingly underlines it even though it works when you ignore'n'run it, then use <f:attribute> instead.
<p:selectManyMenu ... >
<f:attribute name="collectionType" value="java.util.LinkedHashSet" />
...
</p:selectManyMenu>
Solution: Replace the editUserBehavior.currentUser.employers with collection that is not managed by Hibernate.
Why? When the Entity becomes managed, the Hibernate replaces your HashSet with its own implementation of Set (be it PersistentSet). By analysing the implementation of JSF MenuRenderer, it turns out that at one point it creates new Set reflectively. See the comment in MenuRenderer.convertSelectManyValuesForModel()
// try to reflect a no-argument constructor and invoke if available
During construction of PersistentSet initialize() is invoked and - as this class is only meant to be invoked from Hibernate - LazyInitializationException is thrown.
Note: This is my suspicion only. I don't know your versions of JSF and Hibernate but this is more likely the case.

AngularJS - Ng-repeat - Select2 JS - Issue setting default value

Having trouble in setting up the default value for the drop down when AngularJS/ng-repeat/custom directive + Select2 JS is used.
1. I avoided using ng-options as the directive priority is 0.
2. I tried setting the priority for the custom directive 'select2Directive' to a number less than 1000, but still no luck.
Plunker # http://plnkr.co/edit/Csy5FqDSQbErTm2fNPac. Appreciate any help. Thanks.
I noticed that you are calling the select2 using a small directive, but I found this library named angular-select2 which is easy to implement as well.
you can set the default values with your ng-model/$scope, take a lookt to this plunker to get the idea
http://plnkr.co/edit/pFkY5f?p=preview
EDIT:
I'd rather try to pass the data in other way seems like the select2 data and your the ng-repeat are not in sync
you could try a different approach something like creating a directive and insert the data from there.
directive('select2Dynamic', function ($timeout) {
return {
restrict: 'A',
priority: 1,
scope: {
ngModel: "="
},
require: 'ngModel',
link: function (scope, element, attr) {
var select2Inst = element.select2();
select2Inst.select2({data:scope.$parent.$eval(attr.ngModel)});
select2Inst.select2('val',attr['select2Dynamic']);
}
}
});
<select select2-dynamic='2' ng-model='addresses' id="address" name="address" style="width:200px;" >
</select>
if you want to stick to your approach you'll consider to set up the value and the end of the "model binding event"
look at this plunker
anyway I still stand my point that you should try angular-select2 library
hope that helps

Grails: How to make everything I create Upper Case?

I am currently using CSS to change everything I write to upperCase when I create an entry, but that is not enough. When I save things, the text shown in the text fields is upper case, but the real value that Grails stores stays in lower case.
I am assuming I'd need to change something in the controller or anything.
Maybe transforming the $fieldValue CSS could work??
Any ideas would help!
Thnks!
You could just write setters for your domain object?
class Domain {
String aField
void setAField( String s ){
aField = s?.toUpperCase()
}
}
I think you are asking how to change values on your domain objects to uppercase. If this is not the case please clarify the question.
You have a bunch of options. I would recommend
1) In a service method, before you save, using String.toUpperCase() to modify the appropriate values on the domain object.
or
2) You can use the underlying Hibernate interceptors by defining a beforeInsert method on your domain object, and doing the toUpperCase there. (see 5.5.1 of the grails documentation)
or
3) You could do this client side. However, if it is a "business requirement" that the values are stored as upper, then I recommend doing the translation server side. It is easier to wrap tests around that code....
Using annotations is cleanest approach
import org.grails.databinding.BindingFormat
class Person {
#BindingFormat('UPPERCASE')
String someUpperCaseString
#BindingFormat('LOWERCASE')
String someLowerCaseString
}
Here is link for it: Grails doc for data binding
You can use Groovy metaprogramming to change the setter for all domain class String-typed properties without actually writing a custom setter for each property.
To do this, add something like the following to the init closure of Bootstrap.groovy
def init = { servletContext ->
for (dc in grailsApplication.domainClasses) {
dc.class.metaClass.setProperty = { String name, value ->
def metaProperty = delegate.class.metaClass.getMetaProperty(name)
if (metaProperty) {
// change the property value to uppercase if it's a String property
if (value && metaProperty.type == String) {
value = value.toUpperCase()
}
metaProperty.setProperty(delegate, value)
} else {
throw new MissingPropertyException(name, delegate.class)
}
}
}
}

Resources