How can an Angular component query its own shadow DOM? - dart

The following question asks "How to query the shadowDOM in an Angular component test", but I don't want to achieve this in a unit testing context, but the actual component.
Specifically, I have a component whose template contains a canvas that I would like a reference to.

You can extend ShadowRootAware and override onShadowRoot() to obtain a reference to ShadowRoot, which in turn can be used for querying. (using .querySelector)

Related

Binding imperatively

Is there a way to set up bindings imperatively. An example use case:
var el2 = new MyElement();
el2.myProp = this.$.anotherElement.anotherProp
That won't setup a binding, it just assigns the value or object. I'd like to find a way to do something like:
el2.myProp.bindTo(this.$.anotherElement.anotherProp)
Possible?
Polymer 1.0 does not support this at the moment - as explained by #kevinpschaaf in Github https://github.com/Polymer/polymer/issues/1778.
(comment by #kevinpschaaf)
No, we don't currently support this, outside of dom-bind, which is the
only template implementation that late-binds instance children. You
can document.createElement('template', 'dom-bind'), then you can
dynamically append children with binding annotations to its content,
and the bindings will only be evaluated once the dom-bind is attached
to the document. See tests here that show this usage of it:
https://github.com/Polymer/polymer/blob/master/test/unit/dom-bind.html#L95
Note that dom-bind does not currently allow binding to outer scope, so
it has limited use in custom element templates (it's main use case is
for binding between elements in the main document), and that's not
likely to change short-term.
We are achieving a lot of performance optimization by baking the
binding connections into the prototype at registration time for an
element (rather than at instance time), and we haven't built up enough
of the machinery to easily allow runtime addition/removal of bindings.

how to access ShadowDOM of other polymer elements?

I'm learning Dart by making a simple webapp. the app ui I have in mind has two parts, one is a control panel, the other is a workspace. by clicking buttons in the control panel, user should be able to control the workspace.
both the control panel and the workspace are custom polymer elements. In the Control Panel's dart class, I can access itself by using shadowRoot.querySelector, but since the control panel needs to control the workspace, I need to access the workspace also. but I don't know how to do that. I tried querySelector for example, It gave me null. I understand it is a shadow DOM in the workspace tag, but how to access other tags' shadow DOM?
I can't find anything online, every example and document seems to only use shadowRoot to access self elements.
It is difficult to access the shadow DOM of another element, and this is by design. Instead of having your two custom elements so tightly coupled, a better approach would be to use events or signals. Your control panel element should take user input and fire appropriate events using the convenient fire() method it inherits from the PolymerElement class. Your application can catch and then relay those events to your workspace element. If that seems overly circuitous, you can use Polymer's <core-signals> element to pass events without dealing with intermediaries.
As an example, inside your control panel element, you might have a bold button.
<button on-click="{{boldClicked}}">Bold</button>
When that button is clicked, the control panel's boldClicked() method is executed in response. It might look something like this:
void boldClicked(Event event, var detail, Element target) {
fire('core-signal', detail: {'name': 'bold', 'data': null});
}
Then in your workspace element's HTML file, you might have:
<core-signals on-core-signal-bold="{{boldEventReceived}}"></core-signals>
And finally, in your workspace element's Dart class would be a method like so:
void boldEventReceived(Event event, var detail, Element sender) {
// manipulate workspace shadow DOM here
}
This is just one of several ways to accomplish this. You can look over the Dart team's <core-signals> example for more.
And of course, if you're using Polymer to its full potential, you will find that you need to do very little manual DOM manipulation. Using data binding and data-driven views is a winning strategy.
You can either use a selector that pierces though all shadow boundaries querySelector('my-tag /deep/ some-element') or querySelector('* /deep/ some-element') or as selector that just pierces through one level of shadow boundary querySelector('my-tag::shadow some-element') or alternatively
place both elements within the <template> of another Polymer element then you can connect attributes of both components with the same field on the common parent element (this is the preferred method in Polymer.
The solution of #user3216897 is fine of course especially if the elements don't share a common parent.
Instead of shadowRoot.querySelector you should be able to use $['abc'] if the element has an id attribute with the value 'abc'.

How to add a html with angular-dart component using Decorator

I have my custom decorator like from the tutorial which adds HTML code to a page.
But if HTML code contains my custom component it will not be processed by AngularDart.
How can I add a processed component from a decorator?
Components can't be added dynamically. Instead, use ng-hide with a bool value to toggle it.
Then you can use your decorator to update the value upon your needs.

Declaring a new renderer for TabView component

I would like to build a new component on the basis of PrimeFaces Tab/Tabview components. It should look like an add tab in a browser and open a page for filling out a form. The problem is that I want to integrate it in a TabView based on a data model (http://www.primefaces.org/showcase/ui/tabviewModel.jsf). Right now I can either combine a tab for filling out a form with a tab with predefined data or use a TabView, which dynamically creates tabs for my data.
I have read JSF documentation about creating custom components in two ways - as composite component or as a new Java class. I tried to create a custom component but it does not seem to work the way I described beyond.
My questions are:
1) is it possible to solve this problem with a composite component? If yes, could someone give me a hint?
2) if not, is there a tutorial for writing a new component on the basis of existing PrimeFaces component (presumably new sort of TabView)?
UPD: After doing some research I realized that the easiest way is writing a new renderer for TabView.
I declared a new renderer class:
public class AddableTabViewRenderer extends TabViewRenderer
and registered it in faces-config.xml:
<render-kit>
<render-kit-id>HTML_BASIC</render-kit-id>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.TabView</renderer-type>
<renderer-class>
de.idealo.evaluation.jsf.webapp.component.AddableTabViewRenderer
</renderer-class>
</renderer>
</render-kit>
However, when a view with TabView component is rendered, the encodeEnd method of TabViewRenderer is called, not the overriden method of AddableTabViewRenderer.
Can you give me a hint about where the problem might be?
The renderer-class is wrong in my configuration. I misunderstood the instructions about registering a component. I thought that render-type is the class that will be rendered with the custom renderer. It must be org.primefaces.component.TabViewRenderer instead. Now it works fine :)

How to get the contextual Pojo when handling a JSF 2.0 Event

I am using a third party JSF 2.0 component (the Primefaces 3.0 FileUpload) that defines its own custom event. On the server side, the signature of the handler looks like this:
public void handleFileUpload(FileUploadEvent event)
Problem is, my form is built dynamically and may have dozens of separate FileUpload controls in it, and I need to know WHICH of the fileupload controls generated the event.
Actually, I don't need to know which, I just need the "var" that was in the ui:repeat that caused that particular FileUpload control to be generated. With normal controllers I could have easily just passed in the variable I need, but this 3rd party component happens to use an event handling mechanism rather than a controller, and being rather ignorant of how to work with JSF 2.0 events, I don't know how to get at the POJO, given only the event.
I see that event has a getComponent() method on it that tells me the UIComponent, but after poking around I don't see any easy way to get at the contextual variables, or even a way to generate my own EL expression to evaluate to get at the contextual variables.
So the question boils down to... given only an event, how can I get at the contextual variables in scope for the particular component that was clicked?
Figured it out... I needed to put this inside the 3rd party component
<f:attribute name="myObject" value="#{myObject}"/>
Then it is available in the attributes map of the component on the server side:
final MyOjbect myObject = (MyObject) event.getComponent().getAttributes().get("myObject");

Resources