GithubHelp home page GithubHelp logo

aeisenberg / angular-bind-notifier Goto Github PK

View Code? Open in Web Editor NEW
110.0 8.0 13.0 690 KB

On demand refreshing of AngularJS bindings. Vast performance improvements on complex apps.

Home Page: http://aeisenberg.github.io/angular-bind-notifier/

License: MIT License

JavaScript 100.00%
javascript angular angular-performance angular-bindings angular-extension

angular-bind-notifier's People

Contributors

0x4c4a avatar aeisenberg avatar eluinhost avatar gitter-badger avatar kasperlewau avatar tregusti avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

angular-bind-notifier's Issues

watching undefined variable causes many "fake" watchers to be created

In short: using the plugin on an undefined object causes the number of watchers to grow for no reason constantly.

ng-if=":auto:d.fakeVariable"

http://jsbin.com/titozudubo/edit?html,js,output
(i hope it is working, but ill write here anyway the problem)

Explanation:
i use a short code for finding the number watchers. i hope its is not buggy. Each time that the key "auto" has changed, it creates more watchers for no reason because d.fakeVariable is not defined.

here is the code for counting the number of watchers:

var getWatchers = function(root) {
root = angular.element(root || document.documentElement);
var watcherCount = 0;

  var getElemWatchers = function(element) {
    var isolateWatchers = getWatchersFromScope(element.data().$isolateScope);
    var scopeWatchers = getWatchersFromScope(element.data().$scope);
    var watchers = scopeWatchers.concat(isolateWatchers);
    angular.forEach(element.children(), function (childElement) {
      watchers = watchers.concat(getElemWatchers(angular.element(childElement)));
    });
    return watchers;
  }
  
  var getWatchersFromScope = function(scope) {
    if (scope) {
      return scope.$$watchers || [];
    } else {
      return [];
    }
  }
 
  return getElemWatchers(root);
};

console.log(getWatchers ().length);

Refresh all one time by namespace

Hi,

Not sure if I'm asking too much, however I'm trying to see if its possible to have the following (not sure if it make sense):

  • Have a ng-repeat
  • within the ng-repeat bind with a namespace e.g. :refresh:persons
  • Refresh all the bind once, descendants

Example below
http://jsbin.com/sefomorura/edit?html,css,js,output

I've created a jsbin with the example, as you can see ::isSelected doesn't refresh, however when adding a new item that one does (probably because I have the namespace on the ng-repeat). Is it possible to have something like that?

The reason is to remove all watchers within the list and then control how they gets refreshed without having to do :refresh: with every binding.

Thanks, once again.

Ternary operation

Hey, guys, I appreciate this amazing directive, congratz for work.

But I have problems using a simple ternary operator:

e.g:

{{:refresh:vm.check ? :refresh:vm.opc1 : :refresh:vm.opc2}} // Error: $parse:syntax
Syntax Error

Exist another way to use ternary? Thank you.

Leading Whitespace in watch expression still causes parse error

I found an issue with leading whitespace - #28 does not fix the issue. The expression now passes the regex check here https://github.com/kasperlewau/angular-bind-notifier/blob/master/src/bindNotifier.js#L112 but the parts variable declared here https://github.com/kasperlewau/angular-bind-notifier/blob/master/src/bindNotifier.js#L116 a " " in index 0 which means it passes the "not falsey" check a few lines below.

