PrimeFaces dialog framework - closing dialog using remoteCommand, parent method not fired - jsf-2

JSF 2.2; PrimeFaces 5.3
My goal is to capture user closing dialog by clicking X button, go back to parent page so data can be refreshed and update form.
I was able to get p:remoteCommand to call my confirmAndCloseDialog() method in DialogBean, but the onDialogReturn() method in ParentBean is never called. Why is onDialogReturn not called? Any way I can get it to work?
BTW if a user would exit out dialog the normal way, i.e. close the dialog by clicking p:commandButton (CLOSE DIALOG), then everythign is fine.
Here are my codes.
Thank you!
Parent page:
<h:form>
...
<p:commandButton value="Open dialog"
id="openDialogButton"
actionListener="#{parentBean.openDialog()}"
update="#form">
<p:ajax event="dialogReturn"
listener="#{parentBean.onDialogReturn}"
update="#form"/>
</p:commandButton>
...
</h:form>
Dialog page:
<body style="height: 80%;" onunload="userClickOnX();" >
<h:form id="aForm">
<p:remoteCommand id="userClickOnX"
name="userClickOnX"
actionListener="#{dailogBean.confirmAndCloseDialog}"/>
......
<p:commandButton id="closeDialog"
value="CLOSE DIALOG"
actionListener="#{dialogBean.confirmAndCloseDialog}"/>
</h:form>
</body>
ParentBean
public void openDialog() {
Map<String, Object> options = new HashMap<>();
options.put("modal", true);
options.put("draggable", true);
options.put("resizable", true);
options.put("closable", true);
options.put("contentWidth", "100%");
options.put("contentHeight", "100%");
options.put("width", 1000);
options.put("height", 800);
RequestContext.getCurrentInstance().openDialog("dialog", options, null);
}
public void onDialogReturn(SelectEvent event) {
refresh data ....
}
DialogBean:
public void confirmAndCloseDialog() {
RequestContext.getCurrentInstance().closeDialog(objectForParent);
}

4 years later, Primefaces' dialog framework default closable "X" button is still just a link and uses javascript to hide the dialog, that is why the dialogReturn event isn't fired on using said button. I don't know a way to "intercept" its action. So if you don't want to have a custom button closing your dialog, you're out of luck, BUT you can always reinvent the wheel, kind of:
Copy Primefaces's button and make it better :)
<h:body>
<h:form id="formToolbar">
<a class="ui-dialog-titlebar-icon ui-dialog-titlebar-close ui-corner-all" href="#"
role="button"
style="float: right; position: relative; top: -10px; left: -3px; color: #757575;"
onclick="close()">
<span class="ui-icon ui-icon-closethick"></span>
</a>
<p:remoteCommand id="close" name="close" action="#{dialogController.close()}">
</p:remoteCommand>
</h:form>
...
<h:body>
You can tweek the position and color to your liking
In the dialog bean:
public void close() {
PrimeFaces.current().dialog().closeDynamic(null);
}
Now you can expect the returnDialog event in the parent page and respective bean.
<p:commandButton action="#{parentBean.openDialog(param)}">
<p:ajax event="dialogReturn" listener="#{parentBean.handleReturn()}"/>
</p:commandButton>
Remember to set closable to false when opening the dialog otherwise you will have two "X" buttons:
Map<String,Object> options = new HashMap<String, Object>();
options.put("closable", false);
options.put("draggable", false);
PrimeFaces.current().dialog().openDynamic(
"dialog",
options,
null)
PS: I set draggable to false as well, you can still use draggable mode, but this creates a bar on top of the dialog that's not reachable inside the dialog's page, so your "X" button would be positioned a little more towards the bottom which isn't aesthetically pleasing. Hopefully dragging isn't a must.

Have you setup the Dialog Configurations?
As per: http://www.primefaces.org/docs/guide/primefaces_user_guide_5_3.pdf
faces-config.xml
<application>
<action-listener>
org.primefaces.application.DialogActionListener
</action-listener>
<navigation-handler>
org.primefaces.application.DialogNavigationHandler
</navigation-handler>
<view-handler>
org.primefaces.application.DialogViewHandler
</view-handler>
</application>
Also - your :
should be inside the dialog div/contruction, not inside the button you're selecting.

Related

How to remove default tooltip from menu item in collapsable state with sidebar?

How to remove default tooltip from a menu item in a collapsible state with sidebar? It seems like the same question asked in the ant design GitHub also, but no response. Code and screenshot below.
<Menu.Item key="profile">
<Link to={`${baseConfig.page.profile.url}`}>
<span className="isoMenuHolder" style={{color:'#ffffff'}}>
<i className="icon-admin" />
<span className="nav-text">
Settings
</span>
</span>
</Link>
</Menu.Item>
Take it out with css
.ant-tooltip {
display: none;
}
Not sure if my workaround helps you or not but I have a collapse/expand button within the Menu and it displays the color of the button as the tooltip. So i removed the Menu.Item and the tooltip disappeared
<Menu
mode="inline"
theme="light"
inlineCollapsed={this.state.menuCollapsed}
className="CollapseButtonMenu"
>
<Button type="primary" onClick={this.toggleCollapsed} style={{ marginBottom: 16 }}>
<Icon type={this.state.menuCollapsed ? 'menu-unfold' : 'menu-fold'} />
</Button>
</Menu>
since the new changes on antd (> 4.23.3), the <Menu.Item /> component was deprecated, with the new API they provide a way to make the tooltip disappear is to define the title attribute as null or as an empty string on the items list like:
const items = [
{
key: "0",
title: "", //this makes the tooltip disappear
label: "Any Label"
}
];

How can I show a "loader" during knockout.js initialization?

I have a single-page web-app built with knockout.js and jQuery Mobile.
The view-model initialization (i.e. the ko.applyBindings() function) takes about 7-8 seconds. During this time, the page shows blank.
$(document).ready(function () {
ko.applyBindings(viewModel);
})
Is there a way to show the JQM loader in the meantime, or to show a kind of "splash screen", to give to the user a feedback that the "page is loading"?
Note that it seems to me that the solution proposed by #Jeroen is also good together with the default page transitions of jQuery Mobile, at least as I can see in this jsfiddle.
To be honest, the tip proposed by #Omar seems to me to have better integration with JQM, and I will try in the future to combine both answers, with a writeable computed observable to switch the JQM loader on/off.
Keep it simple! Show a loading overlay in your html by default, but use a visible: false binding of some kind. That way when the applyBindings call is done the UI will hide the overlay.
For example, suppose this view:
<div id="main">
<div id="loading-overlay" data-bind="visible: loading"></div>
Some content<br />
Some content
</div>
And suppose this view model:
vm = { loading: ko.observable(true) };
Then calling this:
ko.applyBindings(vm);
If for whatever reason it takes 7 secs to load, the loading-overlay will be shown until the UI is updated.
This approach is great if you have a client side DAL or some single point where you run Ajax calls, because you can follow this pattern:
vm.loading(true)
Ajax call with callbacks for success and failure
On callback do vm.loading(false)
Knockout will handle the overlay visibility for you.
See this fiddle for a demo, or check out this Stack Snippet:
vm = { loading: ko.observable(true) };
ko.applyBindings(vm);
// Mock long loading time:
window.setTimeout(function() {
vm.loading(false);
}, 5000);
html { height: 100%; }
body {
position: relative;
height: 100%;
width: 100%;
}
#loading-overlay {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: url('http://img.cdn.tl/loading51.gif') white no-repeat center;
opacity: 0.75;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<div id="main">
<div id="loading-overlay" data-bind="visible: loading"></div>
Some content<br />
Some content<br />
Some content<br />
Some content<br />
Some content<br />
<input type='text' value='cant edit me until overlay is gone' /><br />
<button>can't press me until overlay's gone!</button><br />
Some content<br />
Some content<br />
Some content
</div>

Dynamic click event not firing

I have a jQuery mobile page with a number of images I'm using as buttons.
When the page initially loads, all of the images have a class of 'inactive'.
If I click 1 of the buttons, its class is changed to 'active' and all of the other buttons are changed from 'inactive' to 'disabled'. If I navigate away from the page and navigate straight back, the 1 image still has a class of 'active', and the rest still have a class of 'disabled'.
When I click the active button it changes class from 'active' to 'inactive', and all of the other buttons change class from 'disabled' to 'inactive'.
This allows me to choose another button to be the active one.
when I click one of the buttons that was previously disabled but is now inactive, the click event doesn't fire. It's as though it thinks the class is still disabled as it was when the page initially loaded. I've checked using Firebug in Firefox and the class is correctly set as inactive, but it's still behaving as though the class is disabled.
Here's my jQuery:
$(document).ready(function() {
$('.inactive, .active').on("click", function(){
// Toggle active/inactive class
$(this).toggleClass("active inactive");
// Disable if 1 active button, else inactive
if($('.active').length == 1) {
$('.inactive').toggleClass("inactive disabled");
} else {
$('.disabled').toggleClass("disabled inactive");
}
});
});
And the HTML buttons:
<a class="button inactive"></a><br />
<a class="button inactive"></a><br />
<a class="button inactive"></a><br />
<a class="button inactive"></a><br />
<a class="button inactive"></a><br />
<a class="button inactive"></a>
And the classes:
.button {
background:url("../images/compare.png") no-repeat;
width: 18px;
height:18px
}
.active {
background-position: 0 -18px;
cursor:pointer
}
.inactive {
background-position: 0 0;
cursor:pointer
}
.disabled {
background-position: 0 -36px;
cursor:default
}
Ok guys, I've figured this out.
When I change the class from disabled to inactive, the click handler doesn't get attached to the 'new' inactive buttons automatically.
I've added a new class 'mybutton' to all the buttons (so an active button would be class="mybutton active" for example), then looked for that class in the click handler so even the disabled buttons will run through the code.
Here's my new code:
$(document).ready(function() {
$('.mybutton').on("click", function(){
if($(this).hasClass("inactive") || $(this).hasClass("active")) {
$(this).toggleClass("active inactive");
}
// Disable if 1 active button, else inactive
if($('.active').length == 1) {
$('.inactive').toggleClass("inactive disabled");
} else {
$('.disabled').toggleClass("disabled inactive");
}
});
});
I had to wrap the $(this).toggleClass("active inactive"); statement in an if statement which has me puzzled.
Without the if statement, clicking a disabled button would turn it to active.
Why would this happen? And why does wrapping the button in an if statement fix it when it's just checking for the same classes as the toggle?

