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

What is the best way to block observable propertie's value? #4964

Closed
Reinmar opened this issue Jul 5, 2017 · 4 comments · Fixed by ckeditor/ckeditor5-utils#241
Closed

What is the best way to block observable propertie's value? #4964

Reinmar opened this issue Jul 5, 2017 · 4 comments · Fixed by ckeditor/ckeditor5-utils#241
Assignees
Labels
package:utils type:improvement This issue reports a possible enhancement of an existing feature.
Milestone

Comments

@Reinmar
Copy link
Member

Reinmar commented Jul 5, 2017

This is a common practice e.g. when one feature wants to control a state of another feature's command.

See https://github.com/ckeditor/ckeditor5-core/blob/4d768dff3facd329b881859a4b831d2dd6a3e3f4/tests/command.js#L118-L135

It overrides some property and then ensures that no one changes it back.

In that test I used a high priority listener and stopped the event so the change of the property value is not visible to the normal listeners.

However, this breaks bindings because they rely on normal priority listeners.

So another option is to listen with a low priority listener and to not stop the event. This will fix the bindings but it means that the change event is visible twice. It's hard to predict implications of that. Infinite loops or blinking UI are possible.

So, what's the best way to achieve:

  • minimal noise,
  • working bindings,
  • safety?
@pjasiun
Copy link

pjasiun commented May 25, 2018

More I think about it, more I feel that changing the observable value in change:observable listener is wrong. change event should be used only to listen on the property change, not to change it. I believe we need a separate event to let users change properties like command.isEnabled and I believe we will be able to bring a nice API for it.

I propose to define some of the observable properties to be overwritable to:

this.set( 'isEnabled', false, { overwritable: true } );

Such properties will not fire one, but two events. The first one will be fired before the change happens, will contain the new value in evt.return and should be used to overwrite the value of the property. I propose to call it set:observable but we could consider something more unique:

command.on( 'set:isEnabled', ( evt ) => {
    if( isReadOnly ) {
        evt.return = false;
        evt.stop();
    }
} );

In such solution both new and old values are available: new as evt.return, old as command.isEnabled (it is not changed yet).

if change event will be fired after set event if the value really changes, does not matter if set event was stopped or not. There is also no priorities collisions: you can set higher priority if you need to execute your listener before others or lower if you need to execute your listener after, you do not need to follow any specific rules.

Note that only some properties should be overwritable, It is unexpected that the value can be different than the one you set:

this.foo = 'bar';
this.foo // 'bom'

We should not overuse this mechanism.

@oskarwrobel
Copy link
Contributor

I would call it beforeChange and fires for each observable.

@jodator
Copy link
Contributor

jodator commented May 25, 2018

I would call it beforeChange and fires for each observable.

Yeah. AFAIR Something similar is in Backbone (before:change or something like this). The question is it that necessary for every observable 🤔. If only few of them requires such thing wouldn't be overhead to add this to every property?

@scofalik
Copy link
Contributor

scofalik commented May 25, 2018

On a plus side of having it for every property is that it would make the code a little easier extendable. Of course, it adds overhead, but I don't think a lot of it. I'd go with having this for every property. This is the easiest solution too.

@oskarwrobel oskarwrobel self-assigned this May 25, 2018
Reinmar referenced this issue in ckeditor/ckeditor5-utils May 29, 2018
Feature: Introduced `beforeChange:{property}` event in `ObservableMixin`. Closes #171.
Reinmar referenced this issue in ckeditor/ckeditor5-core May 30, 2018
Internal: Used `beforeChange` instead of `change` to force disabling commands in read-only mode. Closes https://github.com/ckeditor/ckeditor5-utils/issues/171.
@mlewand mlewand transferred this issue from ckeditor/ckeditor5-utils Oct 9, 2019
@mlewand mlewand added this to the iteration 18 milestone Oct 9, 2019
@mlewand mlewand added status:confirmed type:improvement This issue reports a possible enhancement of an existing feature. package:utils labels Oct 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
package:utils type:improvement This issue reports a possible enhancement of an existing feature.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants