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

feat(ngShow,ngHide) bind to scope event expression evaluation #7531

Closed
@ermalmino

Description

@ermalmino

Request Type: feature, performance

Component(s): ngShow,ngHide and others

Impact: small

Complexity: small

Detailed Description:

In a simple use case such as handling user authorization control over certain elements in a page, menu and partials, we might use ngShow and ngHide to bind to a function or a variable to control the visibility based on the current users permissions.
The matter of fact is that the expression in ngShow or ngHide will evaluate countless times even if it is not going to change except when the user logs out or changes role at runtime.

<div ng-show="checkPermission('readContent')">
     <!-- content here -->
</div>

One solution is to use angular-once, and it is great, but for this example the user might change roles without requiring to refresh the app.

I'm sure there are many other examples where it is unnecessary to watch an expression (especially if it is a function call) and where we know exactly when it is going to need a re-evaluation.

One such solution would be for the expression to be evaluated only on a certain $scope event that the proper service would dispatch when needed (logout, login, changeuser).

This would require to change ngShow, ngHide directive implementation by extending their functionality and keeping backward compatibility.

so changing the above example in:

<div ng-show="checkPermission('readContent')" ng-show-on="scope_event_name">
     <!-- content here -->
</div>

by adding the optional attribute ng-show-on or ng-hide-on we instruct the ng-show directive to listen to the $scope for 'scope_event_name' and evaluate only when it triggers instead of creating a watch.
This would eliminate needless watch expressions boosting the performance and provide a useful simple way of dealing targetet evaluation of expressions only when needed.

The quasi-pseudo-code for the ng-show directive would then be:

var ngShowDirective = ['$animate', function($animate) {
    return function(scope, element, attr) {
        if(!attr.ngShowOn){
            scope.$watch(attr.ngShow, function ngShowWatchAction(value){
                $animate[toBoolean(value) ? 'removeClass' : 'addClass'](element, 'ng-hide');
            });
        } else {
            scope.$on(attr.ngShowOn,function(event,obj){
                var val=scope.$eval(attr.ngShow);
                $animate[toBoolean(val) ? 'removeClass' : 'addClass'](element, 'ng-hide');
            });
        }
    };
}];

Of course the same principle could be extended to other directives as needed.
in the above example i opted for the extra attribute to keep things simple, but we could extend the syntax of the ng-show/ng-hide/etc to include an optional prefix wich would instruct the directive to not watch the expression but bind it to the event.
While we are at it, it could be unified with this feature request
#7486
and use eventname::expression or ::expression to bind to an event or just bind once.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions