Removing Panels from My Account

So recently I was asked, "How can panels be removed from the My Account portlet?"

It seems like such a deceptively simple question since it used to be a supported feature, but my response to the question was that it is just not possible anymore.

Back in the 6.x days, all you needed to do was override the users.form.my.account.main, identification and/or miscellaneous properties in portal-ext.properties and you could take out any of the panels you didn't want the users to see in the my account panel.

The problem with the old way is that while it was easy to remove panels or reorganize panels, it was extremely difficult to add new custom panels to My Account.

With Liferay 7 and DXP, things have swung the other way.  With OSGi, it is extremely easy to add new panels to My Account.  Just create a new component that implements the FormNavigatorEntry interface and deploy it and Liferay will happily present your custom panel in the My Account.  See https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/form-navigator for information how to do this.

Although it is easy to add new panels, there is no way to remove panels.  So I set out to find out if there was a way to restore this functionality.

Background

In Liferay 7, the new Form Navigator components replaces the old portal properties setup.  But while there used to be three separate sets of properties (one for adds, one for updates and one for My Account), they have all been merged into a single set.  So even if there was a supported way to disable a panel, this would disable the panel from not only My Account but also from the users control panel, not something that most sites want.

So this problem actually points to the solution - in order to control the My Account panels separately, we need a completely separate Form Navigator setup.  If we had a separate setup, we'd also need to have a JSP fragment bundle override to use the custom Form Navigator rather than the original.

Creating the My Account Form Navigator

This is actually a simple task because the Liferay code is already deployed as an OSGi bundle, but more importantly the current classes are declared in an export package in the module's BND file.  This means that our classes can extend the Liferay classes without dependency issues.

Here's one of the new form navigator entries that I came up with:

@Component(
	immediate = true,
	property = {"form.navigator.entry.order:Integer=70"},
	service = FormNavigatorEntry.class
)
public class UserPasswordFormNavigatorEntryExt extends UserPasswordFormNavigatorEntry {

	private boolean visible = GetterUtil.getBoolean(PropsUtil.get(
		Constants.MY_ACCOUNT_PASSWORD_VISIBLE), true);

	@Override
	public String getFormNavigatorId() {
		return Constants.MY_ACCOUNT_PREFIX + super.getFormNavigatorId();
	}

	@Override
	public boolean isVisible(User user, User selUser) {
		return visible && super.isVisible(user, selUser);
	}
}

So first off our navigator entry extends the original entry, and that saves us a lot of custom coding.  We're using a custom portal property to disable the panel, so we're fetching that up front.  We're using the property setting along with the super class' method to determine if the panel should be visible.  This will allow us to set a portal-ext.property value to disable the panel and it will just get excluded.

The most important part is the override for the form navigator ID.  We're declaring a custom ID that will separate how the new entries and categories will be made available.

All of the other form navigator entries will follow the same pattern, they'll extend the original class, use a custom property to allow for disabling, and they'll use the special category prefix for the entries.

We'll do the similar with the category overrides:

@Component(
	property = {"form.navigator.category.order:Integer=30"},
	service = FormNavigatorCategory.class
)
public class UserUserInformationFormNavigatorCategoryExt extends UserUserInformationFormNavigatorCategory {
	@Override
	public String getFormNavigatorId() {
		return Constants.MY_ACCOUNT_PREFIX + super.getFormNavigatorId();
	}
}

For the three component categories we'll return our new form navigator ID string.

Creating the My Account JSP Fragment Bundle

Now that we have a custom form navigator, we'll need a JSP override on My Account to use the new version.

Our fragment bundle is based off the the My Account portlet, so we can use the following blade command:

blade create -t fragment -h com.liferay.my.account.web -H 1.0.4 users-admin-web-my-account

If you're using an IDE, just use the equivalent to create a fragment module from the My Account web module for the version currently used in your portal (check the $LIFERAY_HOME/work folder for the com.liferay.my.account.web folder as it includes the version number in your portal).

To use our new form navigator, we need to override the edit_user.jsp page.  This page actually comes from the modules/apps/foundation/users-admin/users-admin-web module from the Liferay source (during build time it is copied into the My Account module).  Copy the file from the source to your new module as this will be the foundation for the change.

I made two changes to the file.  The first change adds some java code to use a variable for the form navigator id to use, the second change was to the <liferay-ui:form-navigator /> tag declaration to use the variable instead of a constant.

Here's the java code I added:

// initialize to the real form navigator id.
String formNavigatorId = FormNavigatorConstants.FORM_NAVIGATOR_ID_USERS;

// if this is the "My Account" portlet...
if (portletName.equals(myAccountPortletId)) {
	// include the special prefix
	formNavigatorId = "my.account." + formNavigatorId;
}

We start with the current constant value for the navigator id.  Then if the portlet id matches the My Account portlet, we'll add our form navigator ID prefix to the variable.

Here's the change to the form navigator tag:

<liferay-ui:form-navigator 
	backurl="<%= backURL %>" 
	formmodelbean="<%= selUser %>" 
	id="<%= formNavigatorId %>" 
	markupview="lexicon">
</liferay-ui:form-navigator>

Build and deploy all of your modules to begin testing.

Testing

Testing is actually pretty easy to do.  Start by adding some portal-ext.properties file entries in order to disable some of the panels:

my.account.addresses.visible=false
my.account.additional.email.visible=false
my.account.instant.messenger.visible=false
my.account.open.id.visible=false
my.account.phone.numbers.visible=false
my.account.sms.visible=false
my.account.social.network.visible=false
my.account.websites.visible=false

If your portal is running, you'll need to restart the portal for the properties to take effect.

Start by logging in and going to the Users control panel and choose to edit a user.  Don't worry, we're not editing, we're just looking to see that all of the panels are there:

User Control Panel View

Next, navigate to My Account -> Account Settings to see if the changes have been applied:

My Account Panel

Here we can see that the whole Identification section has been removed since all of the panels have been disabled.  We can also see that password and personal site template sections have been removed from the view.

Conclusion

So this project has been loaded to GitHub: https://github.com/dnebing/my-account-override  Feel free to clone and use as you see fit.

It uses properties in portal-ext.properties to disable specific panels from the My Account page while leaving the user control panel unchanged.

There is one caveat to remember though.

When we created the fragment, we had to use the version number currently deployed in the portal.  This means that any upgrade to the portal, to a new GA or a new SP or FP or even hot fix may change the version number of the My Account portlet.  This will force you to come back to your fragment bundle and change the version in the BND file.  In fact, my recommendation here would be to match your bundle version to the fragment host bundle version as it will be easier to identify whether you have the right version(s) deployed.

Otherwise you should be good to go!

Update: You can eliminate the above caveat by using a version range in your bnd file.  I changed the line in bnd.bnd file to be:

Fragment-Host: com.liferay.my.account.web;bundle-version="[1.0.4,2.0.0)"

This allows your fragment bundle to apply to any newer version of the module that gets deployed up to 2.0.0.  Note, however, that you should still compare each release to ensure you're not losing any fixes or improvements that have been shipped as an update.

Blogs
Hej David,
Is there alsow a way to remove panels from the product menu -> User (For example "my workflow tasks") ?
Greetings
Hey David,

Thanks a lot for the tutorial.

The fact that it's harder to do this in Liferay 7 than in 6.2 is not intentional. We are working on a fix to make it very similar to what it was in previous versions (maybe even better).

@alex Customizing the product menu is described in the official documentation: https://dev.liferay.com/develop/tutorials/-/knowledge_base/7-0/customizing-the-product-menu
Thanks for the update Jorge. Can't wait to see the changes!

I was asked how to solve this problem today, so until the new and better way is available, this remains the only option.

@alex I think the product menu has the same issue - easy adds now but impossible removes (even the customizing link from @Jorge only talks about adds and not about removes). This technique can be used to solve the problem but you'd have to research to find the right jsp to override.
Hi Jorge - any update on the changes you described here?
Hey Abre,

Thanks for asking. It was indeed implemented, although I don't remember for sure if it was made available for 7.0 or it will be released as part of 7.1.

@sergiogonzalez might be able to answer that.
Hey Abre,
we have actually implemented that and it's available since Liferay 7 GA4 and Liferay DXP FixPack 14.
You can check the technical details and code here https://issues.liferay.com/browse/LPS-70043 and of course that we added some documentation about how to use it here https://dev.liferay.com/discover/portal/-/knowledge_base/7-0/configuring-form-navigator-forms.

Please, feel free to leave us feedback either in the documentation or in the LPS ticket.

Thanks!
Hi Sergio:
Thanks for posting that this feature is now available. I read over it, but, I don't see how this would make removing the "My Workflow" menu item, which was Alex's question.

Can you please give me a hint on how these types of items (including the My Sync Devices, and My Submissions items) can be removed?

Thanks!
Hey David,
Right now you can either disable the component that is responsible for that. In the case of MyWorkflow it would be https://github.com/liferay/liferay-portal/blob/master/modules/apps/forms-and-workflow/portal-workflow/portal-workflow-task-web/src/main/java/com/liferay/portal/workflow/task/web/internal/application/list/MyWorkflowTaskPanelApp.java They all end up with "PanelApp.java".
You can also disable the whole module or app if you're not planning to use that.
Just to confirm, this works very well for removing major sections of the account settings page. Thanks very much for following up.
Is there a way to change the section category text?
For example, in the images you posted, there are sections named 'Categorization', is there a way to change that to some other text?

Some things can now be hidden by custom configuration on Foundation - Form Navigator Configuration. Details on https://dev.liferay.com/discover/portal/-/knowledge_base/7-0/configuring-form-navigator-forms

Hi David, 

Thanks for such informative blog. I wanted to hide/show some options in layout on user role basis. For the same I tried extending LayoutAdvancedFormNavigatorEntry. It seems my class is not being recognized by liferay. Please help me out to understand what is wrong there. Thanks in advanced.

Hi David,I'm looking to achieve the same you mentioned in post, but unable to figure out from where I need to start. As I'm new to Liferay, I'm using liferay7.0.3 CE and IDE, I'll migrate to 7.3 after this MyAccount thing get sorted out.Let me know know any points or document from where I can start.