• About

N1nja Hacks

~ Random assortment of solutions, sneaky hacks and technical HOWTOs

N1nja Hacks

Tag Archives: RichFaces

Dirty <rich:tabPanel />

15 Tuesday Jan 2013

Posted by valblant in JSF

≈ Leave a comment

Tags

Javascript, RichFaces

I have recently had to implement a new requirement for all pages in our app that have a RichFaces Tab Panel. This post is about RichFaces 4.2.Final.

Requirement

Change tabs with Unsaved Changes:
1. Issue the following warning:

There are pending changes to the current tab that have not been saved. Do you wish to proceed with the tab change, or cancel and return to the tab?

2. The User may elect to either:
2.1. Proceed; The changes to the current tab are discarded.
2.2. Cancel; The use case continues at the step at which the user elected to change tabs.

Analysis

rich:tabPanel provides us with the following tools:

  • We can call a server method when the tab is changed (if we use ajax), but w/o ability to stop the tab change or show any warnings
  • We can call arbitrary javascript with ability to warn the user and abort tab switch, but the javascript is rendered at page render time, not at tab switch time, so no info from the server can be communicated

I did not want to get into server side tracking of all changes, since that would really complicate all pages, so the solution must be client side only.

Solution

I have created a very simple framework that I call Dirty Field Handler. It works as follows:

  • dirtyFieldHandler.js attaches a “delegated” event handler to the document, which will handle all “change” events from any input field on the page
  • Developer can use the DirtyFieldHandler framework as follows:
<!-- Include the framework on the page that needs it -->
 	<h:outputScript library="javascript" name="dirtyFieldHandler.js" target="head"/>

 	.....

 	<rich:tabPanel
 		switchType="ajax" <!-- Can't call the server w/o using ajax tab switches! -->
 		onbeforeitemchange='return DirtyFieldHandler.warnUser("#{msgs["common.warn.unsavedTab"]}");' <!-- Smart Javascript popup -->
 		itemChangeListener="#{initiativeBackingBean.tabSwitchAction}"> <!-- Notify the server that tab was switched -->

 		......

	</rich:tabPanel>

Code

 
dirtyFieldHandler.js:

/**
 * Provides the ability to detect if any input fields on the page were dirtied.
 * 
 * Exposes DirtyFieldHandler.warnUser(message, [true/false]) function that can be called
 * by the page to warn the user about dirty fields.
 * 
 * @author Val Blant
 */

if (!window.DirtyFieldHandler) {
	window.DirtyFieldHandler = {};
}


(function($, dfh) {
	
	dfh.setDirty = function() {
		dfh.dirty = true;
	}

	dfh.resetDirty = function() {
		dfh.dirty = false;
	}

	/**
	 * Warns the user if any fields are dirty. If the user chooses
	 * to navigate away, clears the dirty flag, unless the 2nd parameter is used
	 * to override that behavior
	 */
	dfh.warnUser = function(event, message, clearDirty) {
		var leavePage = true;
		clearDirty = typeof clearDirty !== 'undefined' ? clearDirty : true;
		
		if (dfh.dirty) {
			leavePage = confirm(message);
			if ( leavePage && clearDirty) {
				dfh.resetDirty();
			}
		}

		return leavePage;
	}
	
	
	
	// Init dirty flag
	//
	dfh.resetDirty();
	
	// Attach a "delegated" event handler to the document. All events that bubble
	// from input elements under this document will execute the handler.
	// We use a delegated handler b/c this approach will detect input field
	// changed or added by ajax requests
	//
	$(document).on("change", ":input", dfh.setDirty)

}(jQuery, window.DirtyFieldHandler));

Primefaces and Broken Head Resource Ordering

14 Monday Jan 2013

Posted by valblant in JSF

≈ Leave a comment

Tags

JSF, PrimeFaces, RichFaces

I have recently tried using PrimeFaces with a RichFaces application. I am very impressed with PrimeFaces. It is a well designed, simple, yet powerful JSF framework with a lot of cool components. Unfortunately, it does have bugs that I found as soon as I tried to use it.

Introduction

PrimeFaces is an open source JSF component suite with various extensions.

  • Rich set of components (HtmlEditor, Dialog, AutoComplete, Charts and many more).
  • Built-in Ajax based on standard JSF 2.0 Ajax APIs.
  • Lightweight, one jar, zero-configuration and no required dependencies.
  • Ajax Push support via websockets.
  • Mobile UI kit to create mobile web applications for handheld devices.
  • Skinning Framework with 35+ built-in themes and support for visual theme designer tool.
  • Extensive, clear documentation.
  • Large, vibrant and active user community.

Interaction with JSF stack

PrimeFaces uses the following classes to insert itself into the JSF framework. i.e – these are the classes which will be doing stuff to our requests, even if we are not using any PrimeFaces components!

  • org.primefaces.context.PrimePartialResponseWriter (affects AJAX requests)
  • org.primefaces.context.PrimePartialViewContext (affects AJAX requests)
  • org.primefaces.application.PrimeResourceHandler (affects resource handling)

Head Resource Ordering Bug

PrimeFaces comes with some very cool features that allow you to control where your resources are going to be rendered in the <HEAD/>. You can use facets to place your resources into “first”, “middle” and “last” positions. This is a nice feature, since with RichFaces I had to place our style and script tags at the end of the <BODY/>, to make sure that they are rendered after the RF resources. This order is important, since it allows us to override RF styles and scripts.

However, there is a very obvious bug in org.primefaces.renderkit.HeadRenderer which makes this feature quite destructive to our app. Simply including the PrimeFaces jar causes all of our script and style overrides to stop working, b/c the app resources are placed before all others.

There are other issues with this feature as well: http://code.google.com/p/primefaces/issues/detail?id=4807

Workaround

The problem is explained here: http://code.google.com/p/primefaces/issues/detail?id=4807#c1. Even though I know how to fix the problem, I do not wish to start maintaining our own PrimeFaces patches at this point of low adoption. So, the workaround is to disable Head Resource Ordering entirely for now:

WEB-INF/faces-config.xml:

<renderer>
   <component-family>javax.faces.Output</component-family>
   <renderer-type>javax.faces.Head</renderer-type>
   <renderer-class>com.sun.faces.renderkit.html_basic.HeadRenderer</renderer-class>
</renderer>

This means that we now have to manually hardcode the theme include for PrimeFaces components:

WEB-INF/layout/mainTemplate.xhtml:

<h:outputStylesheet library="primefaces-bluesky" name="theme.css" target="head" />

Blog at WordPress.com.