Saturday, 26 March 2011

One area where, in my opinion, Visualforce can really improve the user experience is editing parent and child records in a single page. Think about how many clicks are required to edit and save each contact associated with an account on a one by one basis.

To this end I've created a page and associated controller that allows a subset of details for all contacts (and the parent account) to be edited and saved in one go. This also allows new contacts to be created and existing contacts to be deleted. Below is a screen shot of the page:

The page itself is pretty clunky - clicking the Delete contact button fires the action method to carry out the delete without any user confirmation, while the New Contact button creates a new contact called "Change Me" and refreshes the page:

It does have one smarter feature though - if the page is accessed without specifying an ID, it goes into new account mode, and doesn't render any content or buttons related to contacts.

The Visualforce markup is shown below. If you are a regular reader of this blog you'll recognise it as heavily based on the sample from the Persisting List Edits in Visualforce post. Note that as usual you don't need a lot of markup to produce some pretty useful functionality.

The ID of the contact chosen to delete is propagated back to the controller via the the assignTo attribute. This means that by the time the deleteContact action method is invoked, the chosenContactId controller property will have been populated with the ID from the page. One important point to note about this - I've found that since Winter 11, you must have a rerender attribute on the commandButton for the parameter to be passed to the controller.

The controller is a little more complex, as it has action methods to support each of the buttons - Save and Exit, Save (and remain on page), Delete Contact and New Contact.

In part 2, I'll look at improving the user experience by adding confirmation of delete and allowing the user to specify fields when creating a new contact. This page also looks like it would benefit from fieldsets, so its likely those will be introduced as well.

11 comments:

while clicking on new contact button i am just doing like below written code.. then how can i delete the respective contact...i think you are doing an insert and delete dml on the contact every time.Apart from that i will do like this.. then how can i achieve the delete functionality....Hope you got my point?

Can you explain what you mean by "delete the respective contact"? If you look at my code, it determines the contact to delete based on an apex:param nested in the command button, which passes the id of the contact to delete to the controller.

1. by clicking on new contact initially you are inserting a dummy contact right?here I am creating a list of contact objects only but not inserting in to the database in my scenario. why because i want to eliminate unnecessary insertions and deletions.2.if that is the scenario then how can i identify my contact to delete i.e. what is the value that i can set to the param in the command button as that contact is not there in the database..got my point?how can i handle this scenario....

In this case I am inserting a dummy that the user then has to update. If you take a look at the second part of this blog, you'll see a different technique, but I don't think that is what you are looking for either.

I suspect you'll need to use a wrapper class that contains the contact and an id, where the id can simply be the position of the contact in the list. Then you can use pass back the id to the controller so that it can be removed from the list.

You could include the visualforce in the page layout as it uses the account standard controller. However, this would only show up on the view page which I think is less than ideal from the user experience perspective.

Hi Bob, Is it possible to implement the same logic for a case where we only would display the records using Outputfield. And only for a specific field want to allow editing and updation on a cross object. To allow editing,am using inlineEditsuport, am not able to work on this,as not able to capture the record ID on which i want to do an update. ANy suggestion would be quite helpful..Thanks