JavaFX Text Change Event - textarea

I designed a form in FXML document.I can handle keypress vs. events. But I need text change event.I'm using Netbeans 7.3 . There's three files in the projects: SampleControler, Sample.FXML and Sample.java. I found a code but I have not solved where to use it.
input.textProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue ov, String t, String t1) {
System.out.println("Changed.");
}
});
My TextArea code is:
<TextArea layoutX="10" layoutY="50" maxHeight="125" minHeight="125" maxWidth="570" minWidth="570" editable="true" fx:id="input" prefWidth="570" prefHeight="125" />
What should I do?

In your controller associeted to your fxml, get your TextArea, and you will can do :
yourTextArea.textproperty().addListener ...
public class Example implements Initializable {
#FXML
private TextArea textArea;
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
textArea.textProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observableValue, String s, String s2) {
}
});
}
}
The varibale name on the controller need to have the same name like the fx:id in the fxml

Related

Add attribute dynamically to component in converter?

I wonder if should be possible to add an attribute to a component inside a converter? So inside the getAsString I would use uiComponent.addAttribute(). This seems to work 50% for me, the initial value is set, but when the converter is called later setting a new value the initial value is still retrieved.
you should not do it this way since it breaks separation of duties. you should use a bean or a scope attribute instead.
but maybe this suits:
<h:inputText value="#{bean.someValue}" converter="#{bean}">
<f:attribute name="attrName" value="#{bean.attrValue}"/>
</h:inputText>
and
#ManagedBean
public class Bean implements Converter
{
private String someValue;
private String attrValue;
#Override
public String getAsString(FacesContext context, UIComponent component, Object value)
{
attrValue = "uppercase";
return someValue.toUpperCase();
}
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value)
{
attrValue = "lowercase";
return value.toLowerCase();
}
public String getSomeValue()
{
return someValue;
}
public void setSomeValue(String someValue)
{
this.someValue = someValue;
}
public String getAttrValue()
{
return attrValue;
}
public void setAttrValue(String attrValue)
{
this.attrValue = attrValue;
}
}

Include dynamic content containing JSF tags/components from stream

I am working on an application where I would like to include dynamic XHTML content from a stream. To handle this I wrote a taghandler extension which dumps the dynamic XHTML content to output component as
UIOutput htmlChild = (UIOutput) ctx.getFacesContext().getApplication().createComponent(UIOutput.COMPONENT_TYPE);
htmlChild.setValue(new String(outputStream.toByteArray(), "utf-8"));
This works fine for XHTML content which has no JSF tags. If I have JSF tags in my dynamic XHTML content like <h:inputText value="#{bean.item}"/>, then they're printed as plain text. I want them to render as input fields. How can I achieve this?
Essentially, you should be using an <ui:include> in combination with a custom ResourceHandler which is able to return the resource in flavor of an URL. So when having an OutputStream, you should really be writing it to a (temp) file so that you can get an URL out of it.
E.g.
<ui:include src="/dynamic.xhtml" />
with
public class DynamicResourceHandler extends ResourceHandlerWrapper {
private ResourceHandler wrapped;
public DynamicResourceHandler(ResourceHandler wrapped) {
this.wrapped = wrapped;
}
#Override
public ViewResource createViewResource(FacesContext context, String resourceName) {
if (resourceName.equals("/dynamic.xhtml")) {
try {
File file = File.createTempFile("dynamic-", ".xhtml");
try (Writer writer = new FileWriter(file)) {
writer
.append("<ui:composition")
.append(" xmlns:ui='http://java.sun.com/jsf/facelets'")
.append(" xmlns:h='http://java.sun.com/jsf/html'")
.append(">")
.append("<p>Hello from a dynamic include!</p>")
.append("<p>The below should render as a real input field:</p>")
.append("<p><h:inputText /></p>")
.append("</ui:composition>");
}
final URL url = file.toURI().toURL();
return new ViewResource(){
#Override
public URL getURL() {
return url;
}
};
}
catch (IOException e) {
throw new FacesException(e);
}
}
return super.createViewResource(context, resourceName);
}
#Override
public ResourceHandler getWrapped() {
return wrapped;
}
}
(warning: basic kickoff example! this creates a new temp file on every request, a reuse/cache system should be invented on your own)
which is registered in faces-config.xml as follows
<application>
<resource-handler>com.example.DynamicResourceHandler</resource-handler>
</application>
Note: all of above is JSF 2.2 targeted. For JSF 2.0/2.1 users stumbling upon this answer, you should use ResourceResolver instead for which an example is available in this answer: Obtaining Facelets templates/files from an external filesystem or database. Important note: ResourceResolver is deprecated in JSF 2.2 in favor of ResourceHandler#createViewResource().
My solution for JSF 2.2 and custom URLStream Handler
public class DatabaseResourceHandlerWrapper extends ResourceHandlerWrapper {
private ResourceHandler wrapped;
#Inject
UserSessionBean userBeean;
public DatabaseResourceHandlerWrapper(ResourceHandler wrapped) {
this.wrapped = wrapped;
}
#Override
public Resource createResource(String resourceName, String libraryName) {
return super.createResource(resourceName, libraryName); //To change body of generated methods, choose Tools | Templates.
}
#Override
public ViewResource createViewResource(FacesContext context, String resourceName) {
if (resourceName.startsWith("/dynamic.xhtml?")) {
try {
String query = resourceName.substring("/dynamic.xhtml?".length());
Map<String, String> params = splitQuery(query);
//do some query to get content
String content = "<ui:composition"
+ " xmlns='http://www.w3.org/1999/xhtml' xmlns:ui='http://java.sun.com/jsf/facelets'"
+ " xmlns:h='http://java.sun.com/jsf/html'> MY CONTENT"
+ "</ui:composition>";
final URL url = new URL(null, "string://helloworld", new MyCustomHandler(content));
return new ViewResource() {
#Override
public URL getURL() {
return url;
}
};
} catch (IOException e) {
throw new FacesException(e);
}
}
return super.createViewResource(context, resourceName);
}
public static Map<String, String> splitQuery(String query) throws UnsupportedEncodingException {
Map<String, String> params = new LinkedHashMap<>();
String[] pairs = query.split("&");
for (String pair : pairs) {
int idx = pair.indexOf("=");
params.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
}
return params;
}
#Override
public ResourceHandler getWrapped() {
return wrapped;
}
static class MyCustomHandler extends URLStreamHandler {
private String content;
public MyCustomHandler(String content) {
this.content = content;
}
#Override
protected URLConnection openConnection(URL u) throws IOException {
return new UserURLConnection(u, content);
}
private static class UserURLConnection extends URLConnection {
private String content;
public UserURLConnection(URL url, String content) {
super(url);
this.content = content;
}
#Override
public void connect() throws IOException {
}
#Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(content.getBytes("UTF-8"));
}
}
}
}

How to get standard styleClass attribute in custom component which extends UIOutput

I'm using below custom component to display some kind of guidance in my page. I was asked to pass text and styleClass attributes to this component. But unfortunately styleClass attribute alone is NOT getting applied when this component gets rendered in the page. And thus I've hard coded with in my tag component. And this time style is getting applied properly. Not sure why. Can any one sugegst?
I can see styleClass attribute from css is getting passed to tag component properly. As I mentioned above component is getting rendered with out the passed style class applied.
If I hard code my style as below then it is working.
writer.writeAttribute("style", "background-color: #F1F5F2;font-size: 80%;left: 52em;position: absolute;text-align: left;width: 13.25em;z-index: 5;", null);
How is this caused and how can I solve it?
The custom component is used as follows
<mytags:guidanceBox text="#{FindPersonProps.MY_GUIDANCE_TEXT}" styleClass="guidance_css" />
The source code is below:
#FacesComponent(value="tags.guidanceBox")
public class GuidanceTag extends UIOutput {
#Override
public String getFamily() {
return "javax.faces.NamingContainer";
}
public GuidanceTag() {
}
#Override
public void encodeBegin(FacesContext context) throws IOException {
String guidanceText=(String) getAttributes().get("text");
//String styleClass=(String) getAttributes().get("styleClass");
//System.err.println("Text ["+guidanceText+"] Style ["+styleClass+"]");
ResponseWriter writer=context.getResponseWriter();
String clientId=getClientId(context);
writer.startElement("p", this);
writer.writeAttribute("style", "background-color: #F1F5F2;font-size: 80%;left: 52em;position: absolute;text-align: left;width: 13.25em;z-index: 5;", null);
writer.writeAttribute("name", clientId, "clientId");
writer.startElement("b", null);
writer.writeText("Guidance:", null);
writer.endElement("b");
writer.startElement("br", null);
writer.endElement("br");
writer.writeText(guidanceText, null);
writer.endElement("p");
}
You should implement TagHandler, that is passing the attributes to implementation of your component itself. Something like this:
public class GuidanceTagHandler extends ComponentHandler {
public GuidanceTagHandler(ComponentConfig config) {
super(config);
}
#Override
protected void onComponentCreated(FaceletContext ctx, UIComponent c, UIComponent parent) {
super.onComponentCreated(ctx, c, parent);
TagAttribute styleClassAttribute = getRequiredAttribute("styleClass");
c.getAttributes().put("styleClass", styleClassAttribute);
}
}
in taglib.xml you should have a signature of your component:
<tag>
<tag-name>guidanceTag</tag-name>
<component>
<component-type>guidance</component-type>
<handler-class>yourpackages.GuidanceTagHandler</handler-class>
</component>
</tag>
and finally in faces.config (it will bind on the component-type attribute
<component>
<component-type>guidance</component-type>
<component-class>yourpackages.GuidanceTag</component-class>
</component>
I hope this answer will help you a bit, since I was once having the same problem. So this is the solution I came up with.

primefaces autocomplete with pojo

I read on SO some QA about the same component, but I feel I'm missing something, because I am one step behind.
I can't even make the page open when using the primefaces autocomplete component in it.
The snippet for it is:
<p:autoComplete value="#{indirizzoCtrl.selectedCodiceNazione}"
completeMethod="#{indirizzoCtrl.completeNazione}"
var="nazione" itemLabel="#{nazione.nome}"
itemValue="#{nazione.codiceNazione}" />
Nazione is a Pojo class where CodiceNazione and Nome are two String field (with getter and setter for sure). completeNazione is a method on the ManagedBean that returns List<Nazione>.
Looking at BalusC explanation here, it seems to me that i don't need any converter involved, because both itemValue and value attributes are mapped to string property.
Anyway, when I just open the page containing this autocomplete snippet, it crashes with this error:
javax.el.PropertyNotFoundException: /Cliente/Indirizzo.xhtml #23,56 itemValue="#{nazione.codiceNazione}": itemValue="#{nazione.codiceNazione}": Property 'codiceNazione' not found on type java.lang.String
Why this is happening? I really can't get it. The method completeNazione hasn't even called yet, so it shouldn't know any Nazione yet.
What's wrong with it?
Edited:
Following the suggestion, I tried to add a converter, but I still get the same error.
Here's my converter:
public class NazioneConverter implements Converter {
final static Logger log = Logger.getLogger(NazioneConverter.class);
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value.trim().equals("")) {
return null;
} else {
try {
IndirizzoRepository ir = new IndirizzoRepository();
List<Nazione> nazioni = ir.getNazioneByName(value);
if (nazioni.size()==1) return nazioni.get(0);
else throw new Exception();
} catch (Exception e) {
String msg = "Errore di conversione";
log.error(msg, e);
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, "Non è una nazione conosciuta"));
}
}
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null || value.equals("")) {
return "";
} else {
return String.valueOf(((Nazione) value).getNome());
}
}
}
now the component in the view looks like:
<p:autoComplete value="#{indirizzoCtrl.indirizzo.nazione.codiceNazione}"
completeMethod="#{indirizzoCtrl.completeNazione}"
var="nazione" itemLabel="#{nazione.nome}" converter="#{nazioneConverter}"
itemValue="#{nazione.codiceNazione}" forceSelection="true" />
But still don't working. The converter is not even invoked: I registered it in my faces-config.xml file.
I also tried itemValue="#{nazione}" as in the primefaces showcase but the problem became the ItemLabel attribute, mapped to nazione.nome.
What am I doing wrong?
This worked for me:
//Converter
#FacesConverter(value="MarcaConverter")
public class MarcaConverter implements Converter{
MarcaDAO marcaDAO;
public Object getAsObject(FacesContext contet, UIComponent component, String value) {
if(value==null || value.equals(""))
return null;
try{
int id = Integer.parseInt(value);
return marcaDAO.findMarcaById(id);
}catch (Exception e) {
e.printStackTrace();
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Marca no válida", ""));
}
}
public String getAsString(FacesContext contet, UIComponent component, Object value) {
if(value==null || value.equals(""))
return null;
return String.valueOf(((Marca)value).getCodigoMarca());
}
}
//--------------------------------------
//Bean
#ManagedBean
#ViewScoped
public class MyBeans implements Serializable{
private Marca marca;
...
public Marca getMarca(){
return marca;
}
public void setMarca(Marca m){
marca=m;
}
...
public List<Marca> obtenerMarcasVehiculos(String s) {
List<Marca> marcas,smarcas=new ArrayList<Marca>();
try{
marcas= marcaDAO.findAllMarcas();
if(s.trim().equals("")) return marcas;
for(Marca m:marcas)
if (m.getNombreMarca().toString().contains(s) || m.getNombreMarca().toLowerCase().contains(s.toLowerCase())) {
smarcas.add(m);
}
return smarcas;
}catch(Exception e){
//JsfUtil.showFacesMsg(e,"Error al obtener las marcas de vehículos","",FacesMessage.SEVERITY_WARN);
e.printStackTrace();
JsfUtil.lanzarException(e);
return null;
}
}
//-----------------------------------------
//*.xhtml page
...
<p:autoComplete
id="cbxMarca" value="#{myBean.marca}" size="40"
converter="MarcaConverter"
completeMethod="#{myBean.obtenerMarcasVehiculos}"
var="m" itemLabel="#{m.nombreMarca}" itemValue="#{m}"
forceSelection="true" dropdown="true"
required="true" scrollHeight="200">
</p:autoComplete>
...
//-----------------------------------------
//Class Marca
public class Marca implements Serializable{
private static final long serialVersionUID = 1L;
private Integer codigoMarca;
private String nombreMarca;
...
Have you read the user guide? http://www.primefaces.org/documentation.html
I must say I have never used the autocomplete with pojo but from what I've read in the user guide, Çağatay Çivici says there:
Note that when working with pojos, you need to plug-in your own converter.
Here you can find out that a converter (PlayerConverter) is implemented even if player.name and of the other props are Strings.
I admit this is interesting and I'll do some research but I don't have the necessary time right now...
Change
converter="#{nazioneConverter}" to converter="nazioneConverter" in autocomplete
Change the itemValue from itemValue="#{nazione.codiceNazione}" to itemValue="#{nazione}" in autoComplete.

How disable widget?

I use GWT Editors framework for data binding.
I have next code:
AAAView.java
public interface AAAView extends Editor<AAA> {
public interface Presenter {
}
public interface Driver extends SimpleBeanEditorDriver<AAA, AAAViewImpl> {
}
void setPresenter(Presenter presenter);
Driver initializeDriver();
Widget asWidget();
}
AAAViewImpl.java
public class AAAViewImpl extends Composite implements AAAView {
interface AAAViewImplUiBinder extends UiBinder<Widget, AAAViewImpl> {
}
private static AAAViewImplUiBinder ourUiBinder = GWT.create(AAAViewImplUiBinder.class);
private Presenter presenter;
#UiField
ValueBoxEditorDecorator<String> firstName;
public AAAViewImpl() {
Widget rootElement = ourUiBinder.createAndBindUi(this);
initWidget(rootElement);
}
#Override
public void setPresenter(Presenter presenter) {
this.presenter = presenter;
}
#Override
public Driver initializeDriver() {
Driver driver = GWT.create(Driver.class);
driver.initialize(this);
return driver;
}
AAAViewImpl.ui.xml
<e:ValueBoxEditorDecorator ui:field="firstName">
<e:valuebox>
<g:TextBox maxLength="16" width="100%"/>
</e:valuebox>
</e:ValueBoxEditorDecorator>
How can I disable/enable firstName textbox in runtime?
Or how get access to the inner textbox of ValueBoxEditorDecorator object?
Anyone knows how to solve this problem? Thanks in advance.
Instead of setting the ui:field attribute on the ValueBoxEditorDecorator, set it on the inner TextBox. Then you can disable the TextBox by using:
firstName.setEnabled(false);

Resources