-
-
Notifications
You must be signed in to change notification settings - Fork 96
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
Aurelia should support boolean values for attributes. #347
Comments
I'm thinking this will merge with our support for typed bindables. A typed bindable would look like this:
This would ensure that the property value was always a boolean type, using a value converter under the hood. These value converters could have a property set on them which indicates if they should
|
I was going to raise a similar issue but found this. When you declare a bindable attribute on your custom element, you don't know whether someone is going to directly assign a literal value to it, or bind to it, and therefore the value of the underlying property could end up as a literal string, or as whatever type is bound to it. I think I would prefer to see the @bindable( ) decorator being extended so the options object allows an implicit "value converter" being able to be defined by the user, plus a precanned set of Aurelia-supplied converters. Otherwise, it seems to me that if someone wants their own coercion function, they may have to build their own decorator, which falls into the category of sledgehammer cracking walnut. |
Yes, the options object would be extended to enable providing a value converter. However, we could also provide a nice syntax, as above, for the common primitive types. That syntax would essentially just create the options object and configure the value converter automatically. |
like this feature. |
Is this planned for final release or thereafter? |
It's planned for a point release. Don't we are stopping with 1.0. We just need to cut an official release rather than let it go on forever. After that, we turn right back around to implement some new features. This is one that is near the top of the list. |
Would love to have this, especially the add/remove part, so that you can do |
Yep, we really need this too, and looking very much forward to it - both the type support, the We would also really like to see the @bindable
public foo: boolean; |
@thomas-darling here's the add/remove behavior for boolean attributes: https://gist.run/?id=744ae2416278d35b5a7d450f3cc118f5 |
@jdanyow Thanks, didn't think of using a binding behavior for that - might come in handy! I think there's more to it that that, though. Let's take the From the spec:
I'd also say it should be So, I'd say this property, which we know is class Foo
{
@bindable
public disabled: boolean;
} Should be <foo disabled></foo>
<foo disabled=""></foo>
<foo disabled="disabled"></foo>
<foo disabled.bind="true"></foo> And <foo></foo>
<foo disabled.bind="false"></foo> And if So, while the element in my markup might be written as: <foo disabled.bind="true">I'm disabled</foo>
<foo disabled.bind="false">I'm enabled</foo> The element in the DOM should be: <foo disabled>I'm disabled</foo>
<foo>I'm enabled</foo> That way CSS like this will always work as expected: foo[disabled] { color: gray } Makes sense? |
I guess You are not proposing alternative syntax, but meant |
@jdanyow, I guess You are afraid to make braking change for stock html elements to avoid adding If so, is there a good reason, why Your RemoveAttributeBindingBehavior solution shouldn't be shipped with Aurelia by default? What are the disadvantages in addition to adding extra |
@atsu85 Wow, thanks, not sure how I managed to screw that up :-P |
@EisenbergEffect We're starting to really feel some pain from this and #96, both due to the lack of type inference/conversion, but also because we would like to style some elements based on the value of certain bindable properties, which can't be done without the |
@thomas-darling I feel your pain. I wanted this just the other day for a new library we're working on (which we'll be announcing soon). I'm not sure how soon we can get to it. I might be able to prioritize it in a couple of weeks since it is becoming a dependency. Any interest in contributing? It is a bit of a tricky part of the codebase but it's a great feature. |
@EisenbergEffect Thanks, it would be much appreciated, as it's probably one of our biggest issues at this point - there's a couple of others, but this one just keeps popping up in so many places. Regarding contributing, it's something I personally would absolutely love to do, and also something we, as a company, are actively talking about doing, once we get past our own upcoming release. That said though, we have some very tight deadlines ahead, and as I'm already working 12+ hours a day, it doubt this is something we could easily tackle at this time - I wish we could though, as this is a part of Aurelia I would really like to get to know better myself, and it would definitely be a great contribution. Would you maybe be able to give just a couple of quick pointers to where one might start digging, just in case I, or anyone else, were to find some time to look into it? |
The place to look at is in the templating library. There's a class called |
One comment I would like to make with the ValueConverter type scenarios (with or without reflectToAttribute) is whether you guys have given any consideration to error handling within the conversion pipeline (or what that even means). For a trivial example:
where the "fred" property could have numerous dubious or illegal values such as "jabberwocky" (is that true or false)? or a Date object, etc. I mention this because in our current app we went to a little bit of effort to ensure that our "input controls" (Date Time Pickers, Text Boxes, Currency Inputs and the like) performed type-checks on their bound-to values and went into a kind of "bad data" mode if they received bad data. We could not use the existing type converter paradigm because there is (was?) no way to trap/block erroneous data. |
We've encountered the issue but hadn't designed a solution yet. Definitely open to any ideas you have. We'd like to do it without making a breaking change. Let us know what you think. |
Any news on this? So far, the only way I got this working is by defining a |
Any news on this? |
Any update on this? |
If things go well with #623 You will be able to do: export class VideoPlayer {
@bindable({
coerce(val) {
if (val || val === '') {
return true;
}
return false;
}
})
playing
} Usage: <!-- app.html -->
<template>
<video-player playing></video-player>
<video-player playing=''></video-player>
<video-player playing='true'></video-player>
<video-player playing='playing'></video-player>
</template> With only There is another pending PR aurelia/templating#560, to help you sync back the property |
For: The coercion happens when a value is assigned to a property with @nashwaan Update: I failed to address your question about input number coercion. Number coercion is one of the built-ins along with So it will look like this: export class NumberField {
@bindable({ coerce: 'number' })
value
} <template>
<input type='number' value.bind='value' />
</template> For validation: Any binding behavior will play nicely with coerce as long as it let coercion happen first. And from the aurelia validation code, I see there are no issues. |
simlar to discussion about number value converter to be built in good candidate for contrib maybe can be closed |
Let's keep this open for now since @bigopon has some in-progress work on it. |
Schrodingers issue? |
Clicked the wrong button... |
@EisenbergEffect Quite nice to see so much commits and PRs happening on the aurelia/aurelia vNext. Keep it up :) |
@ghiscoding That's a great question. To be honest, that's a behavior we've struggled with on what the right solution is. @fkleuver is doing most of the vNext binding engine work. I'd love to hear what his thoughts are on it. I'd wager a bit that it's much easier to accomplish this in vNext given that the new engine is much more powerful and extensible. |
@ghiscoding About a month ago I created an issue for vNext to deal with exactly this (and other related things) by going systematically through the HTML specs and making sure we've got every scenario covered with a certain degree of configurability. @EisenbergEffect |
Thanks @fkleuver ! |
There is now an aurelia-contrib plugin for that. @EisenbergEffect issue can be closed |
@Alexander-Taran, @EisenbergEffect, 1. Support custom coercersThe @bindable({ coerce: 'custom' })
public foo: Custom;
@bindable({ coerce: CustomCoercer })
public foo: Custom;
@bindable({ coerce: customCoercer })
public foo: Custom; 2. Leverage TypeScript metadataThe 3. Support reflection back to the DOMThe @bindable({ reflect: true })
public theme: string = "success";
public message: string = "This is a success message"; <message theme.bind="theme">${message}</message> Would result in this DOM: <message theme="success">This is a success message</message> Where we can use this CSS: [theme="success"] { color: green; }
[theme="error"] { color: red; } 4. Support reflection of boolean attributesReflection back to the DOM should support the special needs of boolean attributes Here's some initial thoughts on how the interface of a coercer might look: interface ICoercer<TView, TModel>
{
// Converts a value from the model for use in the view.
toView?(value: TModel): TView;
// Converts a value from the view for use in the model.
fromView?(value: TView): TModel;
// When the `@bindable` option `reflect` is set, this method will be called.
// If it returns a value, that value will be assigned to the attribute in the DOM.
// If it returns undefined, it takes full responsible for manipulating the element.
// Note that the `reflect` option can also be a string, in which case it indicates
// how the value should be reflected - could be e.g. "boolean" or "yes-no".
reflect?(element: Element, value: TModel, reflect?: string): string | undefined;
} I think it makes sense to have the Why?Because literally everyone expects this to just work, and forgetting to convert the type has by far been our largest source of bugs - it's just way too easy to forget, and the bugs can be extremely nasty. This stuff is so tightly coupled to the binding internals, that I'm personally not comfortable taking a dependency on a third party plugin, which may or may not be updated to work with the latest version of the framework. This needs to be part of Aurelia itself. |
@thomas-darling Can you move this comment to an RFC for vNext? Here's a link to where you can do that: https://github.com/aurelia/aurelia/issues/new/choose I do agree this should be discussed. I've found this to be a pain as well and we've heard pretty consistent feedback on that over the years. |
@thomas-darling the plugin is from a core team member. I still propose to close this issue. |
I don't think this one should be closed just yet because it really isn't hard at all to add it to vCurrent. It's just a matter of making ObserverLocator smarter with awareness of what value types the various attributes can have, and letting it return correctly typed observers for that. Related to aurelia/aurelia#75 I wouldn't want to "half-ass" this though. I want do a proper and thorough check on the html spec to see which attributes are supposed to be what, implement the observers/locator in vNext accordingly, and then see which parts make sense to backport. Right now vCurrent just about treats every attribute as a string and that's simply not correct - it even goes against the spec. In general my idea with this, as eluded above, is to make Aurelia's binding more aware of what attributes are supposed to be according to the spec, and not add actual coercion configurability anywhere. Because if the defaults are correct, then you shouldn't need the configuration in 99% of cases and when you do, a value converter seems like the best way to go about it anyway. |
I've added a comprehensive RFC based on my previous comments. |
Closing this in favor of aurelia/aurelia#368 |
I should be able to tell Aurelia that an attribute's value should be treated as a boolean. This should work for both simple custom attributes as well as attributes on custom elements.
Usage:
Custom Element VM:
If the custom attribute or custom element tells Aurelia that it expects its value to be a boolean, the Aurelia will coerce the value to a boolean before setting the VM property and calling any
changed
callbacks.The text was updated successfully, but these errors were encountered: