when I read about the Primefaces Dialog Framework (DF), which is "used to open an external xhtml page in a dialog", I assumed this meant you could display xhtml from another domain.
If this is the case, how can I give an absolute url to the method...
requestContext.getCurrentInstance().openDialog(outcome)?
These don't seem to resolve.
If this is not the case, then what is the purpose/advantage of the DF? If I can only display xhtml from within the same app, why not just use the declarative <p:dialog> component? It can be put inside a <ui:composition> if you want to reuse a dialog from multiple pages, for instance.
OpenDialog enables the page author to open an xhtml referenced via a JSF navigation outcome in a dialog, the options are the configuration attributes for dialog like modal, draggable and finally the optional params are the view params to pass parameters to the dialog.
Actually the PrimeFaces blog entry referring to that means to use an internal application view outcome for the dialog to refer to. That bounds the path to your application JSF navigation cases.
Then what's the advantage of the dialog framework? I would say, bringing you the ability to specify the outcome and the dialog attributes at runtime. Let's say you have a car table, where you open a detail dialog when user clicks on one row. Suposing you need to display different content depending on car's branch, it would be easy to control what is going to be rendered inside the dialog:
String outcome = "dialogs/genericCar";
if (car.getBranch.equals("Ferrari")){
outcome = "dialogs/ferrariCar";
}
else if (car.getBranch.equals("Aston Martin")){
outcome = "dialogs/astonCar";
}
RequestContext.getCurrentInstance().openDialog(outcome);
Doing that would be so clean an straight forwarded. Otherwise with the classing p:dialog tag you're limited to a single dialog with conditional rendering inside depending on the content you want to display.
The chance of being able to change the dialog attributes depending on what you want to render seems interesting too.
See also:
PrimeFaces Dialog Framework
Blog entry
Related
I'm using PrimeFaces 5.
I would like to open a dialog when a button is pressed.
<p:commandButton value="add upload" actionListener="#{theForm.openUpload}" >
public void openUpload() {
this.item = new Item();
RequestContext.getCurrentInstance().openDialog("uploadForm");
}
There will be a save button in the dialog to save the inputs.
<h:commandButton value="#{text['button.add']}" id="add" styleClass="btn btn-default" actionListener="#{theForm.confirmAdd}"/>
public void confirmAdd() {
RequestContext.getCurrentInstance().closeDialog("uploadForm");
}
My managed bean is #ViewScoped. Will the command button break the view scope if the dialog is in an external file as done by PrimeFaces Dialog Framework? Whenever I click the "add upload" button, the #PostConstruct method is called again just like the scope is lost.
Comments section of the official blog says it won't break the view scope, but here the forum a core developer says openDialog() creates a new view, therefore it breaks the view scope.
Can someone confirm this?
PrimeFaces' Dialog Framework basically shows another view in an <iframe> tag. I wouldn't call that breaking a view scope, but the dialog view will have it's own scope, because it is practically a different page. That may or may not be desirable in different circumstances. As PrimeFaces' User Guide says:
Dialog Framework (DF) is used to open an external xhtml page in a
dialog that is generated dynamically on runtime.
p:dialog
Exists in the same view scope.
Can easily have the same conversation context.
Statically defined, the dialog and its components get created immediately on view build. You can only delay rendering, e.g. with a dynamic=true.
Declarative definition means it's more readable and maintainable, because the dialog's existence is not hidden somewhere in java code.
Dialog Framework
Has its own view scope.
Developer has to worry about passing parameters, propagating conversation context. (And PF didn't support includeViewParams until 5.1.)
Dynamic creation means dialog and its components won't be created until the dialog is actually opened, but a new dialog will be created each time it's opened. If the dialog is opened many times, the total performance hit will be larger, plus many dialog views can exhaust JSF view limit and expire other views.
Imperative dynamic creation allows for more resource efficiency in certain cases. E.g. show one specific dialog out of dozens based on user input. Or a rarely used dialog, which could be opened from any page of an application.
My recommendation would be to use p:dialog by default. Only use Dialog Framework in cases like I mentioned in the last bullet point.
That's normal because you have already instantiated theForm(ManagedBean) in your main.xhtml. SO the scope is already used within the main.xhtml.
When you clicked to open the dialog: the dialog is a new view, then a new instance of theForm (ManagedBean) is created.
We had some problems with #ViewScoped in the JBoss 7.1/Mojarra 2.1.7 and we changed to Omnifaces
I suggest you to use #org.omnifaces.cdi.ViewScoped instead of #javax.faces.bean.ViewScoped
I tested with both your example and here on the log you can see the difference:
Log with #org.omnifaces.cdi.ViewScoped
18:58:40,887 INFO [xxx.TheForm] (http-localhost-127.0.0.1-8080-2) #postconstruct
18:58:40,890 INFO [xxx.TheForm] (http-localhost-127.0.0.1-8080-2) openUpload()
Log with #javax.faces.bean.ViewScoped
19:01:19,753 INFO [xxx.TheForm] (http-localhost-127.0.0.1-8080-5) #postconstruct
19:01:19,753 INFO [xxx.TheForm] (http-localhost-127.0.0.1-8080-5) #postconstruct
19:01:19,754 INFO [xxx.TheForm] (http-localhost-127.0.0.1-8080-5) openUpload()
We are making the transition to bootstrap pages. As part of this, we are making most of our dialogs into simple include files that get rendered on demand. The include files have their own backing bean to minimize code duplication.
The typical use case is when a user enters a page a datatable shows a list of things. The user selects one or more rows in the table and then clicks a button to perform an action. The page is re-rendered using ajax. The datatable is not displayed but the former dialog is. The user then does whatever bulk operation the former dialog does and clicks execute (or cancel). The page is then re-rendered with the datatable showing and the former dialog box not.
The problem here is simple; how do you set the render flags on the datatable and former dialog box? Each of the beans needs to set the render flag of the other bean. I blithely tried injecting each bean into the other and promptly got a circular injection error at runtime. I've gone to having a callback interface that the datatable beans implement. When the former dialog bean gets injected, the datatable bean sets itself up to be called back. This works but I am not sure it's the best way to do it. Being an old swing programmer, I considered using property change listeners, which are much more robust than the simple interface, but I'm not sure what the implications of using them in a managed bean environment are. I did check out the messaging API but it clearly doesn't apply to this case.
So, what's the best way for two view beans that are backing the same page to talk to each other?
I would like to utilize p:tabView for horizontal site menu.
When tab is clicked,that user should be redirected in non-ajax style to the specific page.
Is it possible to inject to each tab (e.g. inside p:tab tag) href link ?
Or there is already some alternative to it?
You could put the p:tabView in a template and set the activeIndex property according to the view ID of the current page. It's an ugly hack, but certainly do-able. I did something similar, using a p:menu on the left for navigation in the control panel section of my site.
Primefaces 3.4 now has a p:tabMenu component that may be of use.
You will have to manage the active tab manually since this is an undeveloped feature.
I have a widget in my application that I need to display at two places(once in main page body and once through dialog box). Currently its code has been added twice in the page. Now I was thinking, If there was a way I could just include it only once and show the same instance in the dialog box, as in the main page body.
Can you suggest a way for this?
I'm Using:-
JSF 2.0 with Facelets
Primefaces 3.0 M3 Snapshot
JSF 2 has exactly the feature you want: it's called composite components. I bascially allows you to write a bunch of Facelet code into a file and use it just like any other JSF component, pass parameters to it, etc.
I'm trying to get some data from a datatable in rich:modal panel
The whole flow is as follows
When clicking on search button on main page, a modal panel pops up with appropriate data & check box
Till this point the application is working fine
After clicking on ok button, selected data should be populated into main page. This is where the code fails
I tried stuff like getRowData, getValues, etc. but in vain. This could be done by keeping the bean in session scope but I have to keep this bean in request scope using Apache MyFaces JSF 1.2
Two ways comes to mind:
Pass an extra request parameter (the search string and the page number?) so that the bean knows which data to preload.
Make use of MyFaces Orchestra to create a conversation scope which lies in between request and session scope and is exactly the scope you're looking for this particular functional requirement.