-
Notifications
You must be signed in to change notification settings - Fork 185
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
Need way to subscribe to built instance changes #589
Comments
Thanks. You could add code to the constructor of
...but that is then a global variable. Maybe if the model is only used once in your app, that's enough? |
What about for editable lists of models? That's a pretty common case where you'd have multiple instances of the form. |
You could give the model a field which is a Even simpler, you could give it a field of type
Maybe that will do what you need? |
I think I prefer how the given example looks to adding a field to my built value that is only used in forms-it seems hacky. A change stream on the generated builder seems like it would be intuitive-maybe it could be generated based on a parameter in the annotation? |
The builder would still need to know where to get the stream controller from, though--it's the same problem. I can't think of anywhere to get it from apart from a field in the model. |
I don't understand-wouldn't the generated code have a The example would then look like this (suggested fix 2) @Component(
selector: 'some-form',
template: '''
<input [(ngModel)]="builder.a">
<input [(ngModel)]="builder.b">
'''
)
class SomeForm {
ThingBuilder builder;
StreamController<BuiltThing> _changeController = StreamController();
@Input()
void set thing(BuiltThing thing) {
builder = thing.toBuilder();
builder.onChange.listen(_handleChange);
}
void _handleChange(_) => _changeController.add(builder.build());
@Output()
Stream<BuiltThing> get thingChange => _changeController.stream;
} Not sure if this would be any good for performance, and I think you'd have to cancel the subscription with every new |
Thanks, I think I'm starting to understand what you need. For performance, well, it'll force a build on every change, which doesn't normally happen; that isn't hugely expensive, but it does mean creating an object and copying the fields into it. The two streams in your example seems like overkill; we could instead give the builder a method to call on change
--this seems reasonably straightforward, but it's a bit annoying that any API we write might clash with field names. I suppose that's okay if we also guard it with an annotation
and then this would create the mutable field How does that sound? |
In the example builder.onSet = _changeController.add; This implies onSet has the signature This solution works for the described use case. It's also better than the streams because you only are allowed one subscriber by definition. I like the name onChange better than onSet, but either one works. |
Hmm, can you think of any alternatives to triggering |
I would just make it pass zero arguments-I just mean triggering |
That makes sense. I'll see if I can add this in the next round of improvements--should be easy enough. Thanks! |
If there is nested built classes or collections, is onset function called when there is only a change in the deepest built class or collection? |
A nested builder doesn't do anything to alert the outer builder about a change, so, only the inner builder onSet will be called. |
So I can set a function for every nested builder to add the outer most |
Good point, |
I am following the issue in |
Issue
When writing angular components, typically we want to take as
@Input
an immutable built value instance, and as@Output
we want to push new immutable built value instances with any modifications. This is ideal for developer UX because the angular component does not share references to any mutable data structures.Doing this with built value is awkward because we have no way to subscribe to changes to a built value builder instance. For a form component, for every field modified in the form, we have to write a method in the angular component that updates the input and adds the new model to the output stream. If there are 10 inputs in the form, that's 10 methods that are almost the same. You can share the common pieces of these methods, but it's still repetitive and adds a lot of methods to the component.
Example
Suggested fix 1
Optionally generate an additional class that is immutable, called
ThingRebuilder
, that exposes aStream<ThingRebuilder> onChange
and a setter for each field which outputs modifiedThingRebuilder
s to the stream. This class can have its properties 2 way bound to the inputs.Suggested fix 2
Add a
Stream<void>
change listener to the generated builder. That stream is triggered after any setter is called on the builder. This makes it so we can use a builder instance internally in the component and output to the stream the result ofthingBuilder.build()
whenever the builder is modified.The text was updated successfully, but these errors were encountered: