Remote Apps: How to use Liferay 7.4 new feature?

When we think about Liferay, we always think about Liferay development style. Even to create React modules until 7.3 version, the React code is Liferay based because you need to have an OSGI module to achieve the final result. However, things are changing! 

First, what is React? React is a declarative, efficient, and flexible JavaScript library for building user interfaces. It lets you create complex UIs called components from small and isolated pieces of code. Second, why React? React is one of the most popular JS libraries around the world and nowadays it has already surpassed the Angular framework. Considering that, in my opinion, it's a great choice to be used in new projects :) 

So, how can we use React apps in Liferay 7.4? Let's see how this works diving into some examples.

 

1. React App

You will need a React App running to test it. As the main point in this post is talking about Liferay new feature and not explaining how to create a React App, I'll use a React App created by Maximilian Schwarzmüller in his course React - the complete guide in Udemy platform. 
 

My React App will be running at http://localhost:3000 address and you can find the original application code here.


But, to add this application into Liferay, you need to do some changes listed below:

  1. Add this shell script to your root folder;
  2. Change package.json file to have the scripts section below. I've marked in bold that scripts that you need to change it.

    "scripts": {

    "start": "npm run build && npx serve ./build",

    "build": "react-scripts build && ./rename-chunks.sh",

    "test": "react-scripts test",

    "eject": "react-scripts eject"

    },

  3. Update you index.js file to have an added WebComponent to your application with the ElementId that you'll configure in Liferay - it can be any string as, for example, "my-app-test". You can find the code below:

    class WebComponent extends HTMLElement {

         connectedCallback() {

              ReactDOM.render(<App />, this);
         }

    }

    const ELEMENT_ID = 'remote-age-app';

    if (!customElements.get(ELEMENT_ID)) {

         customElements.define(ELEMENT_ID, WebComponent);

    }

  4. In your public/index.html file, you need to change the <div id="root"></div> element to an element with your ElementId defined in the previous step, like <remote-age-app></remote-age-app>.

You can find the modified code here.

 

2. Connect your app to Liferay

If you can take a look at Liferay Menu in the Applications tab, we have the Custom Apps > Remote Apps option.

By adding a new Remote App you will have the following fields:

  1. Name: The name that your application will have in Liferay Menu;
  2. Type: IFrame  or Custom Element ~ I'll use Custom Element because I'm not creating an IFrame application;
  3. HTML Element Name: The main element's name of your application;
  4. URL (repeatable field): All JS's URLs should be added here;
  5. CSS URL (repeatable field):  All CSS's URLs should be added here;
  6. Instanceable: If your application is instanceable it means that you can add the portlet more than once on same page;
  7. Portlet Category Name: Which category your application will be displayed in Liferay Menu. By default, it's selected the Remote Apps category - I will use the default one;
  8. Properties: You can add dynamic properties to your application - continue reading to learn more about this! :)

 

Considering this explanation, the example will be filled like this:

 

3. Use your app in Liferay Pages

After the second step, you'll now have a new category called Remote Apps and your app will appear with the name configured in the previous step as a Widget to add in any Liferay Page!

 

That's it! You can now add as many apps as you want to your Liferay :)

 

4. Extra - Properties

On the properties field in Remote App configuration, you can add dynamic properties to your application. To do that, just edit your application created before and add some properties like the example below:

 

After that, you can use the properties in your JS code as below:

  1. In your WebComponent element, receive the properties from Liferay configuration:

    class WebComponent extends HTMLElement {

         connectedCallback() {

              const properties = {

                   dynamic_property_test: this.getAttribute('dynamic_property_test'),

              };

              ReactDOM.render(<App properties={properties} />, this);

         }

    }

  2. In you JS code, you can add the properties as a parameter and get the value to use it between curly brackets {}. You can see the example below:

     

    const App = ({ properties }) => {

         const [usersList, setUsersList] = useState([]);

         const title = properties.dynamic_property_test;

         const addUserHandler = (userName, userAge) => {

              setUsersList((prevUsersList) => {

                   return [

                        ...prevUsersList,

                        { id: Math.random().toString(), name: userName, age: userAge                      },

                   ];

              });

         };

         return (

              <div>

                   <h1>{title}</h1>

                   <AddUser onAddUser={addUserHandler} />

                   <UsersList users={usersList} />

              </div>

         );

    };

    export default App;

You can add the code with properties here. And your title will appear before the application:


 

As showed above, you can now create React apps and use it in your Liferay installation as widget apps. Although you can still develop as before, this new version will help us to build awesome applications to Liferay, who will run outside Liferay, without necessarily knowing all Liferay development details. 

I hope you can use the power of this new feature to increase your development in Liferay DXP 7.4 platform. And, of course, if you’ve more tips, doubts or other ways to do the same thing about this subject, please leave them in the comments below!

 

You can find all code used here.

Blogs

Thanks for the excellent article! How can I access the host Liferay instance's theme information so I can make the remote app respond dynamically to theme changes?

Hi! What do you mean by theme changes? You can access themeDisplay object in your remote app to get some Liferay configurations, as an example below:

Liferay.ThemeDisplay.getPathThemeImages()

Thanks!

I'm attempting to leverage some features from a liferay 7.4 dxp into some older apps via remote apps, however I cant seem to find the remote app client SDK script, I am expecting to find it at {host}/o/remote-app-client-js/remote-app-client-js.js but this gives me a 404 when I attempt to import. does this need to be manually generated? is it somewhere else in 7.4? thanks

found it, in 7.4 it seems to be /o/client-extension-client-js/client-extension-client-js.js

perhaps I spoke too soon and these are in fact slightly different, I've noticed this script is pretty temperamental, specifically very prone to attempting to register while already registered and subsequently invalidating the client object. I see that client extensions are still considered a beta feature and perhaps that's what's going on. Maybe this is just normal or I am using it incorrectly. I thought I came across at some point mention of someone needing to have deployed the remote-app-sdk manually but I am having trouble finding it again. At any still open to any insight on the matter.

hey j w,

The remote app client extension feature have been changing a lot since this article was written. I recommend to you the following doc: https://learn.liferay.com/w/dxp/building-applications/client-extensions

 

Thanks! yes, that article has been my primary source of info on client extensions and the basis for the one I am currently working with. Perhaps ill fire up a 7.3 instance and compare to the remote apps there.