I want to use the GWT Editor framework with a CellList. My data model looks like this:
public class CarDto {
private String name;
private List<String> features;
// getter and setter
}
Using GWTP here is part of my presenter:
public class Presenter {
public interface MyView extends View, Editor<CarDto> {
}
private final SimpleBeanEditorDriver<CarDto, ?> editorDriver;
public Presenter(...) {
editorDriver = getView().createEditorDriver();
}
...
#Override
public void saveButtonClicked() {
CarDto carDto = editorDriver.flush();
int size = carDto.getFeatures().size(); // result is 0
}
}
My View class:
public class CarView implements Presenter.MyView {
public interface EditorDriver extends SimpleBeanEditorDriver<CarDto, CarView> {
}
#Path(value="name")
#UiField
TextBox nameInput; // editor works fine with this
#Path(value="features") // this editor is not working !!!
ListEditor<String, LeafValueEditor<String>> featuresEditor;
#UiField
CellList<String> cellList;
ListDataProvider<String> dataProvider;
public CarView() {
dataProvider = new ListDataProvider<String>();
dataProvider.addDataDisplay(cellList);
featuresEditor = HasDataEditor.of(cellList);
}
// create the editor driver
#Override
public SimpleBeanEditorDriver<CarDto, ?> createEditorDriver() {
EditorDriver driver = GWT.create(EditorDriver.class);
driver.initialize(this);
return driver;
}
#UiHandler("save")
protected void saveClicked(ClickEvent e) {
List<String> dtos = dataProvider.getList();
dtos.add("test");
getUiHandlers().saveButtonClicked();
}
}
When I hit save button and do editorDriver.flush() in my presenter than I only get the name property from the view's CarDto. The list of features is always empty.
I have to change the value of the featuresEditor manually like this:
featuresEditor.getList().add(...);
in order to get a change in the List after I flush it. This would mean that I have to set two lists to maintain the data:
featuresEditor.getList().add(...);
dataProvider.getList().add(...);
this does not seems to be correct.
How can I achieve that the ListEditor is updated correctly when the dataProvider list changes? How do I setup an Editor correctly to work with the List<String> which is handled by a CellList?
Related
Is it possible to maintain the value of Java variables in a custom react native module when reloading the JS? I would like to maintain components in the below code for debugging purposes. It persists on onHostResume if the app goes into the background but on reload the value is lost.
public class CustomModule extends ReactContextBaseJavaModuleWithEvents implements LifecycleEventListener {
public List<JsonObject> components = new ArrayList<>();
public CustomModule(ReactApplicationContext reactContext) {
super(reactContext);
reactContext.addLifecycleEventListener(this);
}
#ReactMethod
void addComponents(component) {
// add some components...
components.add(component);
}
#Override
public String getName() {
return "CustomModule";
}
#Override
public void onHostResume() {
getReactApplicationContext()
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("DEBUG_TAG", components.toString());
}
}
Every reload the JS code is creating a new instance of CustomModule reinitializing components. I should have set the components List as a static class variable so that it is only initialized once.
public class CustomModule extends ReactContextBaseJavaModuleWithEvents implements LifecycleEventListener {
public static List<JsonObject> components = new ArrayList<>();
}
I am currently writing an application that takes data from a database and populates an array which is used being used in several places throughout the application for displaying data in a Card View and a Map.
public class Filter {
public ArrayList<Event> eventsList;
public Filter() {
}
public void setEvents(ArrayList events) {
this.eventsList = events;
}
public ArrayList getEvents() {
return eventsList;
}
}
However I need to be able to allow users to filter that data as currently it returns everything from the database. I have no problem will filtering the data down but what I want to be able to do is have the option to remove filters but not effect any other filters that may be selected.
So for example if someone filters by location and date I want to be able remove one of those filters but the other one still apply and if I remove both then the data set will return to its default "Get All" value.
I am currently at a loss on how to approach this. Is there a simple way to be able to add and remove filters and have everything within the application update without any problems?
Shedding any light on this problem would be greatly appreciated.
I would follow this approach:
Create a Filter interface, which all the filters will extend:
public interface Filter {
public boolean filter(Event event);
}
Then you extend an adapter, which will store the filters.
public class FilterableAdapter extends BaseAdapter {
private List<Filter> _filters = new ArrayList<Filter>();
private List<Event> _items = null;
private List<Event> _filteredItems = new ArrayList<Filter>();
public void addFilter(Filter filter) {
_filters.add(filter);
_filterItems();
}
public void removeFilter(Filter filter) {
_filters.remove(filter);
_filterItems();
}
public List<Filter> getFilters() {
return _filters;
}
public void setItems(List<Event> items) {
_items = items;
_filterItems();
}
private void _filterItems() {
_filteredItems.clear();
for (Filter filter : _filters) {
for (Event event : _items) {
if (filter.filter(event)) {
_filteredItems.add(event);
}
}
}
notifyDataSetChanged();
}
#Override
public void getItem(int position) {
return _filteredItems.get(position);
}
#Override
public void getCount() {
return _filteredItems.size();
}
}
Then you create different filters, such as:
public class BigEventFilter implements Filter {
#Override
public boolean filter(Event event) {
return event.getAttendeeCount() > 100;
}
}
or one with parameters:
public class NiceCityFilter implements Filter {
private String _cityName;
public NiceCityFilter(String cityName) {
_cityName = cityName;
}
#Override
public boolean filter(Event event) {
return cityName.equals(event.getCity());
}
}
And then you can add them or remove them from your adapter:
eventAdapter.addFilter(new BigEventFilter());
eventAdapter.addFilter(new NiceCityFilter("Budapest"));
eventAdapter.removeFilter(eventAdapter.getFilters().get(0));
Probably you will have a UI for adding and removing filters, so you have to keep the filter references tied to the correct buttons. For this you could use View.setTag(bigEventFilter) / View.getTag() for example.
I have showed this example with an adapter because this is the most frequent use-case. But you could change it easily to a plain object which has a getFilteredItems() method which returns the internal _filteredItems list.
can anyone help how to pass value from one jInternalFrame1 to another jInternalFrame2?I can't make object of the jInternalFrame1 in jInternalFrame2.I have seen one solution by making constructor and oject the Jframe.But how?
"can you provide code for this data Model?"
The second internal frame accepts a DataModel object. The two will remain the same object when between the frames.
Note if you need something more complex (like back and forth interaction between the frames), you should look into some tutorial on Model View Controller architecture, where you will need to use PropertyChaneListeners and such
public class DataModel {
private String data;
public DataModel() {
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
public class MyInternalFrame1 extends JInternalFrame {
private DataModel dataModel = new DataModel();
public DataModel getDataModel() {
return dataModel;
}
}
public class MyInternalFrame2 extends JInternalFrame {
private DataModel dataModel;
public MyInternaFrame1() {}
public MyIntenalFrame2(DataModel datModel) {
this.dataModel = dataModel;
}
public void setDataModel(DataModel dataModel) {
this.dataModel = dataModel;
}
}
In the Main GUI program, you can do something like this
public class GUI extends JFrame {
MyInternalFrame1 iFrame1 = new MyInternalFrame1();
....
// somewhere else in code
DataModel dataModel = iFrame1.getDataModel();
dataModel.setData("Hello");
new MyInternalFrame2(dataModel);
}
The problem is that ContactDocuments removed with editor.getList().remove(index) are still passed for validation making it impossible to save edited Contact. For example requestContext.save() will fail with onConstraintViolation if I add new ContactDocument with editor.getList().add() then immideatly remove it because of #NotNull violation on some fields.
I have simple relation: Contact has many ContactDocuments. I'm trying to edit Contact with request factory and editors framework. ContactDocuments is annotated with JSR-303 for basic validation.
My ListEditor for ContactDocuments collection:
public class ContactDocumentListEditor extends Composite implements IsEditor<ListEditor<ContactDocumentProxy, ContactDocumentEditor>>, HasRequestContext<List<ContactDocumentProxy>> {
private RequestContext requestContext;
interface ViewUiBinder extends UiBinder<Widget, ContactDocumentListEditor> {}
private final static ViewUiBinder uiBinder = GWT.create(ViewUiBinder.class);
private final ListEditor<ContactDocumentProxy, ContactDocumentEditor> editor = ListEditor.of(new DocumentEditorSource());
#UiField
VerticalPanel container;
#UiField
Button addContactDocumentButton;
#UiHandler("addContactDocumentButton")
void addContactDocumentButtonClick(ClickEvent event) {
addNewContactDocument();
}
public ContactDocumentListEditor() {
initWidget(uiBinder.createAndBindUi(this));
}
private class DocumentEditorSource extends EditorSource<ContactDocumentEditor> {
#Override
public ContactDocumentEditor create(final int index) {
final ContactDocumentEditor documentEditor = new ContactDocumentEditor();
documentEditor.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
removeDocumentEditor(index);
}
});
container.insert(documentEditor, index);
return documentEditor;
}
#Override
public void dispose(ContactDocumentEditor subEditor) {
container.remove(subEditor);
}
#Override
public void setIndex(ContactDocumentEditor subEditor, int index) {
container.insert(subEditor, index);
}
}
#Override
public ListEditor<ContactDocumentProxy, ContactDocumentEditor> asEditor() {
return editor;
}
#Override
public void setRequestContext(RequestContext ctx) {
requestContext = ctx;
}
private void addNewContactDocument() {
ContactDocumentProxy newDocument = requestContext.create(ContactDocumentProxy.class);
editor.getList().add(newDocument);
}
private void removeDocumentEditor(int index) {
editor.getList().remove(index);
}
}
My Presenter to drive it:
final ContactRequestContext contactRequestContext = contactRequestContextProvider.get();
contactRequestContext.save(contact);
driver.edit(contact, contactRequestContext);
driver.flush().fire(new Receiver<Void>() {
#Override
public void onSuccess(Void response) {
// success
}
#Override
public void onConstraintViolation(Set<ConstraintViolation<?>> violations) {
for (ConstraintViolation violation : violations) {
logger.info("Contact constraint violation: " + violation.getPropertyPath() + " = " + violation.getMessage());
}
driver.setConstraintViolations(violations);
}
});
How can I fix it?
Either defer the creation of the real proxy by using a double (create a class that implements your proxy interface, create an instance of that class rather than an RF proxy, and on or after flush create the real proxies to replace the fake ones; that way you'll never create a proxy that won't be sent to the server).
Or if possible only validate your objects as part of others, never individually (don't validate a ContactDocument on its own, only as part of validating a Contact, using #Valid on the property containing the ContactDocuments): this can be accomplished using a ServiceLayerDecorator overriding the validate method, possibly combined with a #GroupSequence on either or both classes and the ServiceLayerDecorator validating using a specific group other than Default.
Related issue: Cannot remove proxy from RequestContext editing context
Will it be possible just to simply extend textfield in creating a custom widget that consists of a textbox and label and subsequently inheriting the functionality of the textfield as well as the eventhandling.
From what I understand is that one would normaly extend Composite and then implement initWidget() in the constructor.
initWidget(binder.createAndBindUi(this));
Can I do something similar by just extending textfield.
The reason I want to do this is because of creating an indicator textfield with label already but applying the eventhandling in this custom widget gives me unexpected results when I try to use it somewhere.
import com.google.gwt.core.client.GWT;
public class IndicatorTextField extends Composite implements HasText, HasKeyUpHandlers{
public interface Binder extends UiBinder<Widget, IndicatorTextField> {
}
private static final Binder binder = GWT.create(Binder.class);
public interface Style extends CssResource{
String textStyling();
String requiredInputLabel();
String colorNotValidated();
}
#UiField Style style;
#UiField Label label;
#UiField TextBox textBox;
public IndicatorTextField()
{
initWidget(binder.createAndBindUi(this));
}
public void setBackgroundValidateTextbox(boolean validated)
{
if(validated)
{
textBox.getElement().addClassName(style.colorNotValidated());
}
else
{
textBox.getElement().removeClassName(style.colorNotValidated());
}
}
#Override
public String getText() {
return label.getText();
}
#Override
public void setText(String text) {
label.setText(text);
}
#UiHandler("textBox")
public void onKeyUp(KeyUpEvent event)
{
DomEvent.fireNativeEvent(event.getNativeEvent(), this);
}
#Override
public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
//return textBox.addKeyUpHandler(handler);
return addDomHandler(handler, KeyUpEvent.getType());
}
}
Look at the default constructor of the TextBox class.
/**
* Creates an empty text box.
*/
public TextBox() {
this(Document.get().createTextInputElement(), "gwt-TextBox");
}
It creates the text input element. You can create your custom class LabeledTextBox with a constructor like this:
public class LabeledTextBox extends TextBox {
public MyTextBox() {
super(Document.get().createDivElement());
final DivElement labelElement = Document.get().createDivElement();
final InputElement textBoxElement = Document.get().createTextInputElement();
getElement().appendChild(labelElement);
getElement().appendChild(textBoxElement);
}
...
}
I didn't try this class myself. Most likely, it will require extra adjustments, there might be listener issues etc.
Do you really need to create a widget by subclassing TextBox? Why don't you use some sort of Panel instead? It's an easier approach as for me.