Note:
There is a lot of code/diagnostics, first I discuss my problem, followed by a lot of code behind (to help answer any questions), finally I add 3 different blocks of diagnostics to hopefully answer any more questions. Obviously I don't expect the reader to read through everything.
The problem:
Whenever I run my app and display the same view (after dismissing it) my console output displays that previous bindings still exist.
Details:
The view I am displaying is as follows: There is a tableview that has its source bound to my ViewModel, each of the cells have the left/right labels bound to the ViewModel.
I created the above view as a modal popover view. Each cell navigates the user to a new view where he/she can edit the field. Going to the new view and navigating with the 'back' button doesn't cause any problems (to my knowledge). Once the user presses a button to dismiss the modal popover ("Cancel" for example), the next time the view is displayed, the old bindings seem to exist. Looking under the Diagnostics shows how the values are repeated. I have no idea why.
I create my tableview and in GetOrCreateCellFor I make a new TimesheetOptionCell for the cells that I have problems with the bindings.
Code Behind:
Inside my ViewDidLoad() of my TimesheetEntryView I set the ItemsSource
var source = new TimesheetTableSource (TableView, this);
var set = this.CreateBindingSet<TimesheetEntryView, TimesheetEntryViewModel> ();
set.Bind (source).For (src => src.ItemsSource).To (vm => vm.Options);
set.Apply ();
TableView.Source = source;
Inside my TimesheetTableSource:
ObservableCollection<ViewModelBase> _options;
public override System.Collections.IEnumerable ItemsSource
{
get
{
return _options;
}
set
{
_options = (ObservableCollection<ViewModelBase>)value;
if (_options != null)
{
this.ReloadTableData ();
}
}
}
public override int NumberOfSections (UITableView tableView)
{
return 3;
}
public override int RowsInSection (UITableView tableview, int section)
{
if (section == 0)
{
return _options.Count;
}
else if (section == 1)
{
return 2;
}
else if (section == 2)
{
return 1;
}
else
{
return 0;
}
}
protected override UITableViewCell GetOrCreateCellFor (UITableView tableView, NSIndexPath indexPath, object item)
{
if(indexPath.Section == 0)
{
return TimesheetOptionCell.Create ();
}
GenericOneLabelCell cell = GenericOneLabelCell.Create ();
if (indexPath.Section == 1 && indexPath.Row == 0)
{
cell.LabelText = "Save";
var set = _timesheetView.CreateBindingSet<TimesheetEntryView, TimesheetEntryViewModel> ();
set.Bind (cell).For (cll => cll.CellEnabled).To (vm => vm.SaveEnabled);
set.Apply ();
}
else if (indexPath.Section == 1 && indexPath.Row == 1)
{
cell.LabelText = "Apply";
var set = _timesheetView.CreateBindingSet<TimesheetEntryView, TimesheetEntryViewModel> ();
set.Bind (cell).For (cll => cll.CellEnabled).To (vm => vm.SaveEnabled);
set.Apply ();
}
return cell;
}
Inside my TimesheetOptionCell:
public TimesheetOptionCell (IntPtr handle) : base (handle)
{
this.DelayBind (() =>
{
//set.bind(<label/textView>) implicitly adds .For("Text")
var set = this.CreateBindingSet<TimesheetOptionCell, OptionViewModelBase>();
set.Bind(FieldDescriptionTextView).To(option => option.OptionValue);
set.Bind(FieldTitleLabel).To(option => option.Title);
set.Apply();
});
}
public static TimesheetOptionCell Create ()
{
return (TimesheetOptionCell)Nib.Instantiate (null, null) [0];
}
Diagnostics:
Here is the first time I display the view:
2013-08-06 09:07:13.824 FCXiOSv2[16478:21e03] mvx: Diagnostic: 6.70 Showing ViewModel TimesheetEntryViewModel
2013-08-06 09:07:13.825 FCXiOSv2[16478:21e03] TouchNavigation: Diagnostic: 6.70 Navigate requested
2013-08-06 09:07:13.840 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 6.72 Receiving setValue to System.Collections.ObjectModel.ObservableCollection`1[FCX.Core.ViewModels.ViewModelBase]
2013-08-06 09:07:13.873 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 6.75 Receiving setValue to 7/23/2013
2013-08-06 09:07:13.874 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 6.75 Receiving setValue to Date Worked
2013-08-06 09:07:13.881 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 6.76 Receiving setValue to 0:00
2013-08-06 09:07:13.882 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 6.76 Receiving setValue to Time Worked
2013-08-06 09:07:13.888 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 6.77 Receiving setValue to
2013-08-06 09:07:13.889 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 6.77 Receiving setValue to Company
2013-08-06 09:07:13.894 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 6.77 Receiving setValue to
2013-08-06 09:07:13.894 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 6.77 Receiving setValue to Description
2013-08-06 09:07:13.899 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 6.78 Receiving setValue to False
2013-08-06 09:07:13.903 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 6.78 Receiving setValue to False
After the second time, I get this:
2013-08-06 09:17:43.965 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.85 Receiving setValue to
2013-08-06 09:17:43.966 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.85 Receiving setValue to
2013-08-06 09:17:43.967 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.85 Receiving setValue to
2013-08-06 09:17:43.967 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.85 Receiving setValue to
2013-08-06 09:17:43.968 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.85 Receiving setValue to
2013-08-06 09:17:43.969 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.85 Receiving setValue to 7/23/2013
2013-08-06 09:17:43.970 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.85 Receiving setValue to 7/23/2013
2013-08-06 09:17:43.971 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.85 Receiving setValue to 0:00
2013-08-06 09:17:43.972 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.85 Receiving setValue to
2013-08-06 09:17:43.972 FCXiOSv2[16478:21e03] mvx: Diagnostic: 636.85 Showing ViewModel TimesheetEntryViewModel
2013-08-06 09:17:43.973 FCXiOSv2[16478:21e03] TouchNavigation: Diagnostic: 636.85 Navigate requested
2013-08-06 09:17:44.017 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.90 Receiving setValue to System.Collections.ObjectModel.ObservableCollection`1[FCX.Core.ViewModels.ViewModelBase]
2013-08-06 09:17:44.024 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.90 Receiving setValue to 7/23/2013
2013-08-06 09:17:44.025 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.90 Receiving setValue to Date Worked
2013-08-06 09:17:44.031 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.91 Receiving setValue to 0:00
2013-08-06 09:17:44.032 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.91 Receiving setValue to Time Worked
2013-08-06 09:17:44.042 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.92 Receiving setValue to
2013-08-06 09:17:44.043 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.92 Receiving setValue to Company
2013-08-06 09:17:44.050 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.93 Receiving setValue to
2013-08-06 09:17:44.050 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.93 Receiving setValue to Description
2013-08-06 09:17:44.053 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.93 Receiving setValue to False
2013-08-06 09:17:44.055 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 636.94 Receiving setValue to False
After the 10th time:
2013-08-06 09:21:08.390 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.27 Receiving setValue to
2013-08-06 09:21:08.391 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.27 Receiving setValue to
2013-08-06 09:21:08.391 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.27 Receiving setValue to
2013-08-06 09:21:08.391 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.27 Receiving setValue to
2013-08-06 09:21:08.392 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.27 Receiving setValue to
2013-08-06 09:21:08.392 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.27 Receiving setValue to
2013-08-06 09:21:08.392 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.27 Receiving setValue to
2013-08-06 09:21:08.393 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.27 Receiving setValue to
2013-08-06 09:21:08.393 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.27 Receiving setValue to
2013-08-06 09:21:08.394 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.27 Receiving setValue to
2013-08-06 09:21:08.394 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.27 Receiving setValue to
2013-08-06 09:21:08.395 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.27 Receiving setValue to
2013-08-06 09:21:08.395 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.396 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.396 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.397 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.397 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.398 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.399 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.399 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.400 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.400 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.400 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.400 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.401 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.401 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.401 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.402 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.402 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.403 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.403 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.404 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.404 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.404 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.404 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.405 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.28 Receiving setValue to
2013-08-06 09:21:08.406 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to
2013-08-06 09:21:08.407 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to
2013-08-06 09:21:08.407 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to
2013-08-06 09:21:08.408 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to
2013-08-06 09:21:08.408 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to
2013-08-06 09:21:08.409 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to
2013-08-06 09:21:08.409 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to
2013-08-06 09:21:08.410 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to
2013-08-06 09:21:08.410 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to
2013-08-06 09:21:08.411 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.412 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.412 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.413 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.413 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.414 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.414 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.415 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.29 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.415 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.416 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.416 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.417 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.417 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.418 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.418 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.419 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.419 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.420 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.421 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 0:00
2013-08-06 09:21:08.421 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 0:00
2013-08-06 09:21:08.422 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 0:00
2013-08-06 09:21:08.422 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 0:00
2013-08-06 09:21:08.423 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 0:00
2013-08-06 09:21:08.424 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 0:00
2013-08-06 09:21:08.424 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 0:00
2013-08-06 09:21:08.425 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.30 Receiving setValue to 0:00
2013-08-06 09:21:08.425 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.31 Receiving setValue to 0:00
2013-08-06 09:21:08.426 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.31 Receiving setValue to
2013-08-06 09:21:08.426 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.31 Receiving setValue to
2013-08-06 09:21:08.427 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.31 Receiving setValue to
2013-08-06 09:21:08.427 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.31 Receiving setValue to
2013-08-06 09:21:08.427 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.31 Receiving setValue to
2013-08-06 09:21:08.427 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.31 Receiving setValue to
2013-08-06 09:21:08.428 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.31 Receiving setValue to
2013-08-06 09:21:08.428 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.31 Receiving setValue to
2013-08-06 09:21:08.428 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.31 Receiving setValue to
2013-08-06 09:21:08.428 FCXiOSv2[16478:21e03] mvx: Diagnostic: 841.31 Showing ViewModel TimesheetEntryViewModel
2013-08-06 09:21:08.429 FCXiOSv2[16478:21e03] TouchNavigation: Diagnostic: 841.31 Navigate requested
2013-08-06 09:21:08.433 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.31 Receiving setValue to System.Collections.ObjectModel.ObservableCollection`1[FCX.Core.ViewModels.ViewModelBase]
2013-08-06 09:21:08.440 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.32 Receiving setValue to 7/24/2013
2013-08-06 09:21:08.441 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.32 Receiving setValue to Date Worked
2013-08-06 09:21:08.446 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.33 Receiving setValue to 0:00
2013-08-06 09:21:08.447 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.33 Receiving setValue to Time Worked
2013-08-06 09:21:08.452 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.33 Receiving setValue to
2013-08-06 09:21:08.453 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.33 Receiving setValue to Company
2013-08-06 09:21:08.459 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.34 Receiving setValue to
2013-08-06 09:21:08.460 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.34 Receiving setValue to Description
2013-08-06 09:21:08.462 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.34 Receiving setValue to False
2013-08-06 09:21:08.464 FCXiOSv2[16478:21e03] MvxBind: Diagnostic: 841.34 Receiving setValue to False
Sorry to overwhelm you. Thanks!
Why are bindings persisting after the view disappears?
Views can be shown multiple times - they can appear, disappear, appear again, etc - so bindings are normally set up for the lifetime of that view - not just for each appearance.
Each View will clear its bindings when it gets disposed. Exactly when the Dispose happens is up to iOS and Xamarin.iOS - it depends on when UIKit decides to clear up memory. In the simulator you can often bring this forwards using the Simulate Memory Warning menu option.
If you want the View to clear the bindings at some point earlier then you can call this.ClearAllBindings() yourself - but in most cases this isn't necessary as the View and ViewModel normally exist together in a pair for the lifetime of the View.
From your description, I'm not sure I entirely follow what you are doing within your custom view presenter nor within your viewmodel location either - I'm not sure what all the Resolve<> Result trace lines mean. I suspect that you might be reusing ViewModels and/or Views and that this might be where your multiple-bind is occurring.
Related
In Flask, when redirecting to different routes after a form is submitted, an Error Response 302 (VFS connection does not exist) is thrown. The below is a small example of what I am dealing with, there are other redirects in other routes too that throw the exact same response. There is not anything odd about the code or the redirect, am I missing something? (I am using AWS Cloud9 by the way)
#app.route('/data/import-data', methods=['GET', 'POST'])
def csv_import():
if request.method == "POST":
#fetch file, some logical tests, parse to pandas df and session data - this works all fine and well
return redirect(url_for('map_fields')) #error occurs here
return render_template('data-import-data.html')
#app.route('/data/import-data/map-fields', methods=['GET', 'POST'])
def map_fields():
#get data from session data
if request.method == "POST":
#continue to work with the session data
return redirect(url_for('data_table'))
return render_template('data-import-map-fields.html')
HTML for a form for the first route that redirects to another route
<form class="" action="/data/import-data" method="POST" enctype=multipart/form-data>
<div class="position-relative form-group"><label for="exampleFile" class="">File</label>
<input name="csvfile" type="file" class="form-control-file">
<small class="form-text text-muted">Max. file size 1.5MB(Mega-Bytes). Accepted file type .csv only. </small>
</div>
<div class="position-relative row form-check">
<button hrefname="csvuploadbutton" class="mb-2 mr-2 btn btn-primary btn-lg btn-block" type="submit">Proceed
</button>
</div>
</form>
I m using :
-primefaces-extensions\3.1.0\primefaces-extensions-3.1.0.jar
-Java 7
-tomcat 7
In my xhtml file, i declared this code:
<p:commandLink id="downloadLink" ajax="true" title="#{document.name}" action="#{documentSearchController.createDocumentViewer()}" style="color: black !important; text-decoration: none;"
oncomplete="PF('dlg01').show(); return false;" update="documentViewerDialog pdfvisualizer">
<h:outputText value="#{document.name}" style="font-weight: bold;"></h:outputText>
<f:setPropertyActionListener value="#{document}" target="#{documentSearchController.view.selectedDocument}" />
<p:dialog showEffect="fold" hideEffect="fold" header="#{document.name}" id="documentViewerDialog" widgetVar="dlg01" modal="true" dynamic="true" >
<pe:documentViewer height="400" width="800" id="pdfvisualizer" value="#{documentSearchController.view.contentViewer}" download="#{document.name}"/>
</p:dialog>
</p:commandLink>
contentViewer is an StreamedContent. This is my Java Code:
DocumentSearchController.java
public void createDocumentViewer() {
LOGGER.debug("Downloading document...");
DocumentVo selectedDoc = getView().getSelectedDocument();
if (selectedDoc != null && selectedDoc.getOriginal() != null) {
InputStream is = rechercheFacade.findById(selectedDoc.getOriginal().getId());
getView().setContentViewer(new DefaultStreamedContent(is, selectedDoc.getOriginal().getMimeType(),
selectedDoc.getName()));
}
}
when calling the documentViewer, i have this exception:
JSF1064 : Impossible de localiser ou de servir une ressource, documentviewer/viewer.html, depuis la bibliothèque primefaces-extensions.
janv. 26, 2018 4:28:46 PM com.sun.faces.application.resource.ResourceHandlerImpl logMissingResource
AVERTISSEMENT:
org.apache.catalina.connector.ClientAbortException: java.io.IOException: Une connexion existante a dû être fermée par l’hôte distant
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:396)
at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:426)
at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:339)
at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:421)
In org.primefaces.extensions.component.documentviewer.DocumentViewerRenderer (line 42) , when evaluating the value of:
writer.writeAttribute("src", generateSrc(context, documentViewer), null);
i had this :
javax.faces.resource/documentviewer/viewer.html.xhtml?ln=primefaces-extensions&v=3.1.0&file=%2FmyProject-web%2Fjavax.faces.resource%2Fdynamiccontent.properties.xhtml%3Fln%3Dprimefaces%26pfdrid%3Dsh1wqWH16DaeFl8tcXfihvHXqz3pBhmdR6eEyycy7B7SwznPx8mFNkrUrcHPPCkZ%26pfdrt%3Dsc%26pfdrid_c%3Dfalse%26uid%3D46a67391-d1c0-486c-8069-17f91c31272d#locale=fr
I find many posts that they have the same problems, but no one gives the answer
I am trying to capture the value of the button in my controller method. I have two buttons save and submit which post back the same form. I need to identify which button was pressed. The buttons are physically present outside the form and use javascript to trigger a postback. The reason why the buttons are out is because of layout reason. I have named the buttons as well as assigned values. Not sure why they are null on postback. Here is the code
<div class="buttonalign" >
<button name="button" value="submit" onclick="$('#requestHeaderform').submit();" class="btn btn-primary">Submit</button>
<button name="button" value="save" onclick="$('#requestHeaderform').submit();" class="btn btn-default">Save as draft</button>
</div>
#using (Html.BeginForm("Request_Insert", "Request", FormMethod.Post,new { id = "requestHeaderform" }))
{
<div class="newRequestHeader">
#Html.Partial("~/Views/Request/_RequestHeaderView.cshtml")
</div>
}
Controller method
[HttpPost]
public ActionResult Request_Insert(NewRequestViewModel newReqeustViewModel,string button)
{
switch (button)
{
case "submit":
// Do something
break;
case "save":
// Do something
break;
default:
break;
}
}
**View**
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script type="text/javascript">
$(function() {
$("#submit").click(function(e) {
e.preventDefault();
alert($("#submit").attr("value"));
$('#ButtonHiddenValue').val($("#submit").attr("value"));
$('#requestHeaderform').submit();
});
$("#save").click(function(e) {
e.preventDefault();
$('#ButtonHiddenValue').val($("#save").attr("value"));
$('#requestHeaderform').submit();
});
});
</script>
<div class="row">
<div class="buttonalign" >
<button name="button" id="submit" value="submit" class="btn btn-primary">Submit</button>
<button name="button" id="save" value="save" class="btn btn-default">Save as draft</button>
</div>
#using (Html.BeginForm("Request_Insert", "Home", FormMethod.Post,new { id = "requestHeaderform" }))
{
<input id="ButtonHiddenValue" name="ButtonHiddenValue" type="hidden" />
}
</div>
**Controller**
public ActionResult Request_Insert(NewRequestViewModel newReqeustViewModel)
{
return null;
}
**Model**
public class NewRequestViewModel
{
public string ButtonHiddenValue { get; set; }
}
My game.jsp code -
<%#page import="java.io.Console"%>
<%#page import="com.liferay.portal.kernel.util.WebKeys"%>
<%# taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>
<portlet:defineObjects />
<script>
function updateGames() {
document.getElementById("gameForm").submit();
}
</script>
<portlet:actionURL name="sampleActionUrl" var="sampleActionUrl">
</portlet:actionURL>
<form id="gameForm" action="${sampleActionUrl}">
<div onclick="updateGames()">CLICK HERE</div>
</form>
My Portlet Code -
package com.home;
import java.io.IOException;
public class Game extends GenericPortlet {
#Override
#RenderMode(name = "VIEW")
protected void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
response.setContentType(request.getResponseContentType());
PortletContext context = getPortletContext();
PortletRequestDispatcher rd = context
.getRequestDispatcher("/WEB-INF/jsp/game.jsp");
System.out.println("Game.doView() >> rendering");
rd.include(request, response);
}
#Override
public void processAction(ActionRequest request, ActionResponse response)
throws PortletException, IOException {
System.out.println("Game.processAction() >> processAction");
}
}
When the Form is submitted on click of the div.
doView gets called for rendering the portlet, but not the processAction.
Is there anything I am missing?
Please use below code and give a try
<portlet:actionURL name="sampleActionUrl" var="sampleActionUrl">
</portlet:actionURL>
<form id="gameForm" action="<%=sampleActionUrl.toString()%>" method="post">
<input type="hidden" id="env" name="env"/>
<div onclick="updateGames()">CLICK HERE</div>
</form>
<script>
function updateGames() {
document.getElementById("env").value = 'DEV';
document.getElementById("gameForm").submit();
}
</script>
If you are not using JSTL then you can use <%=sampleActionUrl.toString()%> instead of ${sampleActionUrl}
update
remove below piece of code
#RenderMode(name = "EDIT")
First check that you have set the following in WEB-INF\portlet.xml
<portlet>
...
<portlet-class>com.home.Game</portlet-class>
...
</portlet>
My new task is to have PrimeFaces <p:messages> dissappear after 5 seconds after appearing. I haven't found any specific setting for that in PF's user guide, nor on their webpage. I thought maybe I could bind an JavaScript event to <p:messages> appearing, but don't know where to start.
My messages are in the Template:
<p:messages id="messages" globalOnly="true" autoUpdate="true" closable="true" rendered="#{not suppressMessages}" />
and render such an empty <div> in DOM:
<div id="messages" class="ui-messages ui-widget" aria-live="polite"></div>
and full:
<div id="messages" class="ui-messages ui-widget" aria-live="polite">
<div class="ui-messages-info ui-corner-all">
<a class="ui-messages-close" onclick="$(this).parent().slideUp();return false;" href="#">
<span class="ui-messages-info-icon"></span>
<ul>
<li>
<span class="ui-messages-info-summary">Sample info message</span>
</li>
</ul>
</div>
</div>
Does anyone know of a jQuery or Primefaces specific solution?
Solution
I've found the combination of jQuery and <p:ajaxStatus> to be the solution to my problem. I've added:
<p:ajaxStatus onstart="PF('statusDialog').show()" onsuccess="setTimeout(function() { $('.ui-messages').slideUp(); }, 5000); PF('statusDialog').hide();" />
to my <p:ajaxStatus> and some jQuery in case of non ajax messages.
jQuery(document).ready(function() {
if(!$.trim($(".ui-messages").html())==''){
//console.log("messages found");
setTimeout(function() {$('.ui-messages').slideUp();}, 5000);
} else {
//console.log("messages not found");
}
});
Thanks for the lead BalusC!
You can use <p:ajaxStatus> to hook on ajax start, complete, success and error events. You can then just fire a setTimeout() on a slideUp() of the messages.
<p:ajaxStatus oncomplete="setTimeout(function() { $('.ui-messages').slideUp(); }, 5000)" />
Or, more generically, you could also use jQuery's $.ajaxStop() for this.
$(document).ajaxStop(function() {
setTimeout(function() {
$('.ui-messages').slideUp();
}, 5000);
});