I am attempting to load a custom component(descending from UIInput). I then encode an html input back to the client. My component loader is thus:
#FacesComponent("TomsWidgetComponent")
#SessionScoped
public class TomsWidgetComponent {
public TomsInput getNewInput(UIComponent parent)
{
ExpressionFactory factory = getFacesContext().getApplication().getExpressionFactory();
TomsInput newComponent = (TomsInput) getFacesContext().getApplication().createComponent(getFacesContext(), "org.tom.example.toms.TomsInput", "org.tom.example.toms.TomsInput");
String newId = FacesContext.getCurrentInstance().getViewRoot().createUniqueId();
newComponent.setId(newId);
elements.put(newId, newComponent);
newComponent.setInputData(new InputData());
ValueExpression valueExpression = factory.createValueExpression(getFacesContext().getELContext(),"#{tomsInput.string}",String.class);
newComponent.setValueExpression("value", valueExpression);
getChildren().add(newComponent);
pushComponentToEL(getFacesContext(), newComponent);
return newComponent;
}
html:
<"input type="tel" id="j_id2" oninput="mojarra.ab(this,event,0,'execute',0)" /input >"
The input shows up just fine, but ajax event never seems show up in my component. I've tried several permutations, with the key on setValueExpression, and adding behavior listeners.
...
Ive gotten passed the exceptions but the Ajax now coming back from the form is causing my component to reload. It's content is:
tomswidgetform=tomswidgetform&j_id2=fffdsdfgbg&javax.faces.ViewState=-6270730402975544133%3A7227399941332846704&javax.faces.source=j_id2&javax.faces.partial.event=input&javax.faces.partial.execute=j_id2%20j_id2&javax.faces.behavior.event=change&AJAX%3AEVENTS_COUNT=1&javax.faces.partial.ajax=true
Any idea what might be wrong? Thanks.
Related
Problem: Checkboxes values are not being bound to my form, properly. The result is that all my boolean values are null (at least the ones not being bound), and the existing ones are not being updated with values changed by the user.
Details: I'm aware that checkboxes are not submitted to the server if they are not selected. However, I do see the values in the request when hooking up an Eclipse debugger. The data is populated using jQuery/Datatable, but the data is posted back to the server using a form submit.
Spring MVC Version: 3.2.8
I'm assuming its configuration, but I'm not seeing where I am wrong. Here is a small code snippet of what I'm doing in my controller.
#Controller
public class CheckboxController {
...
#RequestMapping(value = "saveCheckboxes*", method = RequestMethod.POST)
public String saveCheckboxes(#ModelAttribute(SESSION_FORM_KEY) CheckboxForm form, BindingResult result, ModelMap model) {
// VALIDATE HERE...
if ( !result.hasErrors() ) {
// SAVE
}
else {
// DON'T SAVE (alert user)
}
}
}
So Spring MVC is used to binding request inputs to my form. The form is defined below, which has a list of summary objects with a boolean property.
public class CheckboxForm {
private List<Summary> summaries;
...
}
public class Summary {
private boolean selected;
...
}
I use jQuery/Datatables to populate my online grid of data. The inputs are created dynamically using a callback within datatables.
var tableWidget = (function($) {
init = function() {
...
"aoColumnDefs": [
{ "aTargets": [0], "sName": "", "mData": "selected" "stype": "html", "sClass": "center", "mRender": renderCheckbox, "bSortable":false, "sWidth": "50px" }
...
};
renderCheckbox = function(source, type, row) {
var $name = 'checkboxForm.summaries['+row.index+'].selected';
return createCheckbox($name, source);
};
createCheckbox = function(name, checked) {
var $checked = (checked === true) ? ' checked="checked"' : '';
return '<input type="checkbox" name="'+name+'" value="true"'+$checked+'/><input type="hidden" name="_'+name+'" value="on"/>';
}
...
))(jQuery);
After all of this, I hooked up the debugger and traced it into the WebDataBinder. I found that it seems to throw and exception in the method:
public boolean isWritableProperty(String propertyName)
saying the property cannot be evaluated. This happens for each property returned. However, I can confirm that what is in the request is the very inputs that I am expecting.
First, unless you know why avoid relative URL in #RequestMapping methods. It is a common cause of errors.
Next, as you directly generate your checkboxes without all the bells and whistles that adds spring:checkbox, you wont't get automatic error messages, and could experience problems in getting last checkboxes values if they are unchecked, as they will not be transmitted by browser and Spring will never see them giving a shorter list (or even an empty list if all are unchecked).
That being said, your problem is that you use checkboxForm.summaries[index].selected where Spring would expect only summaries[index].selected. Remove checkboxFormand your controller should affect values to the #ModelAttribute CheckboxForm form.
In a Play 2.2! web project I'm pursuing, I'd like to return views by name in Application.java
I've added the following in the routes config :
GET /:page controllers.Application.show(page: String)
And i'd like Application.java to return the correct view only using it's name (the String page).
At the moment I have :
public static Result show(String page) {
switch(page){
case "home":
return ok(home.render());
case "register":
return ok(register.render());
}
return ok(home.render());
}
I'd like to avoid the switch statement here, and have show(String page) programatically find the view that matches the String page given in argument and return it (or home page if no match has been found).
EDIT : I've read some stuff about reflexion but I don't really know what that is or how to use it :/
Thanks for your insight :)
Remember that Play's view is a Scala function - which takes parameters, for ensuring typesafety, dynamic content etc, etc. In this scenario you shouldn't use :path argument but make usage of different routes to different actions like:
GET /home controllers.Application.home
GET /register controllers.Application.register
Actions:
public static Result home() {
return ok(home.render());
}
public static Result register() {
return ok(register.render());
}
Crypto-advertisment: Use Intellij - create templates for actions and routes and you will be doing it within milliseconds ;)
On the other hand if you have a large set of HTML files you can render them as... files instead of Play views like (pseudo code, debug it yourself!)
public static Result show(String page) {
File htmlFile = new File(page+".html");
if (!htmlFile.exists()) htmlFile = new File("home.html");
return ok(htmlFile).as("text/html");
}
I will only add that is absolutely NOT Play's way for working with templates ;)
I am using Primefaces/JSF in combination with pure javascript tools in order to implement an image viewer & annotator. Image viewer is built upon the OpenLayers framework.
When the user annotates (draws shapes) on the canvas, a JSON object is created and upon Save action passed to the back bean. Back bean retrieves the object (deserialized) and stores it in to a file.
Here is the relevant code:
OpenLayers javascript (image-viewer.js):
function initialiseMap(){'
...
map = new OpenLayers.Map(imageEditorID, options);
imageLayer = new OpenLayers.Layer.TMS(imgURL, "", {
...
});
map.addLayer(imageLayer);
var vlayer = new OpenLayers.Layer.Vector("Editable");
map.addLayer(vlayer);
//draw controls and shape tools
...
//then define save action
var save = new OpenLayers.Control.Button({
...
var GEOJSON_PARSER = new OpenLayers.Format.GeoJSON();
var vectorLayerAsJson = GEOJSON_PARSER.write(vlayer.features);
//and finally post to server layer with drawn shapes
sendJSONToServer([{name:'param', value:vectorLayerAsJson}]);
...
The above Image Viewer/Map tool, is loaded via an p:outputPanel component of primefaces and uses sendJSONToServer remoteCommand to get JSON layer:
<h:head>
<script src="#{facesContext.externalContext.requestContextPath}/js/image-viewer.js" />
...
<h:body>
<h:form id="imageEditor">
<p:fieldset legend="Viewer">
...
// inoutHidden does not have on* events? how am i going to post to image-viewer.js?
<h:inputHidden value="#{imageAnnotations.fetchJsonString()}" />
...
<p:outputPanel layout="block" styleClass="imageEditorImagePanel" />
<p:remoteCommand immediate="true" name="sendJSONToServer" action="#{imageAnnotations.actionOnString}" />
</p:fieldset>
....
Finally in the backbean the JSON object is fetched and stored in a file (implementation is raw):
#ManagedBean(name="imageAnnotations")
public class ImageAnnotations {
//actionOnString fetches and saves the JSON string - this is a raw impementation
public String actionOnString() {
//Do the job and get and save JSON string
}
public String fetchJsonString(){
//Do the job and get JSON string
return jsonString;
}
}
The question is How am i going to use a JSF or primefaces element to make available the imageAnnotations.fetchJsonString() value for fetching from within js?
Even I can't give all answers, for me the filling of your hiddenInput should be managed as following:
#ManagedBean(name="imageAnnotations")
public class ImageAnnotations {
private String jsonString;
public void anyMethodFillingOrInitializingTheJSONString() {
this.jsonString = resultOfYourWork();
}
public String getJsonString(){
return this.jsonString();
}
public void setJsonString(String item) {
this.jsonString = item;
}
}
When you reload this hidden input field, just be sure to trigger a javascript parsing the String and updating your client-side Model. This can be done via the on* - events you can connect with Primefaces buttons.
Guys, can anybody help with the other parts?
I need the URL for a component in wicket. When I use a page it works properly, but when using panel it does not work.
public final class ImageP extends Panel {
public ImageP(String id) {
super(id);
List<Mapp> list = Mapp.loadall(); //load image from database
final Mapp asr = list.get(0);
ByteArrayResource resource = new ByteArrayResource("image/jpeg", asr.getImage());
Image image = new Image("img", resource);
add(image);
System.out.println(getRequestCycle().urlFor(image, IResourceListener.INTERFACE));
}
}
This code does not work and throws an exception, but when I use page instead of panel getRequestCycle().urlFor(image, IResourceListener.INTERFACE) it works properly.
I bet you've got the following exception:
java.lang.IllegalStateException: No Page found for component [Component id = img]
It's because RequestCycle object internally calls getPage() method of the component that's first parameter of the urlFor() method with the following signature:
urlFor(Component component, RequestListenerInterface interface)
In case of calling method urlFor() in the constructor of a panel it's impossible to get page of a panel's child because panel isn't attached to page yet. So Wicket throws "a nice exception".
To fix that problem you just can move your code to the onBeforeRender() method of the panel. Something like that:
#Override
protected void onBeforeRender() {
//
// ... init resource ...
//
Image image = new Image("img", resource);
addOrReplace(image);
System.out.println(getRequestCycle().urlFor(image, IResourceListener.INTERFACE));
super.onBeforeRender();
}
P.S. I also assume that you're using Wicket 1.4 or earlier because there's no RequestCycle.urlFor(component, listener) method in Wicket 1.5 and later. So I think neither your question nor my answer doesn't make sense in that case.
Any idea how I can implement proper pagination without a RPCProxy in GXT? I am currently setting the loader like this:
final PagingLoader<PagingLoadResult<ModelData>> loader = new BasePagingLoader<PagingLoadResult<ModelData>>(null);
store = new ListStore<T>(loader);
And then pass the store to the grid constructor.
Now, if I set null instead of a proxy in the constructor, my pagingToolbar just freezes and goes disabled and displays what appears to be a loading circle.
I read the ideas in here http://www.sencha.com/forum/showthread.php?61780-Pagination-without-RPC, but can anyone be a bit more explicit on how to achieve this?
I am creating the grid and then adding the data and I'm working with RequestFactory so no RCPProxy needed.
You can just implement the DataProxy interface and use your custom data-obtaining method:
BasePagingLoader<PagingLoadResult<ModelData>> loader = new BasePagingLoader<PagingLoadResult<ModelData>>(new DataProxy<PagingLoadResult<ModelData>>() {
#Override
public void load(DataReader<PagingLoadResult<ModelData>> reader,
Object loadConfigAsObject, AsyncCallback<PagingLoadResult<ModelData>> callback) {
BasePagingLoadConfig loadConfig = (BasePagingLoadConfig) loadConfigAsObject;
// Get the results for the requested page...
BasePagingLoadResult<ModelData> pagingLoadResult = new BasePagingLoadResult<ModelData>(...);
callback.onSuccess(pagingLoadResult);
}
});