This problem can be solved by doing a whitespace-only regex check along with the "not falsey" check - line 121 now is
if (part && /^(\w+\S+)$/.test(part)) {

bug: after updating to 1.1.3 breaking when uglified

Hi,

Today I've updated my project to version 1.1.3 up from 1.1.1 (actually semver did) and I've noticed that when the library is being uglified its now breaking. I've also tested the 1.1.2 and its working fine as 1.1.1 used to be.

By breaking I mean:

  • no errors appears
  • simply not refreshing
  • without uglified everything works fine

Note: We are using the src/bindNotifier.js, since then we bundle/uglify all vendors together ourselves.

Update: I was just seeing the commits and this might look to be the culprit 03cc20f#diff-1d91badbc52faa5f1605b75be34bd83eR66

Update2:
Debugged a bit and added screenies

Non-uglified

2015-10-28 19_17_33-sports betting amp for football hockey basketball tennis _ betsson

uglified

2015-10-28 19_12_34-odds - betsson

Same binding used multiple times causes watchers number to increase

Watcher count increases on every $$rebind broadcast if we bind same value on multiple places.

For example:

<tr class="gradeX" ng-repeat="destination in :destinations:editQueue.destinations track by destination.id" style="background-color: #{{:destinations:(destination.is_level?'FAFAFA':'FFFFFF')}};" ng-class=":destinations:{'footable-ignore-filter': destination.is_level}" data-index="{{$index}}">
    <td>
        <input type="checkbox" ng-if=":destinations:(!destination.is_level)" ng-model="destination.selected"/> <a ng-click="editQueue.editDestination(destination)" ng-if=":destinations:(!destination.is_level)">

Here we have ng-if=":destinations:(!destination.is_level)" twice.
The actual list has 6 items that satisfy that condition. After every rebind (and I have to refresh this list every 5 seconds) the watchers count increases by 6. If I remove one of the ng-if=":destinations:(!destination.is_level)", the watchers count is initially bigger, but stays the same over time.

Add to NPM

Package currently can't be installed through NPM, although it seems all ready for it

ng-bind with objects

$scope.expr = { name: 'Mike' };

works
ng-bind=":key:expr.name" // 'Mike'

does not work
ng-bind=":key:expr" // [object Object]


Need to hook into ng-bind and make it aware of the :key:expr syntax, and evaluate the expr if it is not a primitive.


Related issue: angular#11716

This project fucking rocks!

Sorry, I just was talking to my coworker about your tests on ui-mention and found this repo. This is fucking awesome, as this entire spec is what I actually proposed as an alternative to static-bindings half a year prior to the Aug 2014 proposal (I referred to them as namespaced-bindings): angular/angular.js#6354

Anyway, I'm going to be following this project closely! ๐Ÿ‘ ๐Ÿ’ฏ

Parser erro when using nf-if with angular-bind-notifier and angular native bind once

I want to build a condition with both angular-bind-notifier and angular native bind once, but I'm getting the following parser error.

Syntax Error: Token ':' not a primary expression at column 28 of the expression [(vm.event.is_page_owned && ::vm.isClickable)] starting at [::vm.isClickable].

Here is my code:
<a ng-if=":events:vm.event.is_page_owned && ::vm.isClickable" ng-click="vm.goToSubscriptionDetail()" href="#">

Some way to refresh property of only one element in ng-repeat?

So say you have:

<div ng-repeat="e in elements">
  <span>e.name</span>
  <span>:typeRefresh:e.type</span>
</div>

When you do a $scope.$broadcast('$$rebind::typeRefresh'); it's going to refresh the e.type of all items in the elements array, right? Is there some way to trigger a refresh on the property of only one item in the ng-repeat?

Expression throws error

When I have my expression like such:

{{ :refresh:user.name }}
I receive this error:

Syntax Error: Token ':' not a primary expression at column 1 of the expression [:refresh::user.name] starting at [:refresh::user.name].

However, if I remove the leading space, it works. Is this intended behaviour?

e.g.
{{:refresh:user.name}}

feat(gulp): add gulp

In regards to #17 - it'd be a good idea to add a task runner to aggregate the different tasks that would need to run.

At the same time, kill the npmr build step and move that into gulp.

angular-translate with params

Currently the following does not work:

{{:namespace:'string_to_translate' | translate: { someValue: '...' }}}

due to the object literal notation of the translate filter and the splitting regex in angular-bind-notifier.

PhantomJS discrepency

Ref. issues: #15 #14 #5

There are some discrepencies between the following parameters;

  • PhantomJS 2.0 / 1.9.8
  • Minified / non-minified version of Angular.
  • watchDelegate.length, /rx/.test(watchDelegate.toString()), watchDelegate.prototype.

What it boils down to, is that we're getting;

a) False positives.
b) Exponential registration of $on listeners.
c) Broken bindings when B is "fixed".


Will try to spend some more time on the issue this coming weekend, but right now I'm at a wee loss on what would actually cover the entire board.

RangeError: Maximum call stack size exceeded

Angular version: 1.4.7
angular-bind-notifier version: 1.1.4 (also on 1.1.3 and master)

I'm currently optimizing a huge table with many nested ng-repeats which means the number of watchers grows exponentially with amount of data. Recently I changed all bindings to bind once, and used your cool little library to be able to refresh data in table and rebind one-time bindings when necessary (e.g. sorting).
Everything works fine unless the table is really huge (i.e. hundreds of rows), then I get this error:

RangeError: Maximum call stack size exceeded
    at wrap (http://localhost:5000/static/js/vendors/angular/angular-bind-notifier.js:20:46)
    at wrap (http://localhost:5000/static/js/vendors/angular/angular-bind-notifier.js:24:13)
    at wrap (http://localhost:5000/static/js/vendors/angular/angular-bind-notifier.js:24:13)
    at wrap (http://localhost:5000/static/js/vendors/angular/angular-bind-notifier.js:24:13)
    at wrap (http://localhost:5000/static/js/vendors/angular/angular-bind-notifier.js:24:13)
    at wrap (http://localhost:5000/static/js/vendors/angular/angular-bind-notifier.js:24:13)
    at wrap (http://localhost:5000/static/js/vendors/angular/angular-bind-notifier.js:24:13)
    at wrap (http://localhost:5000/static/js/vendors/angular/angular-bind-notifier.js:24:13)
    at wrap (http://localhost:5000/static/js/vendors/angular/angular-bind-notifier.js:24:13)
    at wrap (http://localhost:5000/static/js/vendors/angular/angular-bind-notifier.js:24:13) <span ng-bind=":refreshTable:data | niceNumber" class="ng-binding">

The table still contains several watchers per row, which I'm going to further optimize, so it's possible this issue won't appear when the watcher number will drop to 1-2 per row.

controllerAs?

not sure how this currently plays out with the controllerAs way of doing things. will probably want to support this at some point if it doesn't.

how to keep rebind notifier keys dynamically in the templates

Hello guys...
I have different containers and each has it's own controller and template. So I have ng-repeat for some items in each container.
Here I want to have bind notifier dynamically generated in the controller like below so that I can specifically update only single container ng-repeat.

Current Implementation

<div layout="column" ng-repeat="item in :refresh:$ctrl.iteration.work_items | limitTo : $ctrl.maxLimitOfItems" ng-repeat-end-custom="$ctrl.loadRemainingItems()" class="dragged-work-item-element work-item-space-top" id={{::item._id}}child data-item-type="parent" ng-show="item.isFilter" > </div>

Expected Implementation
HTML
<div layout="column" ng-repeat="item in :$ctrl.refreshKeyWord:$ctrl.folder.items | limitTo : $ctrl.maxLimitOfItems" ng-repeat-end-custom="$ctrl.loadRemainingItems()" class="dragged-work-item-element work-item-space-top" id={{::item._id}}child data-item-type="parent" ng-show="item.isFilter" > </div>

Controller logic:

during initialisation

self.refreshKeyWord = 'refreshItems'+self.folder._id;

After some event

$rootScope.$broadcast('$$rebind::refreshItems'+self.folder._id);

Currently I am using one notifier key to render all of items for all containers.

Please help me.

watch VS listener

Hi,

I was looking for something like this to decrease the number of watchers in a part of the app with a lot of scopes values in the view, and to just update the values in the html when necessary.

The thing is, after making some tests, I can see that the number of watchers decreases, but they are just replaced by listeners.

So for example:

        <div
            bind-notifier="{ keyName:scopeValue }">
            <span
                ng-bind=":keyName:scopeValue">
            </span>
        </div>

The ng-bind watcher is replaced by a listener that is triggered when the bind-notifier value changes and emits a event, I get it.

But applying this to 30 ng-bind elements for example, just create 30 listeners instead of 30 watchers, right?

Maybe Im missing something here so it would be great to know the advantage, thanks.

ng-class binding issue

Hi,

I'm trying to use this plugin since it seems pretty much what I need, in order to do further optimizations however I can't get it working.

I'm trying to use it for ng-class with the following syntax:

<a href="{{::node.slug}}" ng-class=":refresh:{'selected': node.isSelected}">{{::node.name}}</a>

Most probably its failing because of the colon in 'selected': which is causing the parsing to crash

feat(tests): add browser launchers

This past issue with exponential listeners, fn.proto.bind discrepencies across PhantomJS versions and the differing behaviour when using a minified contra non-minified sources of Angular - sucked.

Time to add some more testing;

  • Chrome
  • Canary
  • Firefox
  • Opera
  • IE(?)

Would be a good oppurtunity to introduce gulp and create some nifty tasks for this.

improve the README

  • Kill the current README.
  • Add examples.md
  • Add perf.md
  • Add a list of all supported/unsupported areas of usage.
  • etc(?)

Multi-line object expression parsing problems.

During development I like to write some longer ng-class expressions multi-line. The current regex doesn't support that.
What I mean is:
This works -
<div ng-class=":refresh:{'red' : test, 'blue': !test}">
{{:refresh:test}}
</div>

This doesn't -
<div ng-class=":refresh:{'red' : test ,
'blue': !test}">
{{:refresh:test}}
</div>

jsbin demo

Watchers being constantly created

Hi,

I've been using bind-notifier for a project I'm working on. I need to display thousands of lines so I need to be careful on how I generate the data.

https://plnkr.co/edit/4tWoNYeZlGFbCC3svKxP?p=preview

Here you can see I have vm.data that contains the full data and vm.display that only contains the data to display.
When I click on an Id, I add the corresponding data to the display object.

If you toggle several times any object, you can use the 'Count' button to see the watchers increasing every time.

Any idea why?

Thanks!

TypeError: removeWatchCollection[i] is not a function

On AngularJS v1.5.7, using angular-bind-notifier with ngRepeat causes the following error when ngRepeatAction broadcasts "$destory" message:

TypeError: removeWatchCollection[i] is not a function

This happens because the watch delegate in angular-bind-notifier does not return the removeWatch function, as it should.

To fix this: add return statement to wrapDelegate:

    function wrapDelegate (watchDelegate, scope, listener, objectEquality, parsedExpression) {
      var delegateCall = watchDelegate.bind(this, scope, listener, objectEquality, parsedExpression);
      setupListeners(scope, delegateCall);
      return delegateCall();
    }

You don't really need a PR for this, right?

manual refresh causing "$$refresh" to be registered exponentially

Hi,

Basically I seem to found an issue which is causing to adding $$refresh listeners exponentially, while using manual refresh.

I've got a jsbin with a repro: http://jsbin.com/quromeqihi/1/edit?html,css,js,output

This is how it should be tested:

  • Go to http://jsbin.com/quromeqihi/1/edit?html,css,js,output
  • Add a break point on angular.js on line 14766 ($broadcast)
  • Press Add from the UI
  • See the target.$$listenerCount
  • Keep doing the above e.g. Add and check count
    They target.$$listenerCount keep increase exponentially.

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.