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:

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

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.

