reactive-extensions / rx.angular.js Goto Github PK
View Code? Open in Web Editor NEWAngularJS Bindings for RxJS
License: Other
AngularJS Bindings for RxJS
License: Other
The bower installation instructions in the README appear to use the wrong package name. It looks like this library is registered as angular-rx
, not rx-angular
:
$ bower install rx-angular
bower ENOTFOUND Package rx-angular not found
$ bower search rx
Search results:
rxjs git://github.com/Reactive-Extensions/RxJS
rxjs-jquery git://github.com/Reactive-Extensions/rxjs-jquery
angular-rx-data-table git://github.com/nickburns2006/rxDataTable
rxjs-html git://github.com/Reactive-Extensions/rxjs-html
rx-dom git://github.com/Reactive-Extensions/RxJS-DOM.git
angular-rx git://github.com/Reactive-Extensions/rx.angular.js.git
arx-ui git://github.com/cherrylabs/arx-ui.git
arx git://github.com/cherrylabs/arx-ui.git
rx-winjs git://github.com/Reactive-Extensions/RxJS-WinJS.git
$ bower install angular-rx
bower cached git://github.com/Reactive-Extensions/rx.angular.js.git#0.0.3
bower validate 0.0.3 against git://github.com/Reactive-Extensions/rx.angular.js.git#*
bower cached git://github.com/Reactive-Extensions/RxJS.git#2.2.13
bower validate 2.2.13 against git://github.com/Reactive-Extensions/RxJS.git#*
bower install angular-rx#0.0.3
bower install rxjs#2.2.13
angular-rx#0.0.3 bower_components/angular-rx
└── rxjs#2.2.13
rxjs#2.2.13 bower_components/rxjs
rx is a dependency:
https://github.com/Reactive-Extensions/rx.angular.js/blob/master/package.json#L20
rx.angular.js is pulling Rx off $window object, so rx is not loaded by this package:
https://github.com/Reactive-Extensions/rx.angular.js/blob/master/src/factory.js#L11
Shouldn't rx be changed to a peerDependency since the user is required to load it themselves?
http://blog.nodejs.org/2013/02/07/peer-dependencies/
I'm not sure if there's technical limitations to this, but it seems to me that safeApply seems a bit similar to what I'd expect a scheduler to do.
Thinking more in regular Rx terms, it'd be ideal, and result with cleaner code, if we could have the following:
var scopeScheduler = new ScopeScheduler($scope);
myStream
.timeout(5000)
.observeOn(scopeScheduler)
.subscribe(function() {
// code here will run on correct scope
});
Thoughts?
The digest
operator in src/observableRuntimeExtensions.js
does not pass next values through to observers after invoking the property setter like it does with errors and completes.
It also has no tests or docs.
Working on a pull request to fix....
I was looking at the ScopeScheduler test to figure out how ScopeScheduler should be used, but I'm not sure I understand the test either, so I'm still not sure I understand how to use ScopeScheduler.
I assume that if ScopeScheduler is used with .observeOn()
, the code in the subscriber's onNext function will effectively be passed to Scope.$apply()
thus ensuring the onNext logic is followed by a $digest()
so potentially-relevant watcher callbacks are run. Based on that assumption, I'd write a naive test like this:
var injector = angular.injector(['ng', 'rx']);
var scope = injector.get('$rootScope').$new();
scope.$watch('testProperty', function (val) {
start();
ok(true, 'testProperty watcher fired');
equal(val, 42, 'testProperty should match value emitted by observable');
});
Rx.Observable.return(42)
.observeOn(new Rx.ScopeScheduler(scope))
.subscribe(function(value) {
scope.testProperty = value;
});
expect(2);
I think this would prove the ScopeScheduler caused the watcher to fire and that the testProperty contains the expected value. (This test passes.)
But in the current test... the two watchers on testProperty
- $watch()
and $toObservable()
- and the throttle and the assignment in the tap and the testProperty2
and the commented-out test that fails... These all have me confused and thinking I must be missing something. What was the test trying to prove beyond my basic test above?
The current test only seems to prove that the onNext function is invoked - ok(true)
. We've no idea if a digest is actually triggered by the scheduler and no idea if the watchers see new values that might have been set inside the onNext. But again, maybe I'm completely missing some understanding of the intended usage of ScopeScheduler.
As for the commented-out line :
//ok(scope.testProperty2 === 2); -- Don't know why this doesn't work.
I think the scope.testProperty = 2
assignment inside the tap won't be noticed by Angular until after the ok(scope.testProperty2 === 2)
test is run on the ScopeScheduler. This is because an Angular $apply()
first evaluates it's expression/function arg - in this case the subscribe()
's onNext function containing the failing ok()
- and then Angular calls $rootScope.$digest()
which fires all the watchers. So the first watcher's invocation that should be assigning 2 to scope.testProperty2
doesn't fire until after the code where you test scope.testProperty2 === 2
, hence scope.testProperty2
is still 1 and that test fails.
Also I noticed the implementation of ScopeScheduler contains scheduleNow, scheduleRelative, and scheduleAbsolute functions that are passed to the base Scheduler implementation. I barely even understand what those are for, but does this test attempt to exercise them somehow? How and when would I make use of an immediate, relative or absolute ScopeScheduler?
When including the RX module in IE8, an error is thrown on bootstrap:
Object doesn't support property or method 'defineProperties'
This happens deep in the Angular stack trace so I'm not sure what line in rx-angular is causing this. But I'd guess it's https://github.com/Reactive-Extensions/rx.angular.js/blob/master/src/%24rootScopeExtensions.js#L15
Hey,
I'm trying to create a very simple example that will be a counter that will sum all values.
The idea is that each time a button is clicked, a new random value is added to the observable, then summed and set to some scope variable to sum.
This is the code:
var counter = $scope.$createObservableFunction('increaseCounter')
.flatMap(function() {
return rx.Observable.fromPromise(ApiServer.getCounterAmount(new Date()));
})
.do(ApiServer.logCounter)
.sum()
.subscribe(function(counter) {
$scope.counter = counter;
console.log("Total counter is", counter);
}, function(error) {
console.error("There was an error");
});
If I comment the sum, everything works great but on the counter
variable I get the new value each time. However, when I add the sum, the subscriber is never called. I'm thinking this is because the Observable was set to completed. Why is that?
Thanks!
Where do I put angular 2 stuff? Angular 2 has an awesome Pipeline for bindings so you're able to have async templates. I have a few examples in my angular2-reactive repo
angular-class/angular2-reactive-starter/src/app/components/app.ts#L174
<p>
<pre>appState = {{ appState | async | json }}</pre>
</p>
from angular-class/angular2-reactive-starter/src/app/components/app.ts#L196
this.appState = Rx.Observable.return(initilAppState).combineLatest(
counter.subject,
greet.subject,
(...args) => Object.assign({}, ...args)
);
so integration is pretty simple so far overwriting AsyncPipe
to include RxPipe
The indent_size
in .editorconfig is 4, but all of the code uses 2.
Any chance we could get this up on same CDN as RxJs? Great work by the way this is a extremely helpful for what I am working on.
The following subscribe()
call inside Rx.manageScope()
seems to throw an Rx.NotImplementedError
when using rx.angular 0.0.14 with Rx 4.0.6:
m.setDisposable(source
.observeOn(scheduler)
.subscribe(
observer.onNext.bind(observer),
observer.onError.bind(observer),
observer.onCompleted.bind(observer)
));
Here's a stack trace from Chrome:
Rx.NotImplementedError @ rx.all.js:200
Rx.Scheduler.schedulerProto.schedule @ rx.all.js:980
schedulerProto.scheduleRecursive @ rx.all.js:1086
Rx.internals.ScheduledObserver.ScheduledObserver.ensureActive @ rx.all.js:1884
ObserveOnObserver.next @ rx.all.js:1921
Rx.internals.AbstractObserver.AbstractObserver.onNext @ rx.all.js:1721
tryCatcher @ rx.all.js:63
AutoDetachObserverPrototype.next @ rx.all.js:11660
Rx.internals.AbstractObserver.AbstractObserver.onNext @ rx.all.js:1721
InnerObserver.next @ rx.all.js:5474
Rx.internals.AbstractObserver.AbstractObserver.onNext @ rx.all.js:1721
Rx.BehaviorSubject.addProperties._subscribe @ rx.all.js:11955
Rx.Observable.oldSubscribe @ rx.all.js:1958
Rx.Observable.observableProto.subscribe.observableProto.forEach @ rx.all.js:1990
MapObservable.subscribeCore @ rx.all.js:5459
tryCatcher @ rx.all.js:63
setDisposable @ rx.all.js:2038
Rx.ObservableBase.ObservableBase._subscribe @ rx.all.js:2053
Rx.Observable.oldSubscribe @ rx.all.js:1958
Rx.Observable.observableProto.subscribe.observableProto.forEach @ rx.all.js:1990
ObserveOnObservable.subscribeCore @ rx.all.js:2341
tryCatcher @ rx.all.js:63
setDisposable @ rx.all.js:2038
Rx.ObservableBase.ObservableBase._subscribe @ rx.all.js:2053
Rx.Observable.oldSubscribe @ rx.all.js:1958
Rx.Observable.observableProto.subscribe.observableProto.forEach @ rx.all.js:1990
Rx.manageScope @ rx.angular.js:426
Very useful will be if this project will have index.js which will contains this code:
require('./dist/rx.angular');
It's helpful for projects of node.js.
I apologies if I misunderstood something but it looks like you are publishing this package on bower under "angular-rx" name and at the same time have a different name in the bower.json file.
I think throttle
was changed in RxJs or so.
Now I tried the examples/$toObservable
example and it doesn't work as expected.
With debounce
it delays producing new values by Xms after typing.
But with throttle
it just throws off all values in Xms after start typing and produces new value only if it changes Xms after previous. So we never have last input value if it differs from previous value more then 1 character.
For example if we type 123
in less then 300ms then observable will produce just 1
.
If then we type 456
then observable will instantly produce 1234
and never produce 123456
.
So I think we should use debounce
instead of throttle
.
Using browserify in gulp. Not sure where to take this. Tried using browserify-shim but it doesn't seem to work when using browserify programmatically.
When $rootScope is initialized multiple times (e.g. during testing), Object.defineProperties will throw an error saying it can't redefine '$toObservable'. This seems to be fixed with the new version of Angular (I haven't figured out why but it might be due to the way how a service is initialized)
https://github.com/hotienvu/rxangular-jasmine
A simple solution for this would be do a check for existence of the properties before defining them.
We need something to bridge to events ($scope.$on
,$scope.$onRootScope
) something like $scope.$eventToObservable
and $scope.$rootScopeEventToObservable
.
I have installed the angular-rx
module with bower install
command, but trying to use the $createObservableFucntion
throws an exception:
TypeError: Object #<Scope> has no method '$createObservableFucntion'
Here is my bower.json
file:
{
"name": "ui",
"version": "0.0.0",
"dependencies": {
"angular": "1.2.6",
"json3": "~3.2.6",
"es5-shim": "~2.1.0",
"jquery": "~1.10.2",
"sass-bootstrap": "~3.0.2",
"angular-resource": "1.2.6",
"angular-cookies": "1.2.6",
"angular-sanitize": "1.2.6",
"angular-route": "1.2.6",
"angular-rx": "~0.0.3"
},
"devDependencies": {
"angular-mocks": "1.2.6",
"angular-scenario": "1.2.6"
}
}
It would be great if you added unit tests (eg. with Jasmine) to each of your examples.
It would show best practices, and how to be started in testing RxJS.
I have only provided rx.angular.js in my bower.json without providing the rxjs. rx.angular.js also obviously does not pin the rxjs version, so with rxjs 3.1.1 zipArray does not work anymore. A workaround was to pin rxjs to 3.0.1 additionally in my rx.angular.js to have a stable version. But actually that's not the best way relying on rxjs without any version dependency. Could you please have that in mind? Thanks guys!
There is some code in the current master I'm keen to use, but the last tagged version was from March this year. Is there a policy on releases, or is this just done on an ad hoc basis? Willing to help if there is anything that can be easily picked up.
Rx can abstract sync/async away which doesn't play to well with angular out of the box. I think we need something like a safeApply() operator. It would essentially be something like the do(fn)
operator but it could be called with or without a fn parameter and it would always invoke a safeApply.
e.g.
userInputObservable
.trottle(300)
.select(search())
.safeApply()
.switchLatest()
.subscribe(fn);
One of our examples would run into exactly that problem if it was using a newer angular version. The example currently uses an old version of Rx were $http
runs outside of the $digest
loop.
If I create an observable utilizing the $createObservableFunction method and I subscribe to that observable multiple times. The last subscriber overrides any other subscriber.
However if I create an observable with rx.Observable.interval() and subscribe to that multiple times. Both subscribers fire on the interval.
Why? More importantly how do I get the $createObservableFunction to fire both subscribers.
app.controller('MainCtrl', function($scope, rx) {
var test = $scope.$createObservableFunction('testClick');
var test2 = rx.Observable.interval(3000);
test.subscribe(function(){
console.log('I never run, why?');
});
test.subscribe(function(){
console.log('Why am I overriding the above subscribe');
});
test2.subscribe(function(){
console.log('This observable runs both subscribed functions')
});
test2.subscribe(function(){
console.log('See this gets called and so does the above');
});
});
Example plunker that illustrates the issue. http://plnkr.co/edit/kXa2ol?p=preview
Can someone please explain how to use it with controllerAs
I know that you can watch on the controller using observeOnScope, also you can create streams out of ng events like this:
rx.createObservableFunction(self, 'keypress')
But then how can I use rx
to $watch
and do events without having to inject both rx
and observeOnScope
?
I'm experimenting with angular-rx using Angular 1.3 and ControllerAs syntax. Unless I inject $scope, I cant seem to get ahold of $createObservableFunction, just get an error saying undefined is not a function. Do I have to inject $scope or is there a way to make it work with the "var vm = this" ControllerAs syntax? Do you have any examples using the ControllerAs syntax?
Are there any known issue of using this with Angular 1.3?
Looking at the source, I can see all of the examples and all of the tests are based on Angular 1.2.
I tried running tests against 1.3 and everything seems to pass but it would be good to have extra reassurance
I've got an error and test the combinations. Both of the files are in its /dist directory. (AngularJS v1.2.13)
(O) rx.angular.js 0.0.11 - rx.all.js 2.3.13
(O) rx.angular.js 0.0.11 - rx.all.min.js 2.3.13
(X) rx.angular.min.js 0.0.11 - rx.all.js 2.3.13
(X) rx.angular.min.js 0.0.11 - rx.all.min.js 2.3.13
The examples in the RxJS repo use jQuery. I would enjoy seeing the samples ported to use Angular. I don't have the bandwidth to do this right now, but if it remains open long enough, I'll be happy to undertake the effort.
In commit 8d6a3ab you guys removed ScopeScheduler. Why? We used it here at FunnelFire. Is there a replacement?
If I call .safeApply($scope)
without a function for the second argument, an exception is thrown because noop
is not defined. (In the 1.0 refactor, noop
was removed.)
Granted, this helped me find bugs in my code, because I almost never want to invoke .safeApply()
without a second arg ;)
Is it possible to use $createObservableFunction('click')
without $scope
?
Example:
this.$createObservableFunction('click');
Inside a controller that otherwise would not have $scope
injected
Hello @mattpodwysocki. What about if I'll implement couple operators like a assignProperty
and assignProperties
? They should be use so:
obs.$assignProperty(scope or controller, 'property');
obs.$assignProperties(scope or controller, ['property1', 'property2']);
I have a plunker to play with rx.angular.js: http://plnkr.co/edit/sGx4HH
If I replace ng-controller="CentralController"
with ng-controller="CentralController as c"
and add a c prefix to the scope variables, then use observeOnScope($scope, 'vm.userInput')
and assign to vm.results
instead of $scope.results
, it just stops working!
Does rx.angular.js support this syntax? What other changes do I need to do?
The bower.json
file for the 1.0.4
release has "version": "0.0.14",
instead of 1.0.4
. This causes confusion with some build tools (e.g. https://www.npmjs.com/package/gulp-cdnizer).
I'm guessing that this incorrect version also causes my project's bower.json
to list this dependency as "rx-angular": "rx.angular#1.0.4",
(note the extraneous "rx.angular#").
When switching from controller to controller.
You you have to dispose of the subscription on $scope.$destroy()?
I'd like to be able to bind directives in the document directly to Observables on the scope instead of binding those directives to simple scope values that I have to update from safeApply()
blocks. For instance, an Observable of booleans bound to directives like ngShow
, ngIf
, and ngDisabled
would be very helpful for complex forms and reduce controller boilerplate.
Is that something you feel fits into the goals of rx.angular.js? Or is that somehow an anti-pattern? I'm somewhat new to RxJS, so I'm genuinely curious. But ReactiveCocoa provides something very similar.
I'd love to better understand the advantages of using rx.angular.js
From what I can see so far, observeOnScope
seems to do pretty much the same thing as $scope.watch
.
Apologies if this isn't the correct forum for this type of question.
Hello @mattpodwysocki, when I use rx.angular.js with browserify I cannot find window.Rx. For example it's looks like
var angular = require('angular');
var Rx = require('Rx');
require('rx.angular');
Also I use browserify-shim for bower components:
"browserify": {
"transform": [
"browserify-shim"
]
},
"browser": {
"angular": "./vendor/angular/angular.js",
"angular-rx": "./vendor/angular-rx/rx.angular.js"
},
"browserify-shim": {
"angular": {
"exports": "angular"
}
},
"dependencies": {
"rx": "^2.3.1"
}
Could you please help me with this problem? I guess that window isn't available in browserify.
When I use it so:
require('traceur-runtime');
window.angular = require('angular');
window.Rx = require('rx');
require('angular-rx');
// components
var MainController = require('./first');
var app = angular.module('app', ['rx']);
app.controller('MainController', ['$scope', MainController]);
But use window.angular and etc isn't correct as for me.
I have a little plunker to experiment with rx.angular.js: http://plnkr.co/edit/sGx4HH
I added Lodash to the mix because now I prefer that over loops, but basically it is one of your examples, I think.
If I change the rx.angular.js to the tagged version v1.0.0, it just display nothing, and after a while (a few seconds) I get this stack trace:
ReferenceError: scope is not defined
at ObserveOnScope.subscribeCore (rx.angular.js:178)
at ObserveOnScope.tryCatcher (rx.all.js:63)
at setDisposable (rx.all.js:2038)
at ObserveOnScope.Rx.ObservableBase.ObservableBase._subscribe (rx.all.js:2053)
at ObserveOnScope.Rx.Observable.observableProto.subscribe.observableProto.forEach (rx.all.js:1990)
at DebounceObservable.subscribeCore (rx.all.js:9691)
at DebounceObservable.tryCatcher (rx.all.js:63)
at setDisposable (rx.all.js:2038)
at DebounceObservable.Rx.ObservableBase.ObservableBase._subscribe (rx.all.js:2053)
at DebounceObservable.Rx.Observable.observableProto.subscribe.observableProto.forEach (rx.all.js:1990)
in example https://github.com/Reactive-Extensions/rx.angular.js/blob/master/examples/%24toObservable/app.js
when the search http service fail for what ever reason, $scope.$toObservable('search') seems broken, it won't observe the input change anymore.
When I use $scope
as injected into a controller, $toObservable
gives me an Rx.Observable<T>
.
However I have found that when i use the $toObservable
on the scope passed into the link function of a directive, I get a different observable, namely an object with oldValue
and newValue
properties:
{ oldValue: T, newValue T}
.
I feel that $toObservable
should work consistently in these two situations. What do you think?
Every now and then I would get a cannot access $$phase of null
exception using the scope scheduler.
Using the following seems to get around this, although I am not sure if this is the right way to do it:
(scheduler._scope.$$phase || (scheduler._scope.$root && scheduler._scope.$root.$$phase))
? fn()
: scheduler._scope.$apply(fn);
Refer to scopescheduler.js
Also, I was wondering if it might be due to a $scope that was destroyed. Is there a way to have the scheduler dispose of the subscription when the $scope gets destroyed?
I want to use RxJS Lite.
Would adding support for rx as a peer dependency solve this issue?
How can I create rx wrapper for ng-click in angularJS?
I'm sure I am missing something here, but do you need to inject $scope in order to access createObservableFunction in angular services?
I have the following simple code that fires a request off to a service with a throttle:
var observableText = this.observeOnScope($scope, 'SearchText')
.map(data => { return data.newValue;} )
.distinctUntilChanged();
observableText
.filter(searchText => { return searchText.length > 2; })
.throttle(350, rx.Scheduler)
.flatMap(search => this.fetchBySearch(search))
.subscribe(results => {
this.results = results;
});
I'm having a problem "mocking" the scheduler with a test scheduler, eliminating the absolute throttle timeout.
Is it possible to provide an example showing how do this?
Thanks
I recently had the same problem as http://stackoverflow.com/questions/26664793/createobservablefunction-subscriber-gets-overriden
where trying to subscribe()
multiple times to the same observable created via $scope.$createObservableFunction
overwrites the previous subscription (see the StackOverflow code example).
In a comment to the question, the person asking the question followed up with
"In order to multicast it you need to do $createObservableFunction().publish().refCount() to keep the > the connection to the source."
I can confirm this works with multiple subscriptions. Is there another (better) way of doing this?
Referring to https://github.com/Reactive-Extensions/rx.angular.js/tree/master/docs
'$toObservable'
not in code style like the other. Looks like you used single quotes instead of back ticks.observeOnScope
and $toObservable
have an optional objectEquality
parameter documented as being a (Function) but it is actually a boolean.$createObservableFunction
: listener parameter should be marked as optional (it is omitted in the example).$toObservableCollection
, $toObservableGroup
. I suggest to document them...rx.createObservableFunction
in https://github.com/Reactive-Extensions/rx.angular.js/blob/master/examples/%24createObservableFunctionAsController/app.js Too useful not to be documented... 😄General remark: not sure if there is a difference between observeOnScope
and $toObservable
. BTW, why the former must be injected separately?
Hey @mattpodwysocki and @cburgdorf, I'd like to introduce ngdocs flavored documentation. The ngdocs generator is a kind of enhanced jsdoc generator that comes with some angular sugar like distinguishing between services, filters and directives.
It is also used for angular itself and other angular modules out there. Here's an output example of what you can get:
http://pascalprecht.github.io/angular-translate
If you guys both okay with it, I'd work on a PR.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.