-
Notifications
You must be signed in to change notification settings - Fork 25.1k
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
Provide one time binding possibility for better performance #14033
Comments
And you can by not using binding syntax, but using usual HTML attributes. |
@youneschaoui You can hardcore data in template as per @devoto13 suggestions. Also you could use advanced technics such as https://angular.io/docs/ts/latest/api/core/index/ChangeDetectorRef-class.html and https://angular.io/docs/ts/latest/api/core/index/ChangeDetectionStrategy-enum.html |
Its actually makes sense, currently you can do it only on component level ( |
I have a text file that holds all strings constants (in two languages) used to display something on the webpage (e.g. "Select item", "Welcome, this is XXX website.", ect.). I would like these strings to be displayed and after that never to be watched for changes. In AnguarJS the double semicolon was great feature. My question is why this was replaced with "only on component level" option in Angular 2? Can someone explain? There must be some explanation that I can't figure out. I really want to understand the logic behind this implementation and eventually I (or Angular Team?!) change the way this works. |
You can create directive that detaches @Directive({
selector: '[oneTime]',
})
export class OneTimeDirective {
constructor(template: TemplateRef<any>, container: ViewContainerRef, zone: NgZone) {
zone.runOutsideAngular(() => {
const view = container.createEmbeddedView(template);
setTimeout(() => view.detach());
})
}
} Usage: Hello <ng-template oneTime>{{name}}</ng-template>! |
@dawidgarus any idea for something like this?
I want to set one time binding for placeholder. But I'd still like |
Thank you @dawidgarus I'll probably be implementing this later today. I agree this would be nice to have in Angular as well. Also, I do agree that we could just code this ourselves in our application, but I feel that it would be a great feature to carry over as it gives a lot of ease of use to users. |
I'm confused by the need for other options when the first reply by @devoto13 seems like the easiest built-in way. Is there a drawback that I'm not aware of to using this? |
@aeslinger0 It will set attribute instead of property, but it is still a binding, so CD will keep checking it on subsequent change detection run. What I suggested is that you can hard code value in the template, but it assumes that you know value beforehand, i.e. not load it from somewhere.
This will check |
I am also looking for a one time binding. For example it can be done in Aurelia like this:
|
Made a lib implementation of https://stackblitz.com/edit/angular-akczef?file=app%2Fdemoes.component.ts |
IMHO, this issue is focusing too much on change detection while completely ignoring the rendering speed. The default implementation of NgForOf uses an IterableDiffer to detect changes to the collection and process them in a way that makes it easy to make efficient incremental changes to the DOM. It does this by building up doubly-linked lists for items, additions, removals, moves, and identity changes. The implementation is pretty efficient, but it is optimized for successive mutations, and not for initial rendering. On the first run or, more importantly, if the collection never changes, there is no need to do any of the processing at all. In case of one-time-bindings, this just ends up doing useless work, increasing memory pressure, and polluting the DOM with comment nodes as insertion markers. According to my tests, the rendering could be sped up by ~25% if done directly using createEmbeddedView() or by implementing a one-time-binding / immutable version of NgForOf: |
Adding to the calls for a simple way to achieve binding to a function to be executed only once. This would be really helpful for simple translation tables. |
I'd like to add from the component's user perspective. ComponentA might require some initial data to be configured with, such data might not be always a string, but can be as simple as a true/false value. If we use the first suggestion of @devoto13 then we will only be able to pass string values, even worst if we need to pass an entire object. In some situations, it can even be "dangerous" to modify that property because the component might not be designed to support changing on its input, leading to repetitive checks and runtime errors. Now, from the component's user perspective, it will still be a normal input binding, and, by definition, they establish a one-way binding with the property they are bound to and it won't be clear for the user which These situations have been very common at my project and are the actual reasons I'm writing this. |
I'm curious what impact has @dawidgarus solution on performance... Does it improve it? Or the directive overhead cancels any benefits? Did anyone get a chance to test it? |
@tony-gutierrez ... it's possible to use a pure pipe like this for one-run binding ... and re-run only when binded value has been changing ...
|
Oh. common! |
Also could use this feature. Working on an app which roughly follows a flux pattern and have components that need to accept and emit data in different formats. My workaround is not super elegant but works fine for my purposes.
|
I also have a use case that I'm sure many others do as well that would make this viable. In my application we render relative timestamps like Currently I am using a custom pipe to perform such a transformation of the |
I would like to have the possibility to specify from the parent component property binding, inputs will never change, but in others, I want still to have these options. For example, I have some component like this
And I have 3 possible ways how do I want to use this component
I have an idea of how to reach this effect, with implementing something like this:
But seems like this is not a very pretty solution |
Any updates? |
I have a major angularJs application still in production, with a slow baby-step process of moving into modern angular. This is one of the items Im keeping an eye on. Our clients can label basically everything... based on a config loaded at application init... which will not change after initial template render. It was really easy to implement in angularJs. If its not a concern with how change detection works in in modern angular.. great.. but it seems like not having to deal with the 100's of bindings on our pages after load... would save on performance. Maybe not.. either way.. i eagerly await the recommended way to deal with this issue. Thanks! (keep up the great work) ps - we do almost of the binding thro a pipe... eg |
It can be something like vue's v-once: https://v3.vuejs.org/api/directives.html#v-once |
For many use cases we need to render elements according to first initial value without the need to observe any changes. It would be great if we would have the ability to make one time bindings.
The text was updated successfully, but these errors were encountered: