HomeDev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunitySubmit a ticketLog In
GitHubNuGetDev CommunitySubmit a ticket

Install headless Optimizely Forms JavaScript SDK for the client app

👍

Beta

Headless Optimizely Forms is in beta. Its functionality may change drastically during the development. This should be used only for internal testing and not be used in production.

See Optimizely Forms for information about generally available Forms.

Precondition: npm install -g typescript

  1. Create a React app template.

    npx create-react-app headless-form --template typescript
    cd headless-form
    
  2. Install Javascript SDK. Create a file .npmrc with content to download the package from GitHub.

    @episerver:registry=<https://npm.pkg.github.com/episerver/always-auth=true//npm.pkg.github.com/episerver/:\_authToken=${NPM\_AUTH\_TOKEN}>
    

    📘

    Note

    NPM_AUTH_TOKEN is Environment variable and the value is your GitHub token.

    npm install @episerver/forms-sdk @episerver/forms-react react-router-dom @types/react-router-dom
    

    📘

    Note

    Replace the react-router-dom with version =5.3.4.

  3. Create file .env with content.

    REACT_APP_ENDPOINT_GET_FORM_BY_PAGE_URL=http://localhost:8000/api/React/GetFormInPageByUrl?url=
    REACT_APP_HEADLESS_FORM_BASE_URL=http://localhost:8000/
    REACT_APP_AUTH_BASEURL=http://localhost:8000/api/episerver/connect/token
    
  4. Add code to \src\App.tsx.

    import "./App.css";
    import { useFetch } from "./useFetch";
    import { Form, FormLogin } from "@episerver/forms-react";
    import {
      FormCache,
      FormConstants,
      IdentityInfo,
      extractParams,
    } from "@episerver/forms-sdk";
    import { useState } from "react";
    import { useHistory, useLocation } from "react-router-dom";
    
    function App() {
      const location = useLocation();
      const { language } = extractParams(window.location.pathname);
      const url = `${process.env.REACT_APP_ENDPOINT_GET_FORM_BY_PAGE_URL}${location.pathname}`;
    
      const { data: pageData, loading } = useFetch(url);
    
      const formCache = new FormCache();
      const [identityInfo, setIdentityInfo] = useState<IdentityInfo>({
        accessToken: formCache.get<string>(FormConstants.FormAccessToken),
      } as IdentityInfo);
    
      const history = useHistory();
    
      const handleAuthen = (identityInfo: IdentityInfo) => {
        setIdentityInfo(identityInfo);
      };
    
      return (
        <div className="App">
          {loading && <div className="loading">Loading...</div>}
    
          {!loading && pageData && (
            <>
              <h1>{pageData.title}</h1>
              <div className="main">
                <div className="left">
                  {pageData.childrens.map((c: any) => (
                    <Form
                      key={c.reference.key}
                      formKey={c.reference.key}
                      language={language ?? "en"}
                      baseUrl={process.env.REACT_APP_HEADLESS_FORM_BASE_URL ?? "/"}
                      identityInfo={identityInfo}
                      history={history}
                      currentPageUrl={pageData.pageUrl}
                    />
                  ))}
                </div>
                <div className={`right`}>
                  <h2>Login</h2>
                  <FormLogin
                    clientId="TestClient"
                    authBaseUrl={process.env.REACT_APP_AUTH_BASEURL ?? ""}
                    onAuthenticated={handleAuthen}
                  />
                </div>
              </div>
            </>
          )}
        </div>
      );
    }
    
    export default App;
    
    
  5. Remove App.test.tsx file.

  6. Update code \src\index.tsx.

    import React from "react";
    import ReactDOM from "react-dom/client";
    import "./index.css";
    import App from "./App";
    import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
    
    const root = ReactDOM.createRoot(
      document.getElementById("root") as HTMLElement
    );
    root.render(
      <React.StrictMode>
        <Router>
          <Switch>
            <Route path="/">
              <App />
            </Route>
          </Switch>
        </Router>
      </React.StrictMode>
    );
    
  7. Add file \src\useFetch.ts.

    import { useEffect, useState } from "react";
    
    export const useFetch = (url: string) => {
      const [data, setData] = useState<any>(null);
      const [loading, setLoading] = useState<boolean>(false);
      const [error, setError] = useState<any>(null);
    
      useEffect(() => {
        const fetchData = async () => {
          setLoading(true);
          fetch(url)
            .then(async (response: Response) => {
              if (response.ok) {
                setData(await response.json());
              }
            })
            .catch((err: any) => {
              setError(err);
            })
            .finally(() => {
              setLoading(false);
            });
        };
    
        if (!loading) {
          fetchData();
        }
    
        // eslint-disable-next-line react-hooks/exhaustive-deps
      }, [url]);
    
      return { data, loading, error };
    };
    
    
  8. Run client site.

    npm start
    
  9. Change the frontend's port to ClientApp's port on ManagementSite.

    • Update appsettings.json file.
    • Update on Manage Websites.
    • Use http instead of https on launchSettings.json.