Search code examples
dartflutterrxdart

create RxCommand with two combined streams


I have a form with two inputs: name & address and a save button.

So i've created a change and isValid commands for each

final _nameChangedCommand = RxCommand.createSync<String, String>((x) => x);
final _isNameValidCommand = RxCommand.createSync<String, bool>((x) => x != "");

final _addressChangedCommand = RxCommand.createSync<String, String>((x) => x);
final _isAddressValidCommand = RxCommand.createSync<String, bool>((x) => x != "");

I'm trying to create same for save button, where canSave = _isNameValidCommand && _isAddressValidCommand, but cant figure out the syntax.

I've created a ZipStream :

final _isNameAddressValidStream =
    new StreamZip([_isNameValidCommand, _isAddressValidCommand])
        .map((results) => results.first && results.last)
        .distinct();

final _canSaveCommand =
    RxCommand.createFromStream((_) => _isNameAddressValidStream);

but stream is never called.

Any hints?


Solution

  • Yes 'combineLatest' came also to my mind. what is important with combineLatest is that it won't issue any data unless it received something on all input Streams. Best to reach that if you add a .startWith with an initial value before feeding it to the conbineLatest. Something like

    final _isNameAddressValidStream =
        Observable.combineLatest2<String, String, bool>(
            _nameChangedCommand.startWith(''),
            _addressChangedCommand.startWidth(''),
            (name, address) => name != '' && address != '');
    
    final _saveCommand = RxCommand.createSyncNoResult(
        (dataObject) => _saveToWhatever, // your actual save function 
        canExecute: _isNameAddressValidStream);
            .distinct();
    

    So you only need two commands you can use _saveCommand for you Button's onTaphandler and use the _saveCommand.canExecute Observable to feed a StreamBuilder that created your button in activate or deactivated state.