I can't find a method that allows me to pull the attributes from a component, or better, one specific attribute. Here is an example:
I have two text areas (components).
Both are expandable
While typing in the first one, it auto expands with Ajax, and the height grows.
I get the height attribute from the first text area
I set the height of the second text area to height I have got from the first one.
public class HomePage extends WebPage {
TextArea t = new TextArea("m", "hey");;
TextArea t2 = new TextArea("m2",
"this is a label with label ones attributes added");
public HomePage() {
add(t.add(new AttributeModifier("height", "100;")));
add(t2.add(HERE ADD THE ATTRIBUE HEIGHT FROM LABEL);
}
My solution uses JavaScript for the height modification. t1 is the one that by typing is growing, t2 is the one that's height is being adjusted. Clean and nice i think.
private TextArea textarea1() {
TextArea t1 = new TextArea("t1", Model.of("t1"));
final String js = "document.getElementById('%s').style.height = document.getElementById('%s').style.height;";
t1.add(new OnChangeAjaxBehavior() {
#Override
protected void onUpdate(AjaxRequestTarget target) {
target.appendJavaScript(String.format(js, textarea2.getMarkupId(), textarea1.getMarkupId()));
}
});
t1.setOutputMarkupId(true);
return t1;
}
private TextArea textarea2() {
TextArea t2 = new TextArea("t2", Model.of("t2"));
t2.setOutputMarkupId(true);
return t2;
}
Earlier in your page/panel class declare private fields and assign them the two textarea's
private Textarea textarea1;
private Textarea textarea2;
in ctor:
textarea1 = textarea1();
textarea2 = textarea2();
add(textarea1);
add(textarea2);
Related
It is possible to issue java.lang.reflect.Field to javafx.scene.control.TextField?
For example:
Field[] nodes;
nodes = clase.getDeclaredFields();
for (Field n : nodes)
if (n.getType().getSimpleName().equals("TextField"))
((TextField)((Object) n)).setText("Text");
If you want to modify the TextFields, you need to retrieve the value from those fields (and cast this value to TextField).
The following example should demonstrate the approach:
private TextField t1 = new TextField();
private TextField t2 = new TextField();
#Override
public void start(Stage primaryStage) {
Button btn = new Button("Say 'Hello World'");
btn.setOnAction((ActionEvent event) -> {
Object object = this;
Class clazz = object.getClass();
for (Field field : clazz.getDeclaredFields()) {
if (field.getType().getName().equals("javafx.scene.control.TextField")) {
try {
// get field value here
TextField textField = (TextField) field.get(object);
if (textField != null) {
textField.setText("Hello World");
}
} catch (IllegalArgumentException | IllegalAccessException ex) {
Logger.getLogger(ReflectTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
});
VBox root = new VBox();
root.getChildren().addAll(btn, t1, t2);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
Reflection is probably a really bad approach to this. Among many problems is that you make the functionality dependent on how the code is written. Specifically, you assume that each text field is stored in a specific instance field in some class. If you change the implementation, e.g. so that you keep the text fields in a data structure instead of maintaining references to them yourself, then your functionality will break. It is bad practice to write code that is so tightly coupled to the actual implementation of the code, for obvious reasons.
One better approach would simply to be to put all the text fields in a list (or other data structure), so you can do whatever you need with them easily. E.g.
public class MyForm {
private GridPane view ;
private String[] messages = {"First name:", "Last name", "Email"} ;
private List<TextField> textFields ;
public MyForm {
view = new GridPane();
textFields = new ArrayList<>();
for (int r = 0; r < messages.length ; r++) {
view.addRow(r, new Label(messages[r]), createTextField(messages[r]));
}
}
private TextField createTextField(String text) {
TextField textField = new TextField();
textField.setPromptText(text);
textFields.add(textField);
return textField ;
}
public void processTextFields() {
textField.forEach(tf -> tf.setText("Hello"));
}
}
Another approach would be to use a CSS lookup. If myForm is some node that is an ancestor of all the text fields:
myForm.lookupAll(".text-field").forEach(node -> {
TextField textField = (TextField)node ;
textField.setText("Hello");
});
but note that CSS lookups will not work until after CSS has been applied (by default, this means after the scene has been rendered for the first time).
Another way, if all the text fields are all contained in a single direct parent (such as the grid pane in the first example), would be to iterate through the child nodes and filter the text fields:
textFieldParentNode.getChildrenUnmodifiable().stream()
.filter(TextField.class::isInstance)
.map(TextField.class::cast)
.forEach(tf -> tf.setText("Hello"));
I am working on GXT 2.5.5
I have desinged a GRID in a project
In one column of the grid i have render a composite
It looks like this
This Choose evaluation column is Composite which is rendered in the Grid.
public class Evaluation extends Composite {
private RadioGroup rdgrpEvaluation;
private Radio radio_1;
// More radion buttons
private Radio radio_10;
}
All the radio_x.setValue(true) in the grid are set from the Model
int key = model.get("radioEvaluation");
switch (key) {
case 1:
evaluation.getRadio_1().setValue(true);
break;// more similar code
Now i want that when I click on radio button, the value of the Evalution column should also change.
Can some body help ?
I think that simplest way is call refresh whole table after selecting some button:
grid.getView().refresh(false);
But you also need to update your model.
When You click on radio button you may set value to your model like^
data.setEvalueation(int selectedRadio);
Or You can create specified ValueProvider to Evaluation column
ColumnConfig<Data,String> evaluationColumn = new ColumnConfig<Data, String>(new ValueProvider<Data>() {
#Override
public String getValue(Data o) {
String value = o.getRadioColumnValue();
return value;
}
#Override
public void setValue(Data o, Data o2) {
}
#Override
public String getPath() {
return "evaluation";
}
});
I have a datagrid that may display many rows per page. Let's say I am displayed 25 rows per page. The viewable area of the grid, however, is only 10 rows. i.e. There is only 400px for the entire grid and each row is 40px. So there is a scroll bar on the grid.
When I remove a single row in the grid, the grid automatically moves to the first row in the grid. If I have scrolled the bottom and deleted the last row, I am once again moved to the 1st row.
I have attempted several ways of combatting this, but I can't find a solution that works the way I want it to.
I've tried scrolling the row directly before or after the deleted row into view using the scrollIntoView() method.
I've tried figuring out how to determine which rows were in the visible range before the deletion, but the getVisibleRange() method is relevant to the page range, not the actual displayed range.
I've searched the web for this and seems like I'm the only one having this problem. What am I missing?
I had the same issue, I found that the bug happend if dataGrid has
keyboardSelectionPolicy="BOUND_TO_SELECTION"
If you use ListDataProvider to manage the DataGrid's data, then the DataGrid will not scroll when removing/adding items.
Here is a minimal example of removing grid rows without any scrolling (all contained within the entry point class):
Class for DataGrid Rows:
private class Item{
public String text;
public int value;
public Item(String text, int value){
this.text = text;
this.value = value;
}
}
Filling the DataGrid:
Here I use a private variable, data, to hold the items for the DataGrid. Note, that we must attach the dataGrid to data via the addDataDisplay method.
ListDataProvider data;
public void onModuleLoad() {
// build grid:
DataGrid dataGrid = new DataGrid();
BuildColumns(dataGrid);
dataGrid.setWidth("300px");
dataGrid.setHeight("300px");
// add items:
data = new ListDataProvider();
for(int i = 1; i < 25; i++){
data.getList().add(new Item("Item " + i, i));
}
data.addDataDisplay(dataGrid);
// display:
RootPanel.get().add(dataGrid);
}
Building the DataGrid:
This private method is used to build the columns for the DataGrid. Inside of the FieldUpdater for delCol, which is used to listen for click events for button columns, we remove the respective item from data, and call data.refresh() to update the DataGrid display.
private void BuildColumns(DataGrid dataGrid){
Column textCol = new Column(new SafeHtmlCell()) {
#Override
public SafeHtml getValue(Item object) {
SafeHtmlBuilder sb = new SafeHtmlBuilder();
sb.appendEscaped(object.text);
return sb.toSafeHtml();
}
};
dataGrid.addColumn(textCol);
dataGrid.setColumnWidth(textCol, 75, Unit.PCT);
Column deleteCol = new Column(new ButtonCell()) {
#Override
public String getValue(Item object) {
return "Delete " + object.value;
}
};
deleteCol.setFieldUpdater(new FieldUpdater() {
#Override
public void update(int index, Item object, String value) {
data.getList().remove(index);
data.refresh();
}
});
dataGrid.addColumn(deleteCol);
}
I put this code in a new GWT project and tested it. The DataGrid does not scroll when removing rows.
I have a dropdown component added on a page. the purpose of this dropdown is to change the type of input form that is rendered. for example, different forms have different required fields, editable fields, etc.
public final class Test extends WebPage
{
CustomPanel currentPanel = new MeRequest("repeater",FormType.MIN);
public Test(PageParameters parameters)
{
add(currentPanel);
DropDownChoice ddc = new DropDownChoice("panel", new PropertyModel(this, "selected"), panels, choiceRenderer);
ddc.add(new AjaxFormComponentUpdatingBehavior("onchange") {
protected void onUpdate(AjaxRequestTarget target) {
System.out.println("changed");
currentPanel = new MeRequest("repeater",FormType.PRO);
target.add(currentPanel);
}
});
add(ddc);
}
i've tried various options with limited results. the only real success has been updating the model, but what i really want to do is change how the components behave.
any thoughts on what i'm missing?
1) If you want to replace one panel with another you may just do the following.
First of all, you should output the markup id of the original panel:
currentPanel.setOutputMarkupId(true);
And then in the ajax event handler write something like that:
protected void onUpdate(AjaxRequestTarget target) {
CustomPanel newPanel = new MeRequest("repeater", FormType.PRO);
currentPanel.replaceWith(newPanel);
currentPanel = newPanel;
currentPanel.setOutputMarkupId(true);
target.addComponent(currentPanel);
}
In this case with every change of dropdown choice you add new panel to the page and you remove old panel from the page.
2) But I would proposed a slightly different approach to your problem. You should move the construction logic of your panel to the onBeforeRender() method:
public class MeRequest extends Panel {
private FormType formType;
public MeRequest(String id, FormType formType) {
super(id);
this.formType = formType;
// don't forget to output the markup id of the panel
setOutputMarkupId(true);
// constructor without construction logic
}
protected void onBeforeRender() {
// create form and form components based on value of form type
switch (formType) {
case MIN:
// ...
break;
case PRO:
// ...
break;
}
// add form and form components to panel
addOrReplace(form);
form.add(field1);
form.add(field2);
// ...
super.onBeforeRender();
}
public void setFormType(FormType formType) {
this.formType = formType;
}
}
Then you'll be able to only change type of the panel in the ajax event:
protected void onUpdate(AjaxRequestTarget target) {
currentPanel.setFormType(FormType.PRO);
target.addComponent(currentPanel);
}
Thus we rebuilt the original panel without recreating it.
Is it possible to load data lazily into a GWT DataGrid, similarly to how the GWT CellList lazily loads data?
I have a GWT DataGrid that can potentially bring back hundreds of rows, but only about 20 rows are displayed at a time. When this occurs, the loading of the grid is quite slow.
I want to use a DataGrid instead of a CellTList because I have multiple columns of data that need to be displayed. And I've opted for a DataGrid instead of a CellTable because I want the header columns to be fixed.
Since DataGrid doesn't expose it's ScrollPanel, create an inner class that extends DataGrid and provides a reference to the ScrollPanel:
private static class MyDataGrid<T> extends DataGrid {
public ScrollPanel getScrollPanel() {
HeaderPanel header = (HeaderPanel) getWidget();
return (ScrollPanel) header.getContentWidget();
}
}
Initialize the variables needed for this to work:
private MyDataGrid<MyDataType> myDataGrid;
private int incrementSize = 20;
private int lastScrollPos = 0;
In the constructor, create the grid:
myDataGrid = new MyDataGrid<MyDataType>();
Then add a ScrollHandler, using the getScrollPanel() reference that was just created:
myDataGrid.getScrollPanel().addScrollHandler(new ScrollHandler(){
#Override
public void onScroll(ScrollEvent event) {
int oldScrollPos = lastScrollPos;
lastScrollPos = myDataGrid.getScrollPanel().getVerticalScrollPosition();
// If scrolling up, ignore the event.
if (oldScrollPos >= lastScrollPos) {
return;
}
//Height of grid contents (including outside the viewable area) - height of the scroll panel
int maxScrollTop = myDataGrid.getScrollPanel().getWidget().getOffsetHeight() -
myDataGrid.getScrollPanel().getOffsetHeight();
if(lastScrollPos >= maxScrollTop) {
myDataGrid.setVisibleRange(0,myDataGrid.getVisibleRange().getLength()+incrementSize);
}
}
});