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

Add one-way-out binding. #33

Closed
MicahZoltu opened this Issue May 10, 2015 · 18 comments

Comments

Projects
None yet
@MicahZoltu

MicahZoltu commented May 10, 2015

Currently there is both one-way (in) binding two-way (in-out) binding. I would like a one-way binding that is out only. An example would be an input box where I want changes in the input box to apply to the bound variable, but I don't want changes to the bound variable to apply to the text in the input box.

The purpose of this would be primarily for clarity of intention in the code. If I have an input box that is marked as value.one-way-in, then it is more obvious to the developer that my intention is to populate that input box with text from the view-model. If an input box is marked as value.one-way-out then it is more obvious to the developer that my intention is to populate the view-model from the contents of the box (user input).

This is particularly relevant for custom elements where the author of the element may want to setup the default binding for a bindable to one-way-out. This would mean that when bound with .bind the user of the custom element would be able to read data out from the bindable attribute but they would not be able to change the variable and have those changes reflected in the custom element.

@petermorlion

This comment has been minimized.

Show comment
Hide comment
@petermorlion

petermorlion Jun 4, 2015

Another example is for a file upload. This won't work:

<input type="file" files.two-way="files"></input>

You will receive an error like:

setting a property that has only a getter

petermorlion commented Jun 4, 2015

Another example is for a file upload. This won't work:

<input type="file" files.two-way="files"></input>

You will receive an error like:

setting a property that has only a getter
@Vheissu

This comment has been minimized.

Show comment
Hide comment
@Vheissu

Vheissu Aug 27, 2015

Member

Came here to ask for the same thing. A one-way-out binding would be an incredibly helpful feature to have. I wonder if it is simply a matter of reversing the logic what is already in the codebase for one-way - I might actually look into this and dependending on time commitments, I might be able to make this work. If not, I would still love to see this feature.

Member

Vheissu commented Aug 27, 2015

Came here to ask for the same thing. A one-way-out binding would be an incredibly helpful feature to have. I wonder if it is simply a matter of reversing the logic what is already in the codebase for one-way - I might actually look into this and dependending on time commitments, I might be able to make this work. If not, I would still love to see this feature.

@EisenbergEffect

This comment has been minimized.

Show comment
Hide comment
@EisenbergEffect

EisenbergEffect Aug 27, 2015

Member

It shouldn't be too hard to add actually. @jdanyow What do you think?

Member

EisenbergEffect commented Aug 27, 2015

It shouldn't be too hard to add actually. @jdanyow What do you think?

@Vheissu

This comment has been minimized.

Show comment
Hide comment
@Vheissu

Vheissu Aug 27, 2015

Member

If it helps anyone else, you can achieve a one-way-out binding by using a callback function. Say for example you have an input element and you only want to store the input from the element when the user types into a ViewModel variable. All you need to do is create a callback function on your ViewModel called inputChanged (or any name of your choosing) which will receive an event as its argument.

<input type="text" keyup.delegate="inputChanged($event)">

Then in your ViewModel:

export class ViewModel {
    inputVal = '';

    inputChanged(evt) {
        this.inputVal = evt.target.value;
    }   
}

Whenever a keyup event is fired on the text input, the function that you specified in your ViewModel is called with the $event object for the input. You can then access the value and store it however you will. This effectively achieves a one-way-out relationship. Ideally a binding would simply take this same concept, except you would be binding to a variable in your ViewModel instead of a callback function. I guess it would be a convenience thing more than anything.

Member

Vheissu commented Aug 27, 2015

If it helps anyone else, you can achieve a one-way-out binding by using a callback function. Say for example you have an input element and you only want to store the input from the element when the user types into a ViewModel variable. All you need to do is create a callback function on your ViewModel called inputChanged (or any name of your choosing) which will receive an event as its argument.

<input type="text" keyup.delegate="inputChanged($event)">

Then in your ViewModel:

export class ViewModel {
    inputVal = '';

    inputChanged(evt) {
        this.inputVal = evt.target.value;
    }   
}

Whenever a keyup event is fired on the text input, the function that you specified in your ViewModel is called with the $event object for the input. You can then access the value and store it however you will. This effectively achieves a one-way-out relationship. Ideally a binding would simply take this same concept, except you would be binding to a variable in your ViewModel instead of a callback function. I guess it would be a convenience thing more than anything.

@jdanyow

This comment has been minimized.

Show comment
Hide comment
@jdanyow

jdanyow Aug 27, 2015

Member

grepped the code- looks like it would just be a change to a couple areas: mainly the Binding class and the SyntaxInterpreter. Definitely doable.

Member

jdanyow commented Aug 27, 2015

grepped the code- looks like it would just be a change to a couple areas: mainly the Binding class and the SyntaxInterpreter. Definitely doable.

@WillsonHaw

This comment has been minimized.

Show comment
Hide comment
@WillsonHaw

WillsonHaw Sep 15, 2015

This would definitely be useful for custom elements as well. My use case: I have a custom element <foo> with a binding like <foo someattr.bind="attrval"> in the parent view. However, someattr gets set at creation time and modifies as the user interacts with the control. I want to be able to forward the value of foo's someattr out of the parent view (it's a collection of custom elements and just exposes the value for each element). However, as soon as I do @bindable attrval it is overriding the someattr that foo already set to undefined.

WillsonHaw commented Sep 15, 2015

This would definitely be useful for custom elements as well. My use case: I have a custom element <foo> with a binding like <foo someattr.bind="attrval"> in the parent view. However, someattr gets set at creation time and modifies as the user interacts with the control. I want to be able to forward the value of foo's someattr out of the parent view (it's a collection of custom elements and just exposes the value for each element). However, as soon as I do @bindable attrval it is overriding the someattr that foo already set to undefined.

@jdanyow jdanyow added the enhancement label Sep 18, 2015

@akircher

This comment has been minimized.

Show comment
Hide comment
@akircher

akircher Mar 4, 2016

My two cents. It should mimic value converter syntax from-view & to-view. If we support both directions for one-way, we should deprecate value.one-way since it becomes ambiguous. We then replace it with value.to-view and value.from-view

akircher commented Mar 4, 2016

My two cents. It should mimic value converter syntax from-view & to-view. If we support both directions for one-way, we should deprecate value.one-way since it becomes ambiguous. We then replace it with value.to-view and value.from-view

@EisenbergEffect

This comment has been minimized.

Show comment
Hide comment
@EisenbergEffect

EisenbergEffect Mar 4, 2016

Member

That's a nice recommendation. For compat, we can't remove one-way but we could alias it to to-view. @jdanyow Any thoughts on this?

Member

EisenbergEffect commented Mar 4, 2016

That's a nice recommendation. For compat, we can't remove one-way but we could alias it to to-view. @jdanyow Any thoughts on this?

@jdanyow

This comment has been minimized.

Show comment
Hide comment
@jdanyow

jdanyow Mar 4, 2016

Member

sounds good to me

Member

jdanyow commented Mar 4, 2016

sounds good to me

@yv989c

This comment has been minimized.

Show comment
Hide comment
@yv989c

yv989c Aug 5, 2016

Yes please! 👍

yv989c commented Aug 5, 2016

Yes please! 👍

@CasiOo

This comment has been minimized.

Show comment
Hide comment
@CasiOo

CasiOo Aug 5, 2016

To be honest I don't like view being part of the attribute name. I would much rather have it named like in wpf one-way-to-source and keep one-way

CasiOo commented Aug 5, 2016

To be honest I don't like view being part of the attribute name. I would much rather have it named like in wpf one-way-to-source and keep one-way

@jdanyow

This comment has been minimized.

Show comment
Hide comment
@jdanyow

jdanyow Aug 8, 2016

Member

@CasiOo I think we're going to go with to-view and from-view but the good news is you can alias them very easily:

import {SyntaxInterpreter} from 'aurelia-templating-binding';

SyntaxInterpreter.prototype['one-way-to-source'] = SyntaxInterpreter.prototype['from-view'];
Member

jdanyow commented Aug 8, 2016

@CasiOo I think we're going to go with to-view and from-view but the good news is you can alias them very easily:

import {SyntaxInterpreter} from 'aurelia-templating-binding';

SyntaxInterpreter.prototype['one-way-to-source'] = SyntaxInterpreter.prototype['from-view'];
@CasiOo

This comment has been minimized.

Show comment
Hide comment
@CasiOo

CasiOo Aug 9, 2016

I never was a fan of the toView and fromView naming in the value-converter either. My value-converters are sometimes used outside the view, and has nothing to do with the view at all.

Thanks for the alias example, but I don't think it's a good idea to go against the naming the framework has decided.

CasiOo commented Aug 9, 2016

I never was a fan of the toView and fromView naming in the value-converter either. My value-converters are sometimes used outside the view, and has nothing to do with the view at all.

Thanks for the alias example, but I don't think it's a good idea to go against the naming the framework has decided.

@mdurling

This comment has been minimized.

Show comment
Hide comment
@mdurling

mdurling Oct 25, 2016

What's the status of this? What I would find useful is something like value.one-time="x" value.from-view="y"

So, for example, an input control could get its initial value from property "x" and any updates would be applied to a different property "y"

Is there a way to accomplish this with today's binding capabilities?
.

mdurling commented Oct 25, 2016

What's the status of this? What I would find useful is something like value.one-time="x" value.from-view="y"

So, for example, an input control could get its initial value from property "x" and any updates would be applied to a different property "y"

Is there a way to accomplish this with today's binding capabilities?
.

@jdanyow

This comment has been minimized.

Show comment
Hide comment
@jdanyow

jdanyow Oct 26, 2016

Member

@mdurling this will be implemented, just hasn't been high priority.

Today you can do something like this for your use-case:

<input value.one-time="x" input.delegate="y = $event.target.value">

<!-- or -->

<input value.one-time="x" change.delegate="y = $event.target.value">

<!-- or -->

<input value.one-time="x" change.delegate="y = $event.target.value" input.delegate="y = $event.target.value">

Another option would be to use a binding behavior but I think the code above might be a little more clear for your "different property" use-case.

Member

jdanyow commented Oct 26, 2016

@mdurling this will be implemented, just hasn't been high priority.

Today you can do something like this for your use-case:

<input value.one-time="x" input.delegate="y = $event.target.value">

<!-- or -->

<input value.one-time="x" change.delegate="y = $event.target.value">

<!-- or -->

<input value.one-time="x" change.delegate="y = $event.target.value" input.delegate="y = $event.target.value">

Another option would be to use a binding behavior but I think the code above might be a little more clear for your "different property" use-case.

@SimonFarrugia

This comment has been minimized.

Show comment
Hide comment
@SimonFarrugia

SimonFarrugia Nov 28, 2016

I really like aurelia binding language (dot notation) but I always thought the binding modes where somewhat lacking and too verbose. Borrowing from es5 getter/setter syntax, I propose .get and .set bindings. example:

<!-- sets input value, one-way -->
<input value.set="firstname">

<!-- gets input value, one-way out -->
<input value.get="firstname">

<!-- sets input value once, one-time -->
<input value.set-once="firstname">

<!-- gets input value once, one-time out -->
<input value.get-once="firstname">

SimonFarrugia commented Nov 28, 2016

I really like aurelia binding language (dot notation) but I always thought the binding modes where somewhat lacking and too verbose. Borrowing from es5 getter/setter syntax, I propose .get and .set bindings. example:

<!-- sets input value, one-way -->
<input value.set="firstname">

<!-- gets input value, one-way out -->
<input value.get="firstname">

<!-- sets input value once, one-time -->
<input value.set-once="firstname">

<!-- gets input value once, one-time out -->
<input value.get-once="firstname">

@cluka

This comment has been minimized.

Show comment
Hide comment
@cluka

cluka Mar 2, 2017

What is the status of this?

cluka commented Mar 2, 2017

What is the status of this?

@EisenbergEffect

This comment has been minimized.

Show comment
Hide comment
@EisenbergEffect

EisenbergEffect Mar 2, 2017

Member
Member

EisenbergEffect commented Mar 2, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment