Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Clarification about lazy one-time binding for object literals #7663

Closed
Narretz opened this issue Jun 2, 2014 · 7 comments
Closed

Clarification about lazy one-time binding for object literals #7663

Narretz opened this issue Jun 2, 2014 · 7 comments

Comments

@Narretz
Copy link
Contributor

Narretz commented Jun 2, 2014

Hi,
migrating from bindonce to the new one-time bindings, I cannot do something like: ng-style="::{color : colorVar}" where colorVar is not initially set.

http://plnkr.co/edit/hR1tbyO4E7wEdUG4C2vf?p=preview

In this plunker, setting colorVar is delayed by 1500 ms, and the one time binding does not apply the change. It works for name, though.
Reading the code, it looks like this is because the one time wrapper for $parse checks if the whole expression is undefined, so the ng-style expression is intially defined as {'background-color': undefined}, which is 'good enough' for one time bind. The workaround that comes to mind is putting the whole ng-style expression in a variable and set that after the timeout. (see plunker) However, that is more verbose and you lose the "expressiveness" of the template.
Is this expected use, or can this be changed in the future? It sure is confusing at least!

@caitp
Copy link
Contributor

caitp commented Jun 2, 2014

this has been talked about in cee429f --- The good news is that this use case should actually be totally workable with watchtower/expressionist (although we don't have any code verifying it yet and ensuring that it does work), but this should be doable in 2.0

It's not likely to work in 1.x unfortunately, because it would mean yes, watching sub-expressions, and that whole thing gets complicated.

So yeah, the workaround is basically make the object a parameter in scope which is initially undefined, and set the object to something later. Yes, you do lose expressiveness in the template, and this totally sucks, I agree.

@caitp
Copy link
Contributor

caitp commented Jun 2, 2014

Actually, /cc @EisenbergEffect we should probably open an issue about ensuring that we can make this work in 2.0, since it's clear that people do have uses for it --- and no, we can't really forego it entirely because as has been explained previously, O.o does not solve all of these problems.

@Narretz
Copy link
Contributor Author

Narretz commented Jun 2, 2014

Ah, I see the discussion is quite extensive in the commit. Thanks. I think a little paragraph could be added to the docs about this.
I see how it's not feasible to apply the one-time pattern to sub-expressions, but what about checking each literal key for undefined? I can see this work for most cases, but I might be missing something.

@caitp
Copy link
Contributor

caitp commented Jun 2, 2014

@Narretz it might be doable, I'll see what people think about it --- I feel like it would be looked at as a "slippery slope" kind of thing, though

@IgorMinar
Copy link
Contributor

Interesting use case! We didn't think of this one.

The code works according to the spec but I agree that the result is unexpected.

If we could break down ngClass and ngStyle's literals into individual expressions then we could watch those and update the DOM accordingly. In that case, you would be able to specify one time binding per object value.

This would also mean that the these directive's input would be implemented as micro-syntax rather than a simple expression.

Given that the current implementation of ngClass and ngStyle is not the most efficient one, we should take a look at this and estimate the complexity of the fix.

@rodyhaddad can you take a look some time this week?

@IgorMinar IgorMinar added this to the 1.3.0 milestone Jun 2, 2014
@rodyhaddad
Copy link
Contributor

Here's my proposition to solve this issue and make bind-once work with literal expressions: rodyhaddad/angular.js:c9ee32

It builds up on my PR #7700

@rodyhaddad
Copy link
Contributor

#8209 landed, this is now handled

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