Giusepe
Giusepe

Reputation: 655

How to delay ReactiveCommand.CreateFromTask first execution

I have an App made with Xamarin.Forms and ReactiveUI. Picture a View in this App where you have a kind of dropdown (actually a button that push another view where the user can filter and select one option) and when this "dropdown" is changed, I need to reload a list based on its value.

This "dropdown" won't start with some value, I need to make a async request, grab a value and then update the view.

The problem is, when I'm creating the command to load the documents:

LoadAllDocuments = ReactiveCommand.CreateFromTask<string, IEnumerable<Document>>(_ => m_service.GetAllDocumentsByTodoListAsync(SelectedTodoList.Id), canLoadAll, m_scheduler);

I need the Id from the SelectedToDoList, but this will be null at this point.

There's any way to delay this first execution of a command? Or maybe there's a better workflow to solve this?

Here is a sniped on how I'm doing it right now. Let me know if more information is needed.

LoadAllDocuments = ReactiveCommand.CreateFromTask<string, IEnumerable<Document>>(_ => m_service.GetAllDocumentsByTodoListAsync(SelectedTodoList.Id), canLoadAll, m_scheduler);
ChangeToDoListCommand = ReactiveCommand.CreateFromTask<DocumentListViewModel, bool>(vm => this.PushPageFromCacheAsync<ToDoListViewModel>((model) => model.ParentViewModel = this));

this.WhenActivated((CompositeDisposable disposables) =>
{
    SelectedItem = null;

    var SelectedTodoListChanged =
        this
            .WhenAnyValue(x => x.SelectedTodoList)
            .Throttle(TimeSpan.FromSeconds(1), RxApp.MainThreadScheduler)
            .Publish();

    SelectedTodoListChanged
        .Where(x => x == null)
        .Subscribe(async _ => SelectedTodoList = await viewService.GetMyToDoListByVaultAsync(RuntimeContext.Current.VaultId))
        .DisposeWith(disposables);

    SelectedTodoListChanged
        .Where(x => x != null)
        .InvokeCommand(LoadAllDocuments)
        .DisposeWith(disposables);

    SelectedTodoListChanged.Connect();

    LoadAllDocuments
        .ObserveOn(m_scheduler)
        .SubscribeOn(m_scheduler)
        .Subscribe(list => AddViewsToList(list.ToList()))
        .DisposeWith(disposables);

Upvotes: 0

Views: 754

Answers (1)

Kent Boogaart
Kent Boogaart

Reputation: 178660

If I understand your question correctly, you need to ensure Id is not null before calling InvokeCommand:

SelectedTodoListChanged
    .Where(x => x?.Id != null)
    .InvokeCommand(LoadAllDocuments)
    .DisposeWith(disposables);

Perhaps a better option is to bake this knowledge into the command itself. Since InvokeCommand respects the execution window of the command (as of RxUI 7, that is), if your command's CanExecute is currently false then InvokeCommand will not actually invoke your command:

var canLoadAllDocuments = this
    .WhenAnyValue(x => x.SelectedTodoList?.Id)
    .Select(id => id != null);
LoadAllDocuments = ReactiveCommand.CreateFromTask<string, IEnumerable<Document>>(
    _ => m_service.GetAllDocumentsByTodoListAsync(SelectedTodoList.Id), canLoadAll,
    canLoadAllDocuments,
    m_scheduler);

Now you can do this:

SelectedTodoListChanged
    .InvokeCommand(LoadAllDocuments)
    .DisposeWith(disposables);

Upvotes: 3

Related Questions