I am using Facelets with JSF 2.0. In the facelets tag library there is a tag called <ui:component>.
It inserts an instance of UIComponent to the tree and it trims the tags outside itself.
Can anyone explain me what is the use of this kind of functionality? Why would any one want to add UIComponent instance to the tree?
I searched a lot for the examples of component tag but didn't find any.
The <ui:component> inserts a physical UIComponent instance in the component tree, with all the content as its children.
The <ui:composition> does not insert any physical UIComponent instance in the component tree, instead, it inserts all the content as children of its parent. You cannot find it via findComponent().
Composite components use implicitly <ui:component> because it basically introduces a NamingContainer component which allows reusing the same composite component multiple times in a parent without the risk to end up with duplicate component ID errors caused by the composite's children.
Related
I've been experimenting with the dynamic component loader in Angular2. An issue, possibly related to this: https://github.com/angular/angular/issues/4330 , seems to be that once a component is loaded with, say, the loadIntoLocation() function, the injector cannot find the parent component's injector or the things that were injected into it. As that article suggests, you can pass an array of Resolved Providers obtained from the parent's injector (Injector.resolve) into the last parameter of loadIntoLocation().
This seems to work initially, but I have also found that any children of the dynamically loaded components also have the same problem. The injector of the children does not know to look up the injection tree for providers, so a standard injection in the constructor of the children like
constructor( myComponent: MyComponent)
does not work. The children (of the dynamically loaded components) are not dynamically loaded but just "normally" instantiated using a template, selector etc. I am wondering:
Is this (still) a known issue or am I misunderstanding anything?
If a known issue is there any workaround at the child level? I tried a constructor as above and also using #Host and also using forward ref + #host but none work. Is there another way to manually pass bindings to a component that is not dynamically loaded?
Is there any other possible workaround for this?
The problems seems to be caused by the resolved providers passed to loadToLocation(). DI is hierarchical and DI tries to resolve required types by walking the hierarchy towards the root, but the chain is broken at loadToLocation() because there providers are passed instead of a child-injector.
The dynamically added component and its children can only resolve providers passed to loadToLocation() or listed in the providers list of the dynamically added component itself (or one of its children if it is a (grand-)parent of the actually resolved component).
When DI walks upwards from within the dynamically inserted tree to resolve a dependency, the iteration stops at the component added by loadToLocation() because the injector of this component doesn't have a parent injector (which would be the injector of the host component where the dynamically added component was added).
See also https://github.com/angular/angular/issues/5990
Correction on this. I have conflated another problem in my code with what I thought was the bug described above. The children of my dynamically loaded component were derived from abstract classes. I was trying to inject the abstract class into the children as opposed to the actual implementation which, per this
Interface based programming with TypeScript, Angular 2 & SystemJS
I have learned you cannot do. The injection tree does get broken upon a dynamic load (which I do think should be corrected), but I take back the part about the children thereafter not being able to traverse their own tree. Thanks for the comments - it helped me sort it out.
I have a custom #NgComponent in my project and it works if I place it within the static HTML of the application. What I'm trying to figure out is how to add one to the DOM dynamically? If I construct an instance of my Component it does not appear to be of type Element and so it cannot be added directly to the children of an element in the DOM. Is there an alternate way to construct my component or wrap it for injection into the DOM?
e.g. I naively expected to be able to do something like:
dom.Element holderEl = dom.document.querySelector("#my-holder");
holderEl.children.add( new MyComponent() );
But I have also tried simply appending HTML containing my custom element to an element using innerHTML
holder.innerHtml="<my-component></my-component>"
and creating the element using document.createElement()
dom.Element el = dom.document.createElement("my-component");
dom.document.body.append(el);
But the component does not seem to be realized when added.
thanks,
Pat
You can add components dynamically, but you must manually invoke the Angular compiler so it notices that the innerHTML has a component embedded in it.
However, that is not the "Angular way".
Instead, write your template as
<div id="my-holder">
<my-component ng-if="should_component_be_displayed"></my-component>
</div>
Here, my-component will be created and included in the DOM only if should_component_be_displayed is true.
The my-holder div can be removed which leads to a cleaner DOM structure.
I would like to pass a reference to WebComponent instances created in markup to the WebComponent dart class. For instance:
html:
<element name="x-container>
<template iterate="x in xs">
<x-content-elem>
<x-item item="{{x}}" top-container="{{lexical-scoped-ref-to-container}}">
</x-content-elem>
</template>
...
I'm looking for a way to get a reference to x-container to the x-item.top-container property. The main thing is x-item might be nested in some complicated way so doing dynamic lookup could be difficult or not very robust.
You can use the DOM to find the parent element. Something like this should work.
From inside of x-item:
Container container = this.parent.xtag;
A custom element acts like a node on the page. The elem.xtag getter returns the Dart object that backs the node on the page.
If there are other elements in-between, you can can still use CSS queries to find elements that you are looking for.
How does exactly the following code work:
#{aaa.id}
<h:inputText id="txt1" binding="#{aaa}"/>
I mean, usually the component binding works, by specifying a property (of type UIComponent) in a bean. Here, there's no bean nor property but nevertheless the name "aaa" gets bound correctly (displaying the component id - "txt1"). How does it work/where is it specified?
Thanks
UPDATE: The JSF2.0 Spec [pdf] (Chapter 3.1.5) says:
"A component binding is a special value expression that can be used to facilitate “wiring up” a component instance to a
corresponding property of a JavaBean... The specified ValueExpression must point to a read-write JavaBeans property of type UIComponent (or
appropriate subclass)."
It's been put in the default EL scope during building of the view tree (that's when all binding attributes -- and attributes of tag handlers like JSTL <c:xxx> and JSF <f:xxx> -- are being evaluated). It's being shown by normal EL means during rendering of the view tree. Rendering of the view tree happens after building of the view tree, so it works that way. It's not that this code runs "line by line" as you seemed to expect from the source.
I can't point you out a single reference where it's been specified as there is none. You'd have to read both the EL spec and JSF spec separately and do a 1+1=2.
By the way, to avoid confusion among new developers and to avoid clashes with existing variables in the EL scopes, you can use a java.util.HashMap in the request scope which is been declared as follows in faces-config.xml:
<managed-bean>
<description>Holder of all component bindings.</description>
<managed-bean-name>components</managed-bean-name>
<managed-bean-class>java.util.HashMap</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
and is been used as follows
#{components.aaa.id}
<h:inputText id="txt1" binding="#{components.aaa}"/>
which is more self-documenting.
See also:
How does the 'binding' attribute work in JSF? When and how should it be used?
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");