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

Decomplect the event notification #35

Closed
cowboyd opened this issue Oct 18, 2016 · 14 comments
Closed

Decomplect the event notification #35

cowboyd opened this issue Oct 18, 2016 · 14 comments

Comments

@cowboyd
Copy link
Member

cowboyd commented Oct 18, 2016

One of the consistent pieces of feedback on authoring your own microstates is that the event notification API is confusing. The setState function accepts an optional initial string is the name of the event that gets fired. This is really non intuitive, flummoxes everyone who comes across it, and needs to go.

Let's take a step backwards and implement a modest event regimen with much less magic that is simple, predictable and easy to understand. There are three, and only three kinds of events that a microstate fires automatically.

on-init

Fires whenever a microstate helper recomputes because its parameter changes.

on-state

Fires whenever a new state is available to the microstate for any reason.

Question: Does both on-state and on-init fire when the initial state is computed?

on-[transition-name]

Fired whenever a transition is invoked, receives the state resulting from that transition. So for example, on the boolean microstate on-toggle will be fired whenever the boolean transition is invoked.

@taras
Copy link
Member

taras commented Oct 21, 2016

Are you thinking something like this {{let number=(Number value on-add=(action 'onAdd'))}}?

This will be a problem for Object microstate because it will conflict with object properties. ie {{let object=(Object on-assign=(action 'onAssign))}} will treat on-assign as a property of Object instance.

Thoughts?

@cowboyd
Copy link
Member Author

cowboyd commented Oct 21, 2016

Hmmm.... Good point.

One way would be to constrain the attributes to the position arguments. This would be in keeping with the way other microstates are constructed:

{{let object=(Object (hash foo="bar") on-assign=(action 'onAssign')}}

Another option would be to blacklist anything starting with on-*

@taras
Copy link
Member

taras commented Oct 21, 2016

I would prefer the former.

Alternatively, I could allow both but event binding would only work when constructed via the first param.

@cowboyd
Copy link
Member Author

cowboyd commented Oct 21, 2016

Yeah, making the object attributes feels right from the implementers perspective, and it is in keeping with the idea that a microstate "boxes" a real object. Still, it does make the api a little more awkward.

So are you saying that with one argument, it's the value, with two arguments, the first is the value, the second is the options?

@taras
Copy link
Member

taras commented Oct 21, 2016

So are you saying that with one argument, it's the value, with two arguments, the first is the value, the second is the options?

No, I was thinking that it might work like this:

{{let object=(Object (hash hello="world") on-init=(action 'foo'))}}

or

{{let object=(Object foo="bar")}}

The user can use either of these but with the 2nd, they can't bind transitions.

But really, I think we should accept the "little more awkward" and only allow {{let object=(Object (hash ))}} syntax.

@cowboyd
Copy link
Member Author

cowboyd commented Oct 24, 2016

I agree. I think simplicity of interface in this case is called for. The general form of microstate is:

(Microstate value options)

That means when you're using it, you don't have to think about each individual constructor api.

@taras
Copy link
Member

taras commented Oct 24, 2016

I'm going to start with this:

  1. Refactor (Object helper to initialize from (hash
  2. Send on-${transition} action

I'd like to exclude on-init for now - unless you have specific use case in mind.

@taras
Copy link
Member

taras commented Oct 24, 2016

@cowboyd is the intention that we continue to use Ember.sendEvent(helper, actionName, [state]);?

@cowboyd
Copy link
Member Author

cowboyd commented Oct 24, 2016

In our file upload helper we use on-init to start the upload immediately:

{{#each files as |file|}}
  {{let upload=(file-upload file on-init=(action "startImmediately"))}}
{{/each}}

vs manually starting:

{{#each files as |file|}}
  {{let upload=(file-upload file)}} <button onclick={{action upload.start}}>Upload</button>
{{/each}}

@cowboyd
Copy link
Member Author

cowboyd commented Oct 24, 2016

@cowboyd is the intention that we continue to use Ember.sendEvent(helper, actionName, [state]);?

@taras nah, I don't think so. I think we can just call the callback manually.

this['on-init']()

@taras
Copy link
Member

taras commented Oct 24, 2016

I think we can just call the callback manually.

I'm good with this.

@taras
Copy link
Member

taras commented Oct 24, 2016

@cowboyd I'm going to refactor the tests to only test for on-init and on-*. Are you good with this?

@cowboyd
Copy link
Member Author

cowboyd commented Oct 24, 2016

To the exclusion of on-state?

@taras
Copy link
Member

taras commented Oct 24, 2016

Oh, nvm, we need on-state.

@taras taras mentioned this issue Oct 24, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants