Using collections of data in a store with React and Flux - collections

I have a React + Flux application that uses multiple tab-pages of data. Each tab-page displays the same kind of data (e.g. an invoice), but from another object. Based on other posts I read on this subject, I decided to create a collection in the 'InvoiceStore' that contains an 'Invoice' object for every tab page that displays an invoice.
On every tab (in the details of the invoice), there are multiple widget-like components. These components are nested in multiple layers.
The challenge is that every component should know for which invoice object the data must be displayed. I know that I can arrange that by passing data (actual data or the 'key' of the item in the invoices collection) from the top component of an invoice (tab) to each of its descendants, but that would imply that the components in the middle would need to pass the received properties to its children. This seems like overkill to me.
Is it possible to have some kind of variable that has a scope of one component and its descendants? Or is there another sort of 'standardized' solution for this challenge?
Suggestions are really appreciated!

You can pass through props with JSX spread attributes: {...this.props}, which are based on the ES7 spread operator proposal.
This destructures all the props you received in the parent and passes them to the child. Occasionally, you don't want to pass all the props, and then you need to comb out (or add in) the props you want to pass explicitly. For that, it may be useful to use the new destructuring syntax available in ES6.
Example:
<MyChildComponent
foo={bar}
baz={qux}
{...this.props}
/>
There is also an undocumented, hacky technique using this.context, but that API is unstable and is likely to change. The spread operator is currently the technique recommended by the React team.

There is no "scope" concept in React, since React way prefers composition design pattern. The child component has to be as self-complete as possible, which should not know anything about the parent component except for the required props. Thus the object is required for each child component.
An alternative is to provide a public method getItem(itemId) in the InvoiceStore. But still one would have to pass the invoiceId by props.

Related

How do you manage adding new attributes on existing objects when using firebase?

I have an app using React + Redux and coupled with Firebase for the backend.
Often times, I will want to add some new attributes to existing objects.
When doing so, existing objects won't get the attribute until they're modified with the new version of the app that handles those new attributes.
For example, let's say I have a /categories/ node, in there I've got objects such as this :
{
name: "Medical"
}
Now let's say I want to add an icon field with a default of "
Is it possible to update all categories at once so that field always exists with the default value?
Or do you handle this in the client code?
Right now I'm always testing the values to see if they're here or not, but it doesn't seem like a very good way to go about it. I'd like to have one place to define defaults.
It seems like having classes for each object type would be interesting but I'm not sure how to go about this in Redux.
Do you just use the reducer to turn all categories into class instances when you fetch them for example? I'm worried this would be heavy performance wise.
Any write operation to the Firebase Database requires that you know the exact path to the node that you're writing.
There is no built-in operation to bulk update nodes with a path that is only partially known.
You can either keep your client-side code robust enough to handle the missing properties, or you can indeed run a migration script to add the new property to each relevant node. But since that script will have to know the exact path of each node to write, it will likely first have to read/query the database to determine those paths. Depending on the number of items to update, it could possibly use multi-location updates after that to update multiple nodes in one call. E.g.
firebase.database().ref("categories").update({
"idOfMedicalCategory/icon": "newIconForMedical",
"idOfCommercialCategory/icon": "newIconForCommercial"
"idOfTechCategory/icon": "newIconForTech"
})

Meteor: Call template helper from other template

I have two templates and I've defined JavaScript helpers and events to go with each. When a button is clicked in template A, one of the things I want to do is call a helper function for template B which will change what's displayed on the screen. Is this possible?
If it's not possible, I'd instead like to reload template B.
How can I do either of these? Do I use Tracker.autorun? Reactive variables? Ideally I would do, inside an event function for template A,
B.helpers.call("helperFunctionFromTemplateB");
There are a lot of solutions to what I think you want to achieve, but the answer really depends on context.
If template A is a child template of B:
You can pass a reference to a ReactiveVar in the parent template down to the child template's data context and modify it using {{>childTemplate reactiveVar=reactiveVar}} where reactiveVar is a helper in the parent template that returns the reference to the reactive variable
If the thing you want to change is in the parent's data context, you can use Template.parentData(n) where nis the amount of levels you want to jump up. While modifying the parent's data may not immediately seem reactive, you can make the data prop reactive by accessing it via Template.currentData()
Use some kind of globally accessible state. The most common answer would probably be to use the Session package and use Session.get('var') and Session.set('var', val).
Use an event emitter. This approach gets +'s for decoupling and reusability, but it's also potentially heavy handed if you only need to modify this variable in one place from one source (i.e. your requirements are simple)
Meteor 1.3 - If you want to make references to your reactive data in multiple places but don't want to create a global like Session, use a ReactiveVar or Reactive Dict (closer to session), create your variable where it makes sense, export it, and import it in your templates/anywhere else to be used.
There's a lot of other solutions, these are just the first that come to mind. If you provide more specific context, I'll provide a code sample of what I think's best and explain why. :)

Passing value between two components in angular2-meteor project

I am using angular2-meteor.
When I try to pass a value between two components (when the value change in the first component, create an event in second component and use this new value), I have two ways right now:
One way is meteor way: using this.autorun and Session.get.
Another way is angular2 way: using Injectable service with EventEmitter.
Which way should be prior? Or is there any other better way? Thanks
Now I used angular2-meteor a while.
Although the angular2-meteor tutorial has no example so far about using or choosing Angular 2 service or Meteor Session.
But I feel angular 2 takes the lead in the front end, while meteor makes reactivity easier and also handle all back end things.
So I went with angular2 way using service to share between components. And service is very powerful like #todd-w-crone said.
If anyone has better answer, I will switch to accept that one.
I find it practical to create a new service called App.states.ts which is accessed globally and mimics Session (get / set).
I commonly import this service to all necessary components to get or set new value such as User.status, company.profile, lastProduct, etc.
Since this service is #injectable it can also make use of other services, in case a value hasn't been set already.
This allows me to ask for a variable in a component appState.getLastModifiedItem(), then in app.states.ts I'll write this function to pass this.modifiedItem or either:
Request another service item.service.ts to fetch data
Call another function with itemCollection.findOne({...}) and return such value.
You can configure Mongo queries as you want and either store static data in appState or keep subscription items in appState.
Do take into consideration that all subscriptions handled by an #injectable within a component are imported by such component. Be wary of conflicting subscriptions between components/services.

Dealing with view implicit acquisition problems in Plone

In Plone adding a member variable in a view class instance automatically makes it a part of view acquisition chain. The problem is described in detail here:
http://collective-docs.readthedocs.org/en/latest/views/browserviews.html#views-and-automatic-member-variable-acquisition-wrapping
What is the suggested approach for dealing with this problem
Can we have Plone main template based views without implicit acquisition
How about viewlets and portlet renderers then?
If not... how one should deal with the problem so that self.xxx variables do not get extra acquisition wrapping?
Use Acquisition.aq_inner() to strip away the extra wrapping and restore the object to it's original path. Please, do not use the single-item list approach as described in the document you link to.
To show one example from the linked document, but corrected with aq_inner():
from Acquisition import aq_inner
self.obj = self.context.reference_catalog.lookupObject(value)
return aq_inner(self.obj).absolute_url() # Acquistion chain corrected
Alternatively, you can use the aq_inner attribute:
self.obj = self.context.reference_catalog.lookupObject(value)
return self.obj.aq_inner.absolute_url() # Acquistion chain corrected
but that only works on objects that inherit from Acquisition.Explicit or Acquisition.Implicit; the aq_inner() function returns the passed argument verbatim if it is not a Acquisition-wrapped object.

Mixing Google Maps custom overlays with Backbone Views

TL;DR
Is PinView.prototype = _.extend(PinView.prototype, google.maps.OverlayView.prototype) the "proper" way to have a Backbone View inherit from another "class"?
Long read
We're redoing our site using Backbone and are working on including some mapping functionality.
I've got a Backbone view that handles placing <div>s onto specific points within the browser window; this seems like a natural thing to extend in order have Google's Map API place them on geographical coordinates.
According to the Google API, in order to generate a custom overlay you create a new object and set the prototype for that object to a new instance of google.maps.OverlayView. You then implement three functions on top of that object so that the object responds to:
onAdd
draw
onRemove
Where onAdd is responsible for generating the HTML and then applying it on top of the Map. This subsequently calls draw which positions the element correctly according to the LatLng pairs and bounds you've provided. onRemove gets called when you want to get rid of your layer.
So I've modified my View to include these three methods (which just call render and unrender and are bound to my collection). And then to make "the magic happen" I'm doing:
PinView.prototype = _.extend(PinView.prototype, google.maps.OverlayView.prototype)
Does this look right? I can post the code for the View and the Model on which it's based, but honestly, they're irrelevant to this example -- the code works and I'm able to place custom divs generated through Backbone model, view and controller components on the map without a issue, what I'm asking I guess (and maybe this question is more apropos for programmers.se, so let me know and I'll move it).
This seems to be the easiest way to make my PinView both a Backbone View and a Google Maps OverlayView, but I'm not 100% comfortable with prototypal inheritance to know if I'm doing something "wrong" or breaking something somewhere down the road.
Nice idea! I'm usually a bit sceptical about weather or not you're 'correct' when things work so if you haven't run into a showstopper and the overlays shows up and does what the're supposed to do I'd say you are.
One thing to check out closer, though:
This isn't (and can't) be "real" multiple inheritance - that concept isn't really relevant in a prototype based language: one implementation of a method will inevitable "win" and overwrite the other implementation, at least when using _.extend()
This means that if there are members or methods with the same names in Backbone.View and google.maps.OverlayView the one last in your _.extend() call will be the one that takes over. But when I inspect them using Chrome's Developer Tools I didn't see any obvious collision of this kind.
So my recommendation: continue using this, just test a lot. I'd love to see an example of this technique some time.
Ah! So I've been doing the above, but it's never felt right.
Then I found this discussion on a Backbone group which leads me to the following:
var MyView = (function(){
var view = function(){
Backbone.View.apply(this, arguments);
};
view.extend = Backbone.View.extend;
_.extend(view.prototype, Backbone.View.prototype, google.maps.OverlayView.prototype, [other prototypes...], { [VIEW DEFINITION] });
return view;
}());
This way if we need to override any of the definitions in a class we're extending from, we can since it's earlier in the _.extend chain (later definitions overwrite earlier definitions).
I'm working on 'extending' extend to keep track of the "parent" object's references that would be overridden and providing a method to call them still (like Python's super call). I haven't decided if this should be done through monkey-patching, an intercepter pattern (via underscore's _.tap() method or something else, but I think it'll add a lot of flexibility.
This would allow you to define an initialize view in your "parent" class which could be called by doing something like _.super('ParentClass', 'initialize'); at the end of the "child" class's initialize routine...

Resources