Closed jamwise closed 9 years ago
Hey @i11ume — this is a very interesting idea.
We do have a solution in place that I believe solves the background/solution piece ('A way to assign famo.us objects to a variable which will be accessed from the scope of a controller.') I'll explain it, and then please tell me if you think it doesn't address what you're proposing to solve here.
One of our original primary goals with the Famo.us/Angular integration was to fully support vanilla Famo.us as well as vanilla Angular. There should be no 'dead-ends' or aspects of either of the vanilla frameworks that you sacrifice by using this integration. So this piece about being able to, e.g. overwrite built in methods, access "un-pipe-able" events such as through the sync object on the famous scrollview, or to interact with a famo.us object strictly in javascript
was something we wanted to handle out of the gate.
There are a lot of parallels between Famo.us and DOM. Both are trees, both can be created with HTML (thanks to Famo.us/Angular, in Famo.us's case) and both can be created/manipulated entirely through JavaScript (this is the default for Famo.us, and is the sort of thing you do a lot in jQuery.) E.g. vanilla Famo.us feels a lot to me like creating a web app with pure jQuery and no HTML template (okay, let's create a 'div', let's append it to another 'div', let's set a style on it, let's append all of that to our 'body', and voila! an app!—replace 'div' with 'view,' and 'body' with 'context' to really drive that home.) This recognition is a big part of what drove the creation of F/A's templating system in the first place.
So when it comes to manipulating vanilla Famo.us components that are created in a Famo.us/Angular template (fa-view and co.) we looked toward how Angular handles manipulating things in the DOM. Essentially, you can 'look up' an element in a directive's link function (either with $()
/querySelector or by dealing with the element
passed into a link function) and then manipulate those elements in the code. $('#my-cool-dom-node').css('backgroundColor', 'red');
Fortunately, we were able to create a way to grab a reference to a Famo.us component based on the DOM node that created it. I.e. there's a way to go from $('fa-modifier#my-cool-modifier')
to having a reference to that modifier. The chain of code needed to dig it up gets a little long-winded, so we exposed $famous.find()
to make this easier. E.g. for the template:
<fa-app>
<fa-modifier id="my-modifier">
<fa-surface id="my-surface">
Hey there
</fa-surface>
</fa-modifier>
</fa-app>
This will get a reference to that modifier:
var myModifier = $famous.find('#my-modifier')[0].modifier
myModifier.transformFrom(//...
More here: http://famo.us/integrations/angular/docs/unstable/api/provider/$famousProvider/index.html
Note that just like in normal Angular, the DOM won't exist until a directive postLink, so $famous.find() won't resolve anything until then (i.e. this won't work in a controller, just like $()
won't)
Now as for your solution: as I mentioned, it's a very interesting idea. In fact, I think the same idea could be applied to core Angular with normal DOM node manipulation—it is a convenient alternative to querying for getting DOM references. On the other hand, DOM querying is a rather robust solution that works with existing standards (classes, IDs, attributes, tag names) and that does not require additional markup in the template to work. Do you think there are aspects of faObject
that aren't satisfied by $famous.find()
and do you see compelling reasons that they should both exist?
Thanks Zack for the detailed response.
I was aware of $famous.find() and ran into the obstacles you mentioned, which is why I thought of this solution. The find method actually works well if the markup is in the main html file, but I feel as though that will be a rare occurrence, at least it has been for my use cases. There are a few reasons I had felt best to avoid .find(), some may be out of ignorance, so I apologize is this all goes nowhere.
These are my thoughts, but I'm not attached. Feel free to close this if it doesn't align with the vision and I'll instead try to understand .find() and see if I can resolve the main issue using that method.
Background: It's great that we can use famo.us objects mostly the "angular way" using directives and services. But it would be equally great to be able to access the render nodes directly. Some applications of this might be if a developer wants to overwrite built in methods, access "un-pipe-able" events such as through the sync object on the famous scrollview, or to interact with a famo.us object strictly in javascript which might save some clutter in the markup in some cases.
Solution: A way to assign famo.us objects to a variable which will be accessed from the scope of a controller.
Obstacles:
Proposed solution: Create a service/directive combo. The directive to name the famous render node, and a service to provide a helper method to access the objects "asynchronously". The service functionality could just be wrapped into the $famous service as there's no benefit to it being external.
The Directive
The Service
In Use
Since the service listens for the change on the object, we'll have to pass it a callback instead of accessing methods directly on the object.
Using the directive
Using the service