Seth
Seth

Reputation: 2796

Temporarily breaking/pausing an Ember.Binding

I'm trying to figure out how to write pauseBinding() and resumeBinding(), so that I can interrupt bindings between application layers, e.g. if a validation fails on user input into an Ember.TextField.

var source = Ember.Object.create({ value: 10 });
var target = Ember.Object.extend({ 
    source: source,
    valueBinding: 'source.value'
});

console.log(source.get('value'), target.get('value')); // 10, 10
target.set('value', 20);
console.log(source.get('value'), target.get('value')); // 20, 20

// Stop synchronizing between target.value and source.value
pauseBinding(target.get('valueBinding'));

// Only update target.value
target.set('value', 40);
console.log(source.get('value'), target.get('value')); // 20, 40

// Resume synchronizing, target.value is overwritten
resumeBinding(target.get('valueBinding'));

console.log(source.get('value'), target.get('value')); // 20, 20

Or, asking this more generally: what is the most proper idiom for creating conditional bindings, bindings that flow only-one-way, only-the-other-one-way, both-ways, or no-ways depending on a condition (another property) ?

A condition might be a validation (if validation fails, don't spread the invalid value further), or a condition might be in response to UI state such as focus (if the control is focused, don't programmatically update its value, as this will confuse the UI).

For example, when an Ember.TextField with a valueBinding is focused (as in, active user input), I don't want it being updated, even if the to() side of the binding updates. But this seems like a oneWay() binding that's the opposite direction (oneWay from -> to, instead of oneWay to -> from).

Upvotes: 1

Views: 134

Answers (1)

Seth
Seth

Reputation: 2796

Here's a JSFiddle containing my best shot at creating a ConditionalBinding class:

http://jsfiddle.net/SDe8u/2/

You can use it like this:

var from = Ember.Object.create({
    value: 0
});

var to = Ember.Object.create({
    from: from,
    valueBinding: ConditionalBinding
        .from('from.value')
        .pauseIfTrue('pausingProperty'),
        // Default:
        // .onResumeSetBothTo('latest')
    pausingProperty: false
});

While pausingProperty is set to true, the binding between from and to will not be synchonized in either direction. Upon resume, the binding will be synchronized to the latest-wins (you can also use .onResumeSetBothTo('to') or .onResumeSetBothTo('from') to explicitly set synching from to or from).

If you want to only pause in one direction, you can add onlyPause('from') or onlyPause('to'):

var to = Ember.Object.create({
    from: from,
    valueBinding: ConditionalBinding
        .from('from.value')
        .pauseIfTrue('pausingProperty')
        .onlyPause('from')
        .onResumeSetBothTo('from'),
    pausingProperty: false
});

Upvotes: -1

Related Questions