Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature]: ToObservableChangeSet option to emit initial ChangeSet even if empty #903

Closed
geferon opened this issue May 14, 2024 · 7 comments
Assignees

Comments

@geferon
Copy link
Contributor

geferon commented May 14, 2024

Describe the functionality desired 🐞

Currently the ToObservableChangeSet will only emit an initial value if there are any values in the collection, if the collection is empty nothing will emit until it is somehow modified.

Usage:

var collection = new ObservableCollection();
collection.ToObservableChangeSet()
	.ToCollection()
	.Subscribe(values => Console.WriteLine(values)); // This doesn't get called at all

Solution(?):
Add a new parameter such as bool emitEmpty = false which will evaluate to the following:

// This is currently code in ObservableCollectionEx.cs https://github.com/reactivemarbles/DynamicData/blob/76fd915924fab0e6756038f50a4fff4464a4ed00/src/DynamicData/Binding/ObservableCollectionEx.cs#L122-L125
if (data.Count > 0)
{
    observer.OnNext(data.CaptureChanges());
}
// NEW CHECK
else if (emitEmpty)
{
	observer.OnNext(ChangeSet<T>.Empty);
}

Or you at least could document this behaviour in the method calls as I had to look into the source code to see why it wasn't emitting any initial values.;

Currently the way I'm handling this locally is:

var collection = new ObservableCollection();
var observable = collection.ToObservableChangeSet();

if (!collection.Any())
	observable = observable.Merge(Observable.Return(ChangeSet<T>.Empty));

observable
	.ToCollection()
	.Subscribe(values => Console.WriteLine(values)); // This now gets called at least once even if the collection is empty

The steps the functionality will provide

Provided in functionality desired

Considerations

This is a minor issue that can be solved by doing 1 if and merging locally, this feature would be out of convenience and also to make it clearer, as ToObservableChangeSet emits an initial value if there are values in the collection provided but doesn't if it's empty, I think this is counter-intuitive if not told about in the documentation at least?

@JakenVeina
Copy link
Collaborator

JakenVeina commented May 16, 2024

Yeah, this seems like a no-brainer enhancement. There's also an argument to be made that "emit initial empty" should just be the permanent behavior. @RolandPheasant @dwcullop thoughts?

I agree with your reckoning as well, after plumbing the parameter down into the operator logic, it's the one-liner change you describe, here. You've got first dibs on a PR, if you want.

In the meantime, your workaround is reasonable. If you wanted to be a little more, uhh.... functional about it, you could do...

var collection = new ObservableCollection();
Observable.Create(observer =>
    {
        if (collection.Count is 0)
            observer.OnNext(ChangeSet<T>.Empty);

        return collection.ToObservableChangeSet().SubscribeSafe(observer);
    })
    .ToCollection()
    .Subscribe(values => Console.WriteLine(values)); // This doesn't get called at all

@geferon
Copy link
Contributor Author

geferon commented May 16, 2024

Should I add a test for it? I've noticed changing that breaks multiple tests but only because they expect the message count to be 1 and it's 2 as an Empty is emitted initially.

@JakenVeina
Copy link
Collaborator

Yeah, in general, add a test to cover additional functionality. And changing the expected message count in existing tests is entirely fine, so long as it matches the desired behavior.

Hang tight, though, for now, until we get some feedback on what the "desired behavior" is, I.E. whether we want to add the parameter, or just change the behavior itself.

@RolandPheasant
Copy link
Collaborator

It's only suppresses the initial state for historic reasons, and it's good to change it.

We can release it as a major version change because it could potentially break some code in the wild.

@JakenVeina
Copy link
Collaborator

Sounds good to me.

This is basically the behavior we talked about for DDNext, all operators should guarantee a first-changeset upon subscribe, and then filter empties afterwards.

We have some other major-version-bumping stuff, so we can put this in with whenever that ends up happening.

@JakenVeina
Copy link
Collaborator

@geferon If you still want dibs on a PR, go for it, we'll be ready to do a release when it's done.

Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 24, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants