FirebaseListObservable becomes Observable after query - javascript

I made a small app on firebase. I have been using a type provided by angularfire called a FirebaseListObservable which allows you to observe changes to your data. The problem I'm having is that Angularfire also provides a way to query the data, by attaching / passing in a query object to the request.
The following returns a FirebaseListObservable.
this.resources$ = <FirebaseListObservable<IResource[]>> this.af.list(`/resources/${this.auth.id}`) as FirebaseListObservable<IResource[]>;
//This returns a regular observable.
this.resources$ = <FirebaseListObservable<IResource[]>> this.af.list(`/resources/${this.auth.id}`,
{
query: {
orderByChild: `${property}`
}
}
) as FirebaseListObservable<IResource[]>;
But this returns a plain old observable. The issue is that I need a FirebaseListObservable because it has added CRUD functionality and I'm trying to write simple filter / sorting methods.
I can see they have an Open Issue for this but I'm hoping that there is a way around this issue sooner rather than later. The solution discussed in the ticket describes extending the FirebaseListObservable and overriding the lift method to return the custom observable. I attempted to create a CustomFirebaseListObservable that does just that, but I don't seem to have access to the correct properties (observable.source and observable.operator from within my custom observable. I'm hoping for a way to cast an observable to a firebaseListObservable. Any workaround would do really.

If you are still having this issue, maybe you can create the firebase reference with the ordering and then passing that into angularfire?
let refPath = `/resources/${this.auth.id}`,
ref = firebase.database().ref(refPath).orderByChild(property);
this.resources$ = <FirebaseListObservable<IResource[]>>this.af.list(ref);

Related

How to cast a plain json object to typeorm entity

There is a transformer class called PlainObjectToNewEntityTransformer, if I need to invoke its transform function, I have to pass in the EntityMetadata which requires connection, I think casting doesn’t really need connection. The current workaround is to do the following by just assign in constructor, but this won’t preserve the schema since the field keys are often changed.
#Entity('myentities')
export class MyEntity {
constructor(partial?: Partial<MyEntity>) {
if (partial) {
Object.assign(this, partial);
}
}
}
const entity = new MyEntity(json);
I am not sure if the casting can be done in a proper way.
I am currently attempting to work with PlainObjectToNewEntityTransformer().
I was able to use getConnection() to retrieve the EntityMetadata[]. I see that getConnection.hasMetadata(*entity name*) and getConnection.getMetadata(*entity name*) are available. If I understood your question correctly, I believe one of these will provide the EntityMetadata you are seeking.

How to create Observable from Subject without exposing the Subject to consumers in RxJs v5

I'm trying to return an observable from a function that uses Rx.Subject internally. Of course, as with any good API, the implementation details should be entirely abstracted from the consumer. However, using Subject.asObservable() it appears possible for any consumer to issue new values to all observers.
Example:
const subject = new Rx.Subject();
const observable = subject.asObservable();
observable.source === subject; // true
observable.forEach(value => console.log(value));
observable.source.next('Hello');
// Causes the forEach above to print "Hello"
So my question is, is there a built-in way to expose an Observable to consumers without giving them access to the original subject? If not this is clearly bad design on RxJs' part.
NOTE: This is for RxJS v5
The only way, that I know of, to truly encapsulate this would be to subscribe to the subject inside your function and and have another (either subject or custom obervable) returned that emits those value(s).
But any operator (even the creation-operators like Observable.combineLatest(subject)) has some way to access the source.
Another way to "solve" this would be to use Typescript, because the TS-compiler would tell you, that you cannot access a protected property source on Observable, since it is not a public attribute: https://github.com/ReactiveX/rxjs/blob/master/src/Observable.ts#L30 - of course in ES5 there is no such thing as "protected" and therefor it will be still accessible through the console e.g.

How to add extender to existing observable in Knockout

I've looked at this:
http://knockoutjs.com/documentation/extenders.html
The issue is that I'm using fromJs to create my view model, so my observerables already exist. I would think I could do the following to add an extender:
var data = result.Data;
if (!window.vmRealTimeActivity) {
window.vmRealTimeActivity = ko.mapping.fromJS(data, mappingKeys);
ko.applyBindings(vmRealTimeActivity, $('#second-btm')[0]);
} else {
ko.mapping.fromJS(data, vmRealTimeActivity);
}
vmRealTimeActivity.MyExistingObservable.extend({ numeric: null });
vmRealTimeActivity.MyExistingObservable(9999); // doesn't call numeric extender
My extender gets called the first time the extender is attached, but not after trying to change the value.
I read another SO post that stated that .extend() creates a new observerable so you have to do this, but this doesn't work either:
vmRealTimeActivity.MyExistingObservable = vmRealTimeActivity.MyExistingObservable.extend({ numeric: null });
In addition to not calling my formatter a second time, the value starts coming back NaN.
How do I attach an extender the proper way to an existing observable?
Since you are using the mapping plugin, you could specify a create callback. If you add the following to the existing mappingKeys, it would probably work (I don't know your exact mapping, so you might need to change bits here and there):
'MyExistingObservable': {
create: function(options) {
return new ko.observable(options.data).extend({ numeric: null });
}
}
This result in an extended observable upon mapping from yor data.
Here's a jsFiddle with a working example (vm1) and your current non-working example (vm2) for comparison
The above answer is correct, but for anyone interested, I found the simpler approach is to just create your view models client side and use fromJs to refresh them rather than both create and refresh them. You can then apply the answer here to support adding extend to both your parent and child view models: Map JSON data to Knockout observableArray with specific view model type
With either approach you will have to create additional mappings.

Best way of getting the key after $add

I am using angularFire v 0.5.0
On my returned object I do a $add.
What would be the best way to get the generated key?
It must be something in the succes callback of the $add, because the key will come back asynchrounlusly?
scope.settings = $firebase(ref);
scope.settings.value = {
vat: {
inclusive: true
}
}
}
scope.settings.$add (scope.settings.value).then( function ( {
scope.settings.key = ???
});
note: this is not the actual code, this is just to clarify the problem.
The actiual code is inside a factory in the loaded event, and there is a check if there is already a settings object inside the database.
This somewhat strange construct is to make it easyer for consumers of the factory to change the settings. The settings is a singleton. AngularFire does not return a array of objects, but every item is a object in the settings, with its own key.
$add returns a Firebase ref. Call name() on that ref.
scope.settings.$add(…).name();
See https://github.com/firebase/angularFire/blob/master/angularfire.js#L127.
from the angularfire docs:
The $add method takes a single argument of any type. It will append this value as a member of a list (ordered in chronological order). This is the equivalent of calling push(value) on a Firebase reference.
from the firebase docs (about push()):
Returns
A Firebase reference for the generated location.
so, i think the "key" that you want is the return value of the $add.
Maybe they've changed it in newer versions, now it works like this:
$add() will return a promise. You have to use the callback which runs on success. For example:
var something = $scope.somethings.$add({name: "foo"});
something.then(function(e) {
console.log(e.name())
});
This allows you to perform different actions based on the outcome of the save/write attempt to Firebase.

Sequelize.js afterUpdate hook pass changed values

I'm building a node.js app and I'm evaluating Sequelize.js for persistent objects. One thing I need to do is publish new values when objects are modified. The most sensible place to do this would seem to be using the afterUpdate hook.
It almost works perfectly, but when I save an object the hook is passed ALL the values of the saved object. Normally this is desirable, but to keep the publish/subscribe chatter down, I would rather not republish fields that weren't saved.
So for instance, running the following
tasks[0].updateAttributes({assignee: 10}, ['assignee']);
Would automagically publish the new value for the assignee for that task on the appropriate channel, but not republish any of the other fields, which didn't change.
The closest I've come is with an afterUpdate hook:
Task.hook('afterUpdate', function(task, fn) {
Object.keys(task).forEach(function publishValue(key) {
pubSub.publish('Task:'+task.id+'#'+key, task[key]);
});
return fn();
});
which is pretty straightforward, but since the 'task' object has all the fields, I'm being unnecessarily noisy. (The pubSub system is ignorant of previous values and I'd like to keep it that way.)
I could override the setters in the task object (and all my other objects), but I would prefer not to publish until the object is saved. The object to be saved doesn't seem to have the old values (that I can find), so I can't base my publish on that.
So far the best answer I've come up with from a design standpoint is to tweak one line of dao.js to add the saved values to the returned object, and use that in the hook:
self.__factory.runHooks('after' + hook, _.extend({}, result.values, {savedVals: args[2]} ), function(err, newValues) {
Task.hook('afterUpdate', function(task, fn) {
Object.keys(task.savedVals).forEach(function publishValue(key) {
pubSub.publish('Task:'+task.id+'#'+key, task[key]);
});
return fn();
});
Obviously changing the Sequelize library is not ideal from a maintenance standpoint.
So my question is twofold: is there a better way to get the needed information to my hook without modifying dao.js, or is there a better way to attack my fundamental requirement?
Thanks in advance!
There is not currently. In the implementation for exactly what you describe we simply had to implement logic to compare old and new values, and if they differed, assume that they have changed.

Categories