Vaadin : set value to TextField "from server" doesn't trigger CustomField::generateModelValue - vaadin

I have implemented CustomField which contains two simple textField.
public class MyCustomField extends CustomField<MyCustomPojo> {
private TextField freeTextField;
private TextField searchTextField;
private Binder<MyCustomPojo> binder;
private MyCustomPojo myCustomPojo;
public MyCustomField(){
this.binder = new Binder<>(MyCustomPojo.class);
this.myCustomPojo = new MyCustomPojo();
freeTextField = new TextField();
searchTextField = new TextField();
searchTextField.addFocusListener(event -> showSearchPopup());
}
public void handleSearchResult(String searchResult){
searchTextField.setValue(searchResult);
this.updateValue();
}
#Override
protected MyCustomPojo generateModelValue() {
binder.writeBeanIfValid(this.customPojo);
return this.customPojo;
}
#Override
protected void setPresentationValue(MyCustomPojo customPojo) {
if(oriasModel != null) {
this.customPojo= customPojo;
binder.readBean(this.customPojo);
}
}
}
The first textField can be freely filled with any user input.
The second textField is a little bit special because when the user focus on it a search dialog is open and the user have to search for a data and then the textfield value is set with Textfield::setValue operation.
My issue is that the operation "generateModelValue" is never call when I set the textfield value from search result. But when I first search for fill "searchTextField" and then input manually the
"freeTextField", then "generateModelValue" is called, and the resulting bean is populated.

Related

Multiselection of cells with muose and copy of TableView using JAVAFX

I have a TableView which is editable and multiple selection enabled. I wish to enter new data to some columns and rows. Then I wish to select using mouse and press CTRL-C to copy to clipboard.
I can use column.setCellFactory (TextFieldTableCell.forTableColumn ()); and my code works well for entering data like EXCEL. I could not select using mouse.
I read the reference How can I select multiple cells in tableview with javafx only by mouse?. If I try to implement it I need to use
final Callback<TableColumn<MyDataClass, String>, TableCell<MyDataClass, String>> myCellFactory = new DragSelectionCellFactory ();
column.setCellFactory (myCellFactory);.
Then I am unable to enter any data as CellFactory is different now..
How may I enter data like EXCEL and also select mouse and use CTRL-C to copy? Thanks for any help.
You can refactor the code in the link you provided so that it references another cell factory, and "decorates" the cells with the dragging functionality:
public class DragSelectionCellFactory<S,T> implements Callback<TableColumn<S,T>, TableCell<S,T>> {
private final Callback<TableColumn<S,T>, TableCell<S,T>> factory ;
public DragSelectionCellFactory(Callback<TableColumn<S,T>, TableCell<S,T>> factory) {
this.factory = factory ;
}
public DragSelectionCellFactory() {
this(col -> new TableCell<S,T>() {
#Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
} else {
setText(item.toString());
}
}
});
}
#Override
public TableCell<S,T> call(final TableColumn<S,T> col) {
TableCell<S,T> cell = factory.call(col);
cell.setOnDragDetected(event -> {
cell.startFullDrag();
col.getTableView().getSelectionModel().select(cell.getIndex(), col);
});
cell.setOnMouseDragEntered(event -> {
col.getTableView().getSelectionModel().select(cell.getIndex(), col);
});
return cell ;
}
}
Then you can do
TableColumn<Person, String> column = ...
column.setCellFactory(
new DragSelectionCellFactory<Person, String>(TextFieldTableCell.forTableColumn()));

How to show validator error messages to user when validation error occures?

I have the followinf scenario:
I have field with DoubleRangeValidator with error message specified
field.addValidator(new DoubleRangeValidator("Salary must be a numeric value.",0d,1000000d));
Under SAVE button I call BeanFieldGroup.commit() which raises exception on non numeric value in such field
To show errors I'm using ErrorUtils class mentioned here
Display error messages directly in Vaadin 7
.. which simply calls component.getErrorMessage() for all fields / components and gather all error messages. But the field with DoubleRange validator returns null for getErrorMessage() so no error message is available here. The same apply for other validators. So my question is how can I show validator error messages when validation error occures during the commit() ?
I've tried to reproduce your error with the ErrorUtils class you mentioned but the getErrorMessage method did not returned null. Maybe something is wrong with how you create your BeanFieldGroup and/or Field. Here's my code:
#Override
protected void init(VaadinRequest request) {
BeanFieldGroup<MyBean> bfg = new BeanFieldGroup<>(MyBean.class);
bfg.setItemDataSource(new MyBean());
Field<?> salaryField = bfg.buildAndBind("salary");
salaryField.addValidator(new DoubleRangeValidator("Salary must be a numeric value.", 0d, 1000000d));
Button commit = new Button("Save", e -> {
try {
bfg.commit();
}
catch (CommitException ce) {
ErrorUtils.showComponentErrors(bfg.getFields());
}
});
VerticalLayout hLayout = new VerticalLayout(salaryField, commit);
setContent(hLayout);
}
public class MyBean implements Serializable {
private static final long serialVersionUID = 1L;
private double salary;
public MyBean() {}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}

ContactsContract.CommonDataKinds.Phone CONTENT_FILTER_URI is not loading correct data

I'm trying to list all the available phone numbers with display name from contacts app in a ListView with search. Also if a contact has more than one phone number, it has to be displayed in separate list item (as different contact not as same contact in Contacts App).
I've successfully retrived all the phone numbers with display name and displayed in ListView. Multiple phone numbers of a contact also displayed as separate contact.
But, when I search - either it gives irrelevant phone number for the display name or it fails to filter when I entered single character. Please suggest on this.
Here is my code:
public class ContactsListFragment extends ListFragment implements
AdapterView.OnItemClickListener, LoaderManager.LoaderCallbacks<Cursor> {
// Defines a tag for identifying log entries
private static final String TAG = "ContactsListFragment";
private ContactsAdapter mAdapter; // The main query adapter
private String mSearchTerm; // Stores the current search query term
// Contact selected listener that allows the activity holding this fragment to be notified of
// a contact being selected
private OnContactsInteractionListener mOnContactSelectedListener;
/**
* Fragments require an empty constructor.
*/
public ContactsListFragment() {}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// Let this fragment contribute menu items
setHasOptionsMenu(true);
// Create the main contacts adapter
mAdapter = new ContactsAdapter(getActivity());
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
// Inflate the list fragment layout
return inflater.inflate(R.layout.contact_list_fragment, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
// Set up ListView, assign adapter and set some listeners. The adapter was previously
// created in onCreate().
setListAdapter(mAdapter);
getListView().setOnItemClickListener(this);
getListView().setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
});
}
#Override
public void onAttach(Activity activity){
super.onAttach(activity);
try{
// Assign callback listener which the holding activity must implement. This is used
// so that when a contact item is interacted with (selected by the user) the holding
// activity will be notified and can take further action such as extracting the contact
//details and pass it to AddNewUserDialogFragment
mOnContactSelectedListener = (OnContactsInteractionListener) activity;
}catch(ClassCastException e){
throw new ClassCastException(activity.toString()
+ " must implement OnContactsInteractionListener");
}
}
#Override
public void onPause(){
super.onPause();
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// Gets the Cursor object currently bound to the ListView
final Cursor cursor = mAdapter.getCursor();
// Moves to the Cursor row corresponding to the ListView item that was clicked
cursor.moveToPosition(position);
final String displayName = cursor.getString(ContactMobileNumbQuery.DISPLAY_NAME);
final String mobileNumb = cursor.getString(ContactMobileNumbQuery.NUMBER);
mOnContactSelectedListener.onContactSelected(displayName, mobileNumb);
}
/**
* Called when ListView selection is cleared, for example
* when search mode is finished and the currently selected
* contact should no longer be selected.
*/
private void onSelectionCleared() {
// Uses callback to notify activity this contains this fragment
mOnContactSelectedListener.onSelectionCleared();
// Clears currently checked item
getListView().clearChoices();
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
// Inflate the menu items
inflater.inflate(R.menu.contact_list_menu, menu);
// Locate the search item
MenuItem searchItem = menu.findItem(R.id.menu_search);
//sets up and configures the ActionBar SearchView
final SearchManager mSearchManager = (SearchManager)getActivity().getSystemService(Context.SEARCH_SERVICE);
// Retrieves the SearchView from the search menu item
final SearchView mSearchView = (SearchView) searchItem.getActionView();
// Assign searchable info to SearchView
mSearchView.setSearchableInfo(mSearchManager.getSearchableInfo(getActivity().getComponentName()));
// Set listeners for SearchView
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
// Called when the action bar search text has changed. Updates
// the search filter, and restarts the loader to do a new query
// using the new search string.
String newFilter = !TextUtils.isEmpty(newText) ? newText : null;
// Don't do anything if the filter is empty
if(mSearchTerm == null && newText == null){
return true;
}
// Don't do anything if the new filter is the same as the current filter
if(mSearchTerm != null && mSearchTerm.equals(newText)){
return true;
}
// Updates current filter to new filter
mSearchTerm = newFilter;
// Restarts the loader. This triggers onCreateLoader(), which builds the
// necessary content Uri from mSearchTerm.
getLoaderManager().restartLoader(ContactMobileNumbQuery.QUERY_ID, null, ContactsListFragment.this);
return true;
}
});
searchItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
// Nothing to do when the action item is expanded
return true;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
// When the user collapses the SearchView the current search string is
// cleared and the loader restarted.
if(!TextUtils.isEmpty(mSearchTerm)){
onSelectionCleared();
}
mSearchTerm = null;
getLoaderManager().restartLoader(ContactMobileNumbQuery.QUERY_ID, null, ContactsListFragment.this);
return true;
}
});
getLoaderManager().restartLoader(ContactMobileNumbQuery.QUERY_ID, null, ContactsListFragment.this);
}
#Override
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
if(!TextUtils.isEmpty(mSearchTerm)){
// Saves the current search string
outState.putString(SearchManager.QUERY, mSearchTerm);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item){
return super.onOptionsItemSelected(item);
}
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Log.i(TAG, "onCreateLoader starts");
//If this is the loader for finding contacts in the Contacts Provider
if(id == ContactMobileNumbQuery.QUERY_ID){
Uri contentUri;
// There are two types of searches, one which displays all contacts and
// one which filters contacts by a search query. If mSearchTerm is set
// then a search query has been entered and the latter should be used.
if(mSearchTerm == null){
// Since there's no search string, use the content URI that searches the entire
// Contacts table
contentUri = ContactMobileNumbQuery.CONTENT_URI;
}else{
// Since there's a search string, use the special content Uri that searches the
// Contacts table. The URI consists of a base Uri and the search string.
contentUri = Uri.withAppendedPath(Phone.CONTENT_FILTER_URI, Uri.encode(mSearchTerm));
}
// Returns a new CursorLoader for querying the Contacts table. No arguments are used
// for the selection clause. The search string is either encoded onto the content URI,
// or no contacts search string is used. The other search criteria are constants. See
// the ContactsQuery interface.
return new CursorLoader(getActivity(),
contentUri,
ContactMobileNumbQuery.PROJECTION,
ContactMobileNumbQuery.SELECTION,
null,
ContactMobileNumbQuery.SORT_ORDER);
}
Log.e(TAG, "onCreateLoader - incorrect ID provided (" + id + ")");
return null;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// This swaps the new cursor into the adapter.
if(loader.getId() == ContactMobileNumbQuery.QUERY_ID){
mAdapter.swapCursor(data);
}
}
#Override
public void onLoaderReset(Loader<Cursor> loader) {
if(loader.getId() == ContactMobileNumbQuery.QUERY_ID){
// When the loader is being reset, clear the cursor from the adapter. This allows the
// cursor resources to be freed.
mAdapter.swapCursor(null);
}
}
/**
* This is a subclass of CursorAdapter that supports binding Cursor columns to a view layout.
* If those items are part of search results, it will be bind to the view layout.
*/
private class ContactsAdapter extends CursorAdapter implements SectionIndexer {
private LayoutInflater mInflater; // Stores the layout inflater
private TextAppearanceSpan highlightTextSpan; // Stores the highlight text appearance style
/**
* Instantiates a new Contacts Adapter.
* #param context A context that has access to the app's layout.
*/
public ContactsAdapter(Context context) {
super(context, null, 0);
// Stores inflater for use later
mInflater = LayoutInflater.from(context);
}
#Override
public Object[] getSections() {
// TODO Auto-generated method stub
return null;
}
#Override
public int getPositionForSection(int section) {
// TODO Auto-generated method stub
return 0;
}
#Override
public int getSectionForPosition(int position) {
// TODO Auto-generated method stub
return 0;
}
/**
* Binds data from the Cursor to the provided view.
*/
#Override
public void bindView(View view, Context context, Cursor cursor) {
// Gets handles to individual view resources
final ViewHolder holder = (ViewHolder) view.getTag();
final String displayName = cursor.getString(ContactMobileNumbQuery.DISPLAY_NAME);
final String mobileNumb = cursor.getString(ContactMobileNumbQuery.NUMBER);
final int startIndex = indexOfSearchQuery(displayName);
if (startIndex == -1) {
// If the user didn't do a search, or the search string didn't match a display
// name, show the display name without highlighting
holder.text1.setText(displayName);
holder.mobile_text.setText(mobileNumb);
if (TextUtils.isEmpty(mSearchTerm)) {
} else {
}
}else {
// If the search string matched the display name, applies a SpannableString to
// highlight the search string with the displayed display name
// Wraps the display name in the SpannableString
final SpannableString highlightedName = new SpannableString(displayName);
// Sets the span to start at the starting point of the match and end at "length"
// characters beyond the starting point
highlightedName.setSpan(highlightTextSpan, startIndex,
startIndex + mSearchTerm.length(), 0);
// Binds the SpannableString to the display name View object
holder.text1.setText(highlightedName);
}
}
private int indexOfSearchQuery(String displayName) {
if (!TextUtils.isEmpty(mSearchTerm)) {
return displayName.toLowerCase(Locale.getDefault()).indexOf(
mSearchTerm.toLowerCase(Locale.getDefault()));
}
return -1;
}
/**
* Overrides newView() to inflate the list item views.
*/
#Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
// Inflates the list item layout.
final View itemLayout = mInflater.inflate(R.layout.contacts_list_view_item, viewGroup,false);
// Creates a new ViewHolder in which to store handles to each view resource. This
// allows bindView() to retrieve stored references instead of calling findViewById for
// each instance of the layout.
final ViewHolder holder = new ViewHolder();
holder.text1 = (TextView) itemLayout.findViewById(android.R.id.text1);
holder.text2 = (TextView) itemLayout.findViewById(android.R.id.text2);
holder.mobile_text = (TextView) itemLayout.findViewById(R.id.mobile_text);
// Stores the resourceHolder instance in itemLayout. This makes resourceHolder
// available to bindView and other methods that receive a handle to the item view.
itemLayout.setTag(holder);
// Returns the item layout view
return itemLayout;
}
}
/**
* A class that defines fields for each resource ID in the list item layout. This allows
* ContactsAdapter.newView() to store the IDs once, when it inflates the layout, instead of
* calling findViewById in each iteration of bindView.
*/
private class ViewHolder {
TextView text1;
TextView text2;
TextView mobile_text;
}
/**
* This interface must be implemented by any activity that loads this fragment. When an
* interaction occurs, such as touching an item from the ListView, these callbacks will
* be invoked to communicate the event back to the activity.
*/
public interface OnContactsInteractionListener {
/**
* Called when a contact is selected from the ListView.
* #param contactUri The contact Uri.
*/
public void onContactSelected(String name, String mobile);
/**
* Called when the ListView selection is cleared like when
* a contact search is taking place or is finishing.
*/
public void onSelectionCleared();
// Uses callback to notify activity this contains this fragment
}
/**
* This interface defines constants used by mobile number retrieval queries.
*/
public interface ContactMobileNumbQuery{
final static int QUERY_ID = 1;
//A Content Uri for Phone table
final static Uri CONTENT_URI = Phone.CONTENT_URI;
//The search or filter query Uri
final static Uri FILTER_URI = Phone.CONTENT_FILTER_URI;
final static String SELECTION = Phone.HAS_PHONE_NUMBER + "=1" + " AND " + Phone.DISPLAY_NAME_PRIMARY + "<>''";
final static String SORT_ORDER = Phone.SORT_KEY_PRIMARY;
final static String[] PROJECTION = {
Phone._ID,
Phone.DISPLAY_NAME_PRIMARY,
Phone.LOOKUP_KEY,
Phone.HAS_PHONE_NUMBER,
Phone.NUMBER,
Phone.TYPE,
SORT_ORDER
};
final static int ID = 0;
final static int DISPLAY_NAME = 1;
final static int LOOKUP_KEY = 2;
final static int HAS_PHONE = 3;
final static int NUMBER = 4;
final static int TYPE = 5;
}
}
Can somebody help me to fix it? Thanks in advance!
The below code fixes my issue.
#Override
public void bindView(View view, Context context, Cursor cursor) {
// Gets handles to individual view resources
final ViewHolder holder = (ViewHolder) view.getTag();
final String displayName = cursor.getString(ContactMobileNumbQuery.DISPLAY_NAME);
final String mobileNumb = cursor.getString(ContactMobileNumbQuery.NUMBER);
holder.text1.setText(displayName);
holder.mobile_text.setText(mobileNumb);
}

MVVMCross binding text on Ended event UITextField

I am trying to implement a custom binding on a subclass of UITextField so that the bound value is set when the user is done editing instead of with each keystroke because some interim values are invalid in the viewmodel (for example, while setting 'Age' to '26', a value of '2' is invalid so I'd like to wait to set the value until both digits are there). Something similar to setting UpdateSourceTrigger in xaml. I looked at several examples here:
MvvmCross UITextField custom binding is similar, as is MvvmCross: change update source trigger property of binding on MonoDroid (but for Android). I've also watch N=28 custom binding and looked at the source for MvxUITextFieldTextTargetBinding.
I think I'm close, but my custom binding never gets created and the UITextFields in my app still FireValueChanged with every keystroke.
I created the following Custom Binding:
public class UITextFieldFocusChangedBinding : MvxTargetBinding
{
private bool _subscribed;
private UITextField _view;
public UITextFieldFocusChangedBinding(UITextField target) : base(target)
{
_view = target;
}
public override void SetValue(object value)
{
if (_view == null) return;
_view.Text = (string)value;
}
public override void SubscribeToEvents()
{
var view = _view;
if (view == null)
return;
view.Ended += TextFieldOnEnded;
}
private void TextFieldOnEnded(object sender, EventArgs eventArgs)
{
var view = _view;
if (view == null)
return;
if (!view.IsFirstResponder)
FireValueChanged(view.Text);
_subscribed = true;
}
public override Type TargetType
{
get { return typeof(string); }
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.TwoWay; }
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
var view = _view;
if (view != null && _subscribed)
{
view.Ended -= TextFieldOnEnded;
_subscribed = false;
}
}
base.Dispose(isDisposing);
}
}
My setup.cs contains the following:
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
base.FillTargetFactories(registry);
registry.RegisterPropertyInfoBindingFactory(typeof(Bindings.UITextFieldFocusChangedBinding),typeof(UITextField), "Text");
}
and in my MvxViewController I have:
var set = this.CreateBindingSet<LifeNeedsView, LifeNeedsViewModel>();
set.Bind(_txtFinMedExpenses).To(vm => vm.FinalMedicalExpenses);
set.Apply();
The bindings work (values are passing correctly) but with every keystroke. Any suggestions on what I might be missing?

How to create a number of Fields dynamically in Blackberry Java SDK 5.0?

I'm trying to create a couple of BasicEditField objects after i get the number of fields that i want from an ObjectChoiceField.
Problem: the BasicEditField fields that i add to my screen don't refresh unless i do it in the listener from my ObjectChoiceField.
what i want to do :
select the number of BasicEditFields that i want.
refresh the screen so the fields added appear.
PD: if you need more info, just tell me, and sorry about my english. I'm new at developing for the BlackBerry plataform
public final class MyScreen extends MainScreen
{
private int fields_lenght;
public MyScreen()
{
// Set the displayed title of the screen
setTitle("Example");
fields_lenght =0;
final String shortcodes[] = {"1","2","3"};
final ObjectChoiceField dropdownlist=new ObjectChoiceField("Select a number of fields",shortcodes);
this.add(dropdownlist);
dropdownlist.setChangeListener( new FieldChangeListener() {
public void fieldChanged( Field arg0, int arg1 ) {
if(arg1 != PROGRAMMATIC){
fields_lenght= Integer.parseInt(shortcodes[dropdownlist.getSelectedIndex()]);
}
}
} );
// how to refresh the screen with the new fields ???
BasicEditField fields[]=new BasicEditField [fields_lenght] ;
for(int i = 0; i<fields.length;i++){
fields[i]=new BasicEditField("Campo "+i,"");
this.add(fields[i]);
}
}
}
You really should add or delete the fields from within your ObjectChoiceField listener. That's when you know what the proper number of fields is. (Certainly, if you just want to keep your code neat and clean, you could define a separate method, that is called from the choice field listener ... that's not much different).
Try something like this:
public final class MyScreen extends MainScreen {
/** A cached vector of the BasicEditFields, to make deleting easier */
private Vector fields;
public MyScreen() {
super(MainScreen.VERTICAL_SCROLL | MainScreen.VERTICAL_SCROLLBAR);
setTitle("Example");
final String shortcodes[] = {"1","2","3"};
final ObjectChoiceField dropdownlist = new ObjectChoiceField("Select a number of fields", shortcodes);
add(dropdownlist);
fields = new Vector();
final Screen screen = this;
dropdownlist.setChangeListener( new FieldChangeListener() {
public void fieldChanged( Field field, int context ) {
if (context != PROGRAMMATIC) {
// how many fields has the user chosen?
int fieldsLength = Integer.parseInt(shortcodes[dropdownlist.getSelectedIndex()]);
while (fieldsLength > fields.size()) {
// we need to ADD more fields
Field f = new BasicEditField("Campo " + fields.size(), "");
fields.addElement(f);
screen.add(f);
}
while (fieldsLength < fields.size()) {
// we need to DELETE some fields
Field f = (Field)fields.elementAt(fields.size() - 1);
fields.removeElement(f);
screen.delete(f);
}
}
}
});
}
I defined a new member named fields, which just makes it easier to keep track of the basic edit fields (in case this screen has many other fields, too).
When the choice field listener is called, I determine how many fields the user wants; if they need more, I add them to the screen, and to the fields Vector. If they want fewer, I delete some fields from the end of the Vector, and remove them from the Screen.
Note: there should be no need to call invalidate() here. Calling Screen#add() or Screen#delete() should add/delete the fields and cause repainting.

Resources