ToolTip for each SelectOneMenu Items in jsf

My requirement is to provide a tooltip for every option in the
SelectOneMenu because label of option is so large
that it's not possible to provide such a large size SelectOneMenu .So the
label is cutting. Thats why i need tooltip to show
the whole value on mouse over of the options in the SelectOneMenu .
Any ideas will be appreciated.
If you are using a list of "javax.faces.model.SelectItem" you can pass the description attribute to show a tooltip for each and every option.
You can use javascript.
Assume your selectOneMenu as below.
<h:form id="form1">
<h:selectOneMenu id="combo1">
<f:selectItem itemLabel="First Label"/>
<f:selectItem itemLabel="Second Label"/>
<f:selectItem itemLabel="Third Label"/>
</h:selectOneMenu>
</h:form>
Add this script at the top of your page.
<script>
window.onload = function() {
var options = document.getElementById("form1:combo1").options;
for(var i = 0; i < options.length; i++) {
options[i].title = options[i].innerHTML;
}
}
</script>

Refresh jquery ui dialog position

I'm using a jquery dialog.
The content of this dialog is dynamic so the height change when the dialog is open.
$("#a_div").dialog({ width: 400 });
The dialog initially appears center in the page. but when the height change is no more center.
How can i refresh the dialog's position without close and reopen it?
thanks
You need to re-set the position by doing:
$("#a_div").dialog({
position: { 'my': 'center', 'at': 'center' }
});
The position is set once when creating the dialog, but can be altered afterwards (or just re-set at the same value, forcing jQuery to recalculate).
See this demo: http://jsfiddle.net/petermorlion/3wNUq/2/
If you want to use the exact position settings as used by jquery ui for the initial positioning, you can grab the options from the jquery ui code and use them again any time you want to reposition your dialog.
function refreshDialogPosition(id) {
$("#" + id).position({
my: "center",
at: "center",
of: window,
collision: "fit",
// Ensure the titlebar is always visible
using: function (pos) {
var topOffset = $(this).css(pos).offset().top;
if (topOffset < 0) {
$(this).css("top", pos.top - topOffset);
}
}
});
}
Use:
refreshDialogPosition("YourDialogId");
This will also make sure your title bar is always visible. Otherwise your title bar will be outside your screen when using dialogs with large content. (content height > window height)
Have a nice day.
You can try to resize the dialog using its classes by JQuery directly (documentation here)
The basic structure of JQueryUI Dialog is this:
<div class="ui-dialog ui-widget ui-widget-content ui-corner-all ui-draggable ui-resizable">
<div class="ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix">
<span id="ui-dialog-title-dialog" class="ui-dialog-title">Dialog title</span>
<a class="ui-dialog-titlebar-close ui-corner-all" href="#"><span class="ui-icon ui-icon-closethick">close</span></a>
</div>
<div style="height: 200px; min-height: 109px; width: auto;" class="ui-dialog-content ui-widget-content" id="dialog">
<p>Dialog content goes here.</p>
</div>
</div>
So, maybe you should play with classes's width and height to set the best.
Another solution is to set dialog's width directly before open (when your data is successfully loaded):
$("#a_div").dialog({ width: 400 });
$.get('my_url.php',function(data){
$('#a_div .ui-dialog').css('width','400px');
// Or...
$('#a_div').css('width','400px');
});
I hope it helps you.
Marked as Correct didn't work for me. It persists position once it opened.
Following code will reset dialog position, every time you open/re-open it.
$dlg.dialog({
open: function(event, ui) {
// Reset Dialog Position
$(this).dialog('widget').position({ my: 'center', at: 'center', of: window });
}
});
$dlg.dialog('open');

Resources