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

Computed binding not executed if argument is undefined #2158

Closed
MaKleSoft opened this issue Jul 27, 2015 · 9 comments
Closed

Computed binding not executed if argument is undefined #2158

MaKleSoft opened this issue Jul 27, 2015 · 9 comments
Assignees
Labels

Comments

@MaKleSoft
Copy link

I've noticed two scenarios in which computed bindings where not executed.

  1. Binding to an undefined property:

    <span>{{ _computedBinding(blah) }}</span>

    For this is does not matter if blah is a declared property or not.

  2. Binding to an undefined subproperty if the compute function has more than one argument:

    <span>{{ _computedBinding(myString, myObj.blah) }}</span>

    Strangely enough, binding to an undefined property works if it is the only argument:

    <span>{{ _computedBinding(myObj.blah) }}</span>
@robrez
Copy link

robrez commented Jul 28, 2015

Hi, @MaKleSoft --

I noticed this previously, as well. As it turns out, what you're seeing is by design. See kevin's helpful response here:

#1874 (comment)

@MaKleSoft
Copy link
Author

Thanks, @robrez, that clears things up somewhat. Doesn't explain the inconsistent behavior though.

@kevinpschaaf
Copy link
Member

These behaviors are by design.

I grant that when compared side-by-side it may be counter-intuitive, but there are actually just two rules that govern the current behavior:

  • Effects "go" when dependencies are pushed
    • Rationale: we do not "pull" dependencies; rather effects go when dependencies are set
  • Effects with multiple dependencies "go" when all values are defined
    • _Rationale: we do this to provide an ergonomic benefit to avoid needing undefined checks (since effects would run for each value being set in sequence), and as a performance benefit for the initial use (so the effect is only run once, e.g. at startup or when initially setting all values)

Thus from your examples above:

    1. The computing function runs only once blah has been set (to any value, including undefined)
  • 2a. The computing function runs once myString and myObj.blah are set (but only to non-undefined values, per the second rule)
  • 2b. Same as 1, the computing function runs once myObj.blah is set; note that setting myObj to any value will result in myObj.blah being pushed to the computing function (which may be undefined in the case of myObj = {})

That said, we have been exploring refinements to these rules based on feedback.

Possibilites include:

  • Don't run single-property observers when undefined is pushed (would make it a single rule: "Effects go once all dependencies are defined")
    • This is practically be fine as long as users don't ever manually set undefined, which we highly discourage and treat as an anti-pattern anyway
  • Currently, the binding system "sets" undefined when a path evaluates to undefined (e.g. {{myObj.noPropHere}}); since this would violate the "don't set undefined rule", we are considering having the binding system use the default value of a target property in place of undefined

@kaste
Copy link
Contributor

kaste commented Oct 30, 2015

As a result of this you cannot have a simple computed OR(a, b), which every user would exptect to simply work. Using a wildcard binding is not as declarative, and it actually fires too often. That's a bug introduced by design and I hope for a fix rather sooner than later.

@trevordixon
Copy link
Contributor

trevordixon commented Apr 22, 2016

@kaste or @kevinpschaaf, what's a workaround for OR(a, b) when properties might be undefined?

@tjsavage tjsavage added the 1.x label Sep 8, 2016
@TonyBogdanov
Copy link

Almost an year and a half since this issue was posted and this still hasn't been solved?

I found myself in a position where I need a very simple OR(a, b) computation, just like @kaste commented, but that doesn't work as expected.

As @kevinpschaaf explained:

Effects "go" when dependencies are pushed

What if both dependent properties have declared values to be used as default value? Why do they still need to be "set" to be considered resolved?

I'm pretty sure it can all go down to a simple check.

Does the property have declared value?

(yes) ==> Push effects once at the beginning.
(no) ==> Wait for it to be set (current behavior).

This way you even won't have to break your "don't set undefined rule". If it's undefined and no value has been declared simply don't do anything – responsibility goes to the coder to choose a default "not yet set" value and handle it.

As an example for my case in particular, I need to display a bar holding a (String) heading and a subHeading. The bar should be displayed when either of the properties are defined. However, for the cases where only heading or only subHeading is set, the bar is not displayed :(

I've declared both properties to a false as default value, which even differs from an empty string, so I always know when either has been set, even if it's empty. null is also an option, again – coder's responsibility.

@aletorrado
Copy link

+1

1 similar comment
@mvtorres
Copy link

mvtorres commented Aug 4, 2017

+1

@TimvdLippe
Copy link
Contributor

Observers run with undefined in Polymer 2 as described in the upgrade guide, therefore I am closing this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
10 participants