How to add ValueChangeHandler to the customize DateBox? - gwt

I want to add the functionality of value change handler to my customize class that extends the DateBox. I had already added the key handler but I also want to implement the value change handler to the same class.
I want my DateBox to work properly when I take input from DatePicker or Keyboard.
Any other suggestion will also be helpful.
public class ValidationDateBoxInternal extends DateBox implements KeyUpHandler{
private List<String> regexList;
public ValidationDateBoxInternal(){
super();
this.getTextBox().addKeyUpHandler(this);
regexList = new ArrayList<String>();
}
public void setAsNotEmpty() {
regexList.add(DateValidation.isNotEmpty);
isValid();
}
public void setAsValidDate(){
regexList.add(DateValidation.isValidDate);
isValid();
}
public void onKeyUp(KeyUpEvent event) {
isValid();
}
public void setText(String text) {
super.getTextBox().setText(text);
isValid();
}
public void clearRegexList() {
regexList.clear();
}
public String getText() {
if (regexList.size() == 0) {
return super.getTextBox().getText();
}
if (isValid()) {
for (String regex: regexList) {
if (regex.equals(DateValidation.isValidDate)) {
return super.getTextBox().getText().toLowerCase().trim();
}
}
return super.getTextBox().getText().trim();
}
else {
return null;
}
}
public boolean isValid() {
for (String regex: regexList) {
if (!DateValidation.isValid(super.getTextBox().getText(), regex)) {
this.addStyleName("invalid");
return false;
}
}
this.removeStyleName("invalid");
return true;
}
}

Your class extends DateBox, which implements the HasValueChangeHandlers interface. So you can call:
DateBox.addValueChangeHandler(ValueChangeHandler<java.util.Date> handler)
For example:
public class MyDateBox extends DateBox implements ValueChangeHandler<Date> {
void foo() {
addValueChangeHandler(this);
}
void onValueChange(ValueChangeEvent<Date> event) {
// validate the value of the DateBox
}
}

Related

How to convert normal data(returned from room) to LiveData on ViewModel layer

I am using the clean architecture with MVVM pattern so the room part goes into the data layer and I'm returning observables from there to domain layer and using them in presentation layer by wrapping them in a LiveData.
Now, the problem is that after insertion/deletion/update the list is not getting updated immediately in UI.
Viewmodel in Presentation Layer:
public class WordViewModel extends BaseViewModel<WordNavigator> {
//get all the use cases here
private GetAllWords getAllWords;
private InsertWord insertWord;
private DeleteThisWord deleteThisWord;
private UpdateThisWord updateThisWord;
private GetTheIndexOfTopWord getTheIndexOfTopWord;
//data
public MutableLiveData<List<Word>> allWords;
public WordViewModel(GetAllWords getAllWords, InsertWord insertWord, DeleteThisWord deleteThisWord, UpdateThisWord updateThisWord, GetTheIndexOfTopWord getTheIndexOfTopWord) {
this.getAllWords = getAllWords;
this.insertWord = insertWord;
this.deleteThisWord = deleteThisWord;
this.updateThisWord = updateThisWord;
this.getTheIndexOfTopWord = getTheIndexOfTopWord;
}
public void getAllWords() {
getAllWords.execute(new DisposableObserver<List<Word>>() {
#Override
public void onNext(List<Word> words) {
allWords.setValue(words);
}
#Override
public void onError(Throwable e) {
}
#Override
public void onComplete() {
}
}, GetAllWords.Params.getAllWords());
}
public void insertWord(Word word) {
insertWord.execute(new DisposableObserver<Boolean>() {
#Override
public void onNext(Boolean aBoolean) {
if (aBoolean)
Log.e("ganesh", "word inserted successfully!!!");
}
#Override
public void onError(Throwable e) {
e.printStackTrace();
}
#Override
public void onComplete() {
}
}, InsertWord.Params.insertWord(word));
}
public void getTheIndexOfTopWord(final String action) {
getTheIndexOfTopWord.execute(new DisposableObserver<Word>() {
#Override
public void onNext(Word word) {
if (word != null)
getNavigator().updateTopIndex(word.getWordId(), action);
}
#Override
public void onError(Throwable e) {
e.printStackTrace();
}
#Override
public void onComplete() {
}
}, GetTheIndexOfTopWord.Params.getTheIndexOfTopWord());
}
public void deleteThisWord(int wordId) {
deleteThisWord.execute(new DisposableObserver<Boolean>() {
#Override
public void onNext(Boolean aBoolean) {
if (aBoolean)
Log.e("ganesh", "word deleted successfully!!!");
}
#Override
public void onError(Throwable e) {
e.printStackTrace();
}
#Override
public void onComplete() {
}
}, DeleteThisWord.Params.deleteThisWord(wordId));
}
public void updateThisWord(int wordId, String newWord) {
updateThisWord.execute(new DisposableObserver<Boolean>() {
#Override
public void onNext(Boolean aBoolean) {
if (aBoolean)
Log.e("ganesh", "word updated successfully!!!");
}
#Override
public void onError(Throwable e) {
e.printStackTrace();
}
#Override
public void onComplete() {
}
}, UpdateThisWord.Params.updateThisWord(wordId, newWord));
}
public MutableLiveData<List<Word>> getWords() {
if (allWords == null) {
allWords = new MutableLiveData<>();
}
return allWords;
}
#Override
protected void onCleared() {
super.onCleared();
if (getAllWords != null)
getAllWords = null;
if (deleteThisWord != null)
deleteThisWord = null;
if (insertWord != null)
insertWord = null;
if (updateThisWord != null)
updateThisWord = null;
if (getTheIndexOfTopWord != null)
getTheIndexOfTopWord = null;
}
}
DAO in Data Layer:
#Dao
public interface WordDao {
#Insert
void insertThisWord(Word word);
#Query("delete from word_table")
void deleteAll();
#Query("select * from word_table order by word_id asc")
List<Word> getAllWords();
#Query("delete from word_table where word_id = :wordId")
void deleteThisWord(int wordId);
#Query("update word_table set word = :newWord where word_id = :wordId")
void updateThisWord(int wordId, String newWord);
#Query("select * from word_table order by word_id asc limit 1")
Word getTheIndexOfTopWord();
}
Repository in Data Layer:
public class WordRepositoryImpl implements WordRepository {
private ApiInterface apiInterface;
private SharedPreferenceHelper sharedPreferenceHelper;
private Context context;
private WordDao wordDao;
private WordRoomDatabase db;
public WordRepositoryImpl(ApiInterface apiInterface, SharedPreferenceHelper sharedPreferenceHelper, WordRoomDatabase db, Context context) {
this.apiInterface = apiInterface;
this.sharedPreferenceHelper = sharedPreferenceHelper;
this.context = context;
this.db = db;
wordDao = db.wordDao();
}
#Override
public Observable<Integer> sum(final int a, final int b) {
return Observable.fromCallable(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
return (a + b);
}
});
}
#Override
public Observable<List<Word>> getAllWords() {
return Observable.fromCallable(new Callable<List<Word>>() {
#Override
public List<Word> call() throws Exception {
List<Word> list = new ArrayList<>();
List<com.example.data.models.Word> listWords = db.wordDao().getAllWords();
for (com.example.data.models.Word item : listWords) {
list.add(new Word(item.getWordId(), item.getWord(), item.getWordLength()));
}
return list;
}
});
}
#Override
public Observable<Boolean> insertThisWord(final Word word) {
return Observable.fromCallable(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
com.example.data.models.Word item = new com.example.data.models.Word(word.getWord(), word.getWordLength());
db.wordDao().insertThisWord(item);
return true;
}
});
}
#Override
public Observable<Boolean> deleteThisWord(final int wordId) {
return Observable.fromCallable(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
db.wordDao().deleteThisWord(wordId);
return true;
}
});
}
#Override
public Observable<Boolean> updateThisWord(final int wordId, final String newWord) {
return Observable.fromCallable(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
db.wordDao().updateThisWord(wordId, newWord);
return true;
}
});
}
#Override
public Observable<Word> getTheIndexOfTopWord() {
return Observable.fromCallable(new Callable<Word>() {
#Override
public Word call() throws Exception {
com.example.data.models.Word item = db.wordDao().getTheIndexOfTopWord();
Word word = new Word(item.getWordId(), item.getWord(), item.getWordLength());
return word;
}
});
}
}
GetAllWordsUseCase in Domain Layer:
public class GetAllWords extends UseCase<List<Word>, GetAllWords.Params> {
private WordRepository wordRepository;
public GetAllWords(PostExecutionThread postExecutionThread, WordRepository wordRepository) {
super(postExecutionThread);
this.wordRepository = wordRepository;
}
#Override
public Observable<List<Word>> buildUseCaseObservable(Params params) {
return wordRepository.getAllWords();
}
public static final class Params {
private Params() {
}
public static GetAllWords.Params getAllWords() {
return new GetAllWords.Params();
}
}
}
UseCase Base Class in domain layer:
public abstract class UseCase<T, Params> {
private final PostExecutionThread postExecutionThread;
private final CompositeDisposable compositeDisposable;
public UseCase(PostExecutionThread postExecutionThread) {
this.postExecutionThread = postExecutionThread;
this.compositeDisposable = new CompositeDisposable();
}
/**
* Builds an {#link Observable} which will be used when executing the current {#link UseCase}.
*/
public abstract Observable<T> buildUseCaseObservable(Params params);
/**
* Dispose from current {#link CompositeDisposable}.
*/
public void dispose() {
if (!compositeDisposable.isDisposed()) {
compositeDisposable.dispose();
}
}
/**
* Executes the current use case.
*
* #param observer {#link DisposableObserver} which will be listening to the observable build
* by {#link #buildUseCaseObservable(Params)} ()} method.
* #param params Parameters (Optional) used to build/execute this use case.
*/
public void execute(DisposableObserver<T> observer, Params params) {
if (observer != null) {
final Observable<T> observable = this.buildUseCaseObservable(params)
.subscribeOn(Schedulers.io())
.observeOn(postExecutionThread.getScheduler());
addDisposable(observable.subscribeWith(observer));
}
}
/**
* Dispose from current {#link CompositeDisposable}.
*/
private void addDisposable(Disposable disposable) {
if (disposable != null && compositeDisposable != null)
compositeDisposable.add(disposable);
}
}
Finally, WordActivity in Presentation Layer
public class WordActivity extends BaseActivity<WordViewModel> implements
View.OnClickListener, WordNavigator {
#Inject
WordViewModel wordViewModel;
private Button deleteButton, updateButton, addButton;
private EditText editTextWord;
private WordListAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_word);
((MainApplication) getApplicationContext()).getComponent().inject(this);
editTextWord = findViewById(R.id.activity_word_et_word);
deleteButton = findViewById(R.id.activity_main_delete_button);
updateButton = findViewById(R.id.activity_main_update_button);
addButton = findViewById(R.id.activity_word_btn_add_word);
deleteButton.setOnClickListener(this);
updateButton.setOnClickListener(this);
addButton.setOnClickListener(this);
RecyclerView recyclerView = findViewById(R.id.recyclerview);
adapter = new WordListAdapter(this);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
getViewModel().setNavigator(this);
getViewModel().getAllWords();
getViewModel().getWords().observe(this, new Observer<List<Word>>() {
#Override
public void onChanged(#android.support.annotation.Nullable List<Word> words) {
adapter.setWords(words);
}
});
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.activity_main_delete_button:
getViewModel().getTheIndexOfTopWord(TOP_INDEX_ACTION_DELETE);
break;
case R.id.activity_main_update_button:
getViewModel().getTheIndexOfTopWord(TOP_INDEX_ACTION_UPDATE);
break;
case R.id.activity_word_btn_add_word:
handleAddButtonClick();
break;
}
}
public void handleAddButtonClick() {
String text = editTextWord.getText().toString();
if (text.equals("")) {
Toast.makeText(getApplicationContext(), R.string.empty_not_saved, Toast.LENGTH_LONG).show();
} else {
Word word = new Word(text, text.length());
getViewModel().insertWord(word);
editTextWord.setText("");
editTextWord.clearFocus();
}
}
#Override
public void updateTopIndex(Integer wordId, String action) {
if (action.equals(TOP_INDEX_ACTION_DELETE))
getViewModel().deleteThisWord(wordId);
else
getViewModel().updateThisWord(wordId, "dsakagdad");
}
#Override
public WordViewModel getViewModel() {
return wordViewModel;
}
}
**getViewModel().getWords().observe(this, new Observer<List<Word>>() {
#Override
public void onChanged(#android.support.annotation.Nullable List<Word> words) {
adapter.setWords(words);
}
});**
//This portion is getting called only once but not when I
insert/update/delete words from room database!
Can anyone go through these and help me out here!
This method in the DAO will query for the list and return it like a normal SQL query:
#Query("select * from word_table order by word_id asc")
List<Word> getAllWords();
If you want to observe for changes you might wanna consider using an RxJava2 Flowable/Observable or a LiveData for that.
As I prefer the RxJava approach, It will look like this:
#Query("select * from word_table order by word_id asc")
Flowable<List<Word>> getAllWords();
// or
Observable<List<Word>> getAllWords();
Difference between Flowable and Observable
With that done, you might wanna change the getAllWords method in the repository to return that Flowable/Observable.
Note: Either using an Observable or a Flowable both will emit the query result initially once and then start observing for further changes till unsubscribed to.
Read more about Room with RxJava

Multiple Click handlers

I have different 3 Different Buttons with different onclick events :
add.addClickHandler(new ClickHandler()
{
#Override
public void onClick(ClickEvent event)
{
add();
}
});
set.addClickHandler(new ClickHandler()
{
#Override
public void onClick(ClickEvent event)
{
set();
}
});
get.addClickHandler(new ClickHandler()
{
#Override
public void onClick(ClickEvent event)
{
get();
}
});
So now if i extend this up to 10 Buttons my Script would be far to long,
is there a way to pass the Methode or do seperate the Handlers?
Suppose you have some view:
customview.ui.xml
<g:VerticalPanel>
<style:Button ui:field="addButton" text="Add"/>
<style:Button ui:field="setButton" text="Set"/>
<style:Button ui:field="getButton" text="Get"/>
</g:VerticalPanel>
In your View class define 3 fields and 3 handlers:
CustomView.java
public class CustomView extends ViewWithUiHandlers<CustomUiHandlers>
implements CustomPresenter.MyView {
#UiField
Button addButton;
#UiField
Button setButton;
#UiField
Button getButton;
// Here constructor and other code
#UiHandler("addButton")
void onAddButtonClicked(ClickEvent event) {
if (getUiHandlers() != null) {
getUiHandlers().onAddClicked();
}
}
#UiHandler("setButton")
void onSetButtonClicked(ClickEvent event) {
if (getUiHandlers() != null) {
getUiHandlers().onSetClicked();
}
}
#UiHandler("getButton")
void onGetButtonClicked(ClickEvent event) {
if (getUiHandlers() != null) {
getUiHandlers().onGetClicked();
}
}
}
CustomUiHandlers.java
public interface CustomUiHandlers extends UiHandlers {
void onAddClicked();
void onSetClicked();
void onGetClicked();
}
CustomPresenter.java
public class CustomPresenter extends
Presenter<CustomPresenter.MyView, CustomPresenter.MyProxy>
implements CustomUiHandlers {
// Some code
#Override
public void onAddClicked() {
// Here your code
}
#Override
public void onSetClicked() {
// Here your code
}
#Override
public void onGetClicked() {
// Here your code
}
}
You can bind event handler to a method by UiBinder, or alternatively wait for lambda support for GWT.

ListEditorWrapper NPE

GWT 2.5.0
A simple case using ListEditor failed below, what did i miss?
public class OneBean {
private String name;
public OneBean() {
}
public OneBean(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "OneBean [name=" + name + "]";
}
}
public class OneListEditor extends Composite implements
IsEditor<ListEditor<OneBean, OneEditor>> {
interface OneListUiBinder extends UiBinder<Widget, OneListEditor> {}
OneListUiBinder uiBinder = GWT.create(OneListUiBinder.class);
#UiField
VerticalPanel panel;
public OneListEditor() {
initWidget(uiBinder.createAndBindUi(this));
}
#Override
public ListEditor<OneBean, OneEditor> asEditor() {
return listEditor;
}
private ListEditor<OneBean, OneEditor> listEditor = ListEditor
.of(new EditorSource<OneEditor>() {
#Override
public OneEditor create(int index) {
OneEditor widget = new OneEditor();
panel.insert(widget, index);
return widget;
}
});
}
public class OneEditor extends Composite implements Editor<OneBean> {
interface OneUiBinder extends UiBinder<Widget, OneEditor> {}
OneUiBinder uiBinder = GWT.create(OneUiBinder.class);
#UiField
TextBox name;
public OneEditor() {
initWidget(uiBinder.createAndBindUi(this));
}
}
public class OneListEditorApp implements EntryPoint {
#Override
public void onModuleLoad() {
List<OneBean> beans = new ArrayList<OneBean>();
beans.add(new OneBean("1st bean"));
beans.add(new OneBean("2nd bean"));
OneListEditor oneListEditor = new OneListEditor();
oneListEditor.asEditor().setValue(beans); // exception thrown here!
RootPanel.get().add(oneListEditor);
}
}
java.lang.NullPointerException: null
at com.google.gwt.editor.client.adapters.ListEditorWrapper.attach(ListEditorWrapper.java:95)
at com.google.gwt.editor.client.adapters.ListEditor.setValue(ListEditor.java:164)
at OneListEditorApp.onModuleLoad ....
void attach() {
editors.addAll(editorSource.create(workingCopy.size(), 0));
for (int i = 0, j = workingCopy.size(); i < j; i++) {
chain.attach(workingCopy.get(i), editors.get(i)); // ListEditorWrapper NPE here!
}
}
#EDIT
According to the answer from #Thomas Broyer, NPE is gone after EditDriver being wired to OneListEditor below,
interface OneEditorDriver extends
SimpleBeanEditorDriver<OneBean, OneEditor> {}
OneEditorDriver driver = GWT.create(OneEditorDriver.class);
#Override
public ListEditor<OneBean, OneEditor> asEditor() {
listEditor.setEditorChain(new EditorChain<OneBean, OneEditor>() {
#Override
public OneBean getValue(OneEditor subEditor) {
return null;
}
#Override
public void detach(OneEditor subEditor) {
}
#Override
public void attach(OneBean object, OneEditor subEditor) {
driver.initialize(subEditor);
driver.edit(object);
}
});
return listEditor;
}
You're not using an EditorDriver, so the ListEditor is not initialized with an EditorChain, so chain is null, hence the NPE. Case made.
⇒ use an EditorDriver (or do not use a ListEditor)

Paste event on GWT

I found an example of how to catch the Paste event on a TextArea on GWT but it doesn't work.
public MyTextArea() {
super();
sinkEvents(Event.ONPASTE);
}
#Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
switch (event.getTypeInt()) {
case Event.ONPASTE:
System.out.println("Paste Detected");
Window.alert("Paste Works!!! Yippie!!!");
break;
}
}
The problem is that I never enter to onBrowserEvent ... Any suggestion ?
Thnx
Works for me as intended:
public class Starter implements EntryPoint {
#Override
public void onModuleLoad() {
RootPanel.get().add(new MyTextArea());
}
class MyTextArea extends TextArea {
public MyTextArea() {
super();
sinkEvents(Event.ONPASTE);
}
#Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
switch (event.getTypeInt()) {
case Event.ONPASTE:
System.out.println("Paste Detected");
Window.alert("Paste Works!!! Yippie!!!");
break;
}
}
}
}
On what browser are you testing it?

Does anyone have a working examples of ActionCells working within a CompositeCell?

I tried following the example, http://gwt.google.com/samples/Showcase/Showcase.html#!CwCellTree , and added two ActionCells inside of the CompositeCell with no luck. The ActionCell's onBrowserEvent() does not get triggered.
This simple example works for me. Since you didn't provide any code or further explanation on what exactly you're trying to achieve, I have no idea whether my example is of any help or not.
public void onModuleLoad() {
CellTable<Person> table = new CellTable<Starter.Person>();
List<HasCell<Person, ?>> cells = new LinkedList<HasCell<Person, ?>>();
cells.add(new HasCellImpl("first name", new Delegate<Person>() {
#Override
public void execute(Person object) {
Window.alert(object.getFirstName());
}
}));
cells.add(new HasCellImpl("last name", new Delegate<Starter.Person>() {
#Override
public void execute(Person object) {
Window.alert(object.getLastName());
}
}));
CompositeCell<Person> cell = new CompositeCell<Person>(cells);
table.addColumn(new TextColumn<Starter.Person>() {
#Override
public String getValue(Person object) {
return object.getFirstName() + " " + object.getLastName();
}
}, "name");
table.addColumn(new Column<Person, Person>(cell) {
#Override
public Person getValue(Person object) {
return object;
}
}, "composite");
LinkedList<Person> data = new LinkedList<Starter.Person>();
data.add(new Person("Amy", "Reed"));
data.add(new Person("Tim", "Gardner"));
table.setRowData(data);
RootPanel.get().add(table);
}
private class HasCellImpl implements HasCell<Person, Person> {
private ActionCell<Person> fCell;
public HasCellImpl(String text, Delegate<Person> delegate) {
fCell = new ActionCell<Person>(text, delegate);
}
#Override
public Cell<Person> getCell() {
return fCell;
}
#Override
public FieldUpdater<Person, Person> getFieldUpdater() {
return null;
}
#Override
public Person getValue(Person object) {
return object;
}
}
private class Person {
private String fFirstName;
private String fLastName;
public Person(String first, String last) {
fFirstName = first;
fLastName = last;
}
public String getFirstName() {
return fFirstName;
}
public String getLastName() {
return fLastName;
}
}