---
title: Add Custom Fonts
product: Survey Creator
description: Theme Editor is a form styling tool integrated into SurveyJS Form Builder. With the Theme Editor, form creators can use a set of UI controls to adjust form colors, fonts, sizes, and more. If a desired font is missing from the predefined font collection, you can easily register a custom font and make it available in the font families list. Try out a live demo for JavaScript with a step-by-step guide on how to add and use custom fonts in SurveyJS Form Builder.
framework: Angular
source: https://surveyjs.io/survey-creator/examples/add-custom-fonts/angular
index: https://surveyjs.io/survey-creator/examples/overview.md
---

# Add Custom Fonts (Angular)

Theme Editor in SurveyJS Form Builder enables designers to personalize surveys and forms by creating custom UI themes. Although Theme Editor ships with a set of default fonts, you might want to use custom branded fonts to enhance the look and feel of your forms and give your surveys a personalized touch. To add custom fonts to Theme Editor, follow these steps:

1. Register custom fonts.      
Add custom fonts to the page with Survey Creator. In this demo, custom fonts are loaded from a server and added as a `<style>` element to the `<head>` of the page. Refer to the `loadFont` function for code listing. The following code shows how you can specify custom TTF fonts using CSS:

    ```css
    @font-face {
      font-family: "RobotoMono-Regular"; /* Provide a name for your font */
      src: url("./custom-fonts/RobotoMono-Regular.ttf") format("truetype");
      /* Add other font properties, like `font-weight` and `font-style` if needed */
    }
    @font-face {
      font-family: "RobotoMono-Italic"; /* Provide a name for your font */
      src: url("./custom-fonts/RobotoMono-Italic.ttf") format("truetype");
      /* Add other font properties, like `font-weight` and `font-style` if needed */
    }
    ```

1. Add custom fonts to the font list.      
Import the `DefaultFonts` array from the `"survey-creator-core"` module and push new font names to this array. The font names must begin with a font's `font-family` attribute value:

    ```js
    import { DefaultFonts } from "survey-creator-core";

    DefaultFonts.push(
        "RobotoMono-Regular, monospace",
        "RobotoMono-Italic, monospace"
    );
    ```

Now, custom fonts are available within Theme Editor. For instance, you can apply them using the **Font Family** setting in the **Appearance** tab:

<img src="/Content/Images/examples/custom-fonts/custom-fonts.png" alt="Access custom fonts in SurveyJS Theme Editor" width="1600" height="782">

## Files

### `src/app/components/creator.component.css`

```css
/* You can define custom CSS rules here */
```

### `src/app/components/creator.component.html`

```html
<div style="position: fixed; top: 0; bottom: 0; right: 0; left: 0;">
    <survey-creator [model]="model"></survey-creator>
</div>
```

### `src/app/components/survey_json.js`

```js
export const formJSON = {
  "title": "Online Check-in",
  "description": "Check-in is available 2 to 24 hours prior to departure for all destinations. To complete the check-in process, please fill out the form below.",
  "completedHtml": "<div style=\"max-width:640px;text-align:center;margin:16px auto;\">\n\n<div style=\"padding:0 24px;\">\n<h4>Check-in complete.</h4>\n<p>Thank you for checking in. Your journey with us is all set. Have a great flight.</p>\n</div>\n\n</div>\n",
  "pages": [
    {
      "name": "page1",
      "elements": [
        {
          "type": "paneldynamic",
          "name": "passengers",
          "width": "100%",
          "minWidth": "256px",
          "titleLocation": "hidden",
          "templateElements": [
            {
              "type": "text",
              "name": "first-name",
              "width": "35%",
              "minWidth": "208px",
              "title": "PASSENGER #{panelIndex} INFO",
              "titleLocation": "top",
              "placeholder": "First name"
            },
            {
              "type": "text",
              "name": "last-name",
              "width": "30%",
              "minWidth": "172px",
              "startWithNewLine": false,
              "title": " ",
              "titleLocation": "top",
              "placeholder": "Last name"
            },
            {
              "type": "dropdown",
              "name": "prefix",
              "width": "35%",
              "minWidth": "208px",
              "startWithNewLine": false,
              "title": " ",
              "titleLocation": "top",
              "choices": [
                "Mr.",
                "Mrs.",
                "Ms."
              ],
              "choicesOrder": "random",
              "placeholder": "Prefix",
              "allowClear": false
            },
            {
              "type": "multipletext",
              "name": "birthdate",
              "width": "65%",
              "minWidth": "256px",
              "items": [
                {
                  "name": "date",
                  "inputType": "date",
                  "title": "Date of birth"
                }
              ]
            },
            {
              "type": "text",
              "name": "nationality",
              "width": "35%",
              "minWidth": "208px",
              "startWithNewLine": false,
              "placeholder": "Nationality"
            },
            {
              "type": "text",
              "name": "passport-number",
              "width": "100%",
              "minWidth": "256px",
              "title": "PASSENGER #{panelIndex} ID",
              "titleLocation": "top",
              "placeholder": "Passport #"
            },
            {
              "type": "dropdown",
              "name": "passport-issue-country",
              "width": "35%",
              "minWidth": "208px",
              "choicesByUrl": {
                "url": "https://surveyjs.io/api/CountriesExample",
                "valueName": "name"
              },
              "placeholder": "Country of issue",
              "allowClear": false
            },
            {
              "type": "multipletext",
              "name": "passport-exp-date",
              "width": "65%",
              "minWidth": "256px",
              "startWithNewLine": false,
              "items": [
                {
                  "name": "date",
                  "inputType": "date",
                  "title": "Exp. date"
                }
              ]
            }
          ],
          "panelCount": 1,
          "minPanelCount": 1,
          "confirmDeleteText": "Do you want to delete the passenger?",
          "addPanelText": "ADD PASSENGER",
          "removePanelText": "REMOVE",
          "showProgressBar": false
        },
        {
          "type": "panel",
          "name": "person-to-notify",
          "elements": [
            {
              "type": "text",
              "name": "person-to-notify-first-name",
              "width": "35%",
              "minWidth": "208px",
              "title": "PERSON TO NOTIFY",
              "titleLocation": "top",
              "setValueIf": "{passengers[0].first-name} notempty",
              "setValueExpression": "{passengers[0].first-name}",
              "placeholder": "First name"
            },
            {
              "type": "text",
              "name": "person-to-notify-last-name",
              "width": "30%",
              "minWidth": "172px",
              "startWithNewLine": false,
              "title": " ",
              "titleLocation": "top",
              "setValueIf": "{passengers[0].last-name} notempty",
              "setValueExpression": "{passengers[0].last-name}",
              "placeholder": "Last name"
            },
            {
              "type": "dropdown",
              "name": "person-to-notify-prefix",
              "width": "35%",
              "minWidth": "208px",
              "startWithNewLine": false,
              "title": " ",
              "titleLocation": "top",
              "setValueIf": "{passengers[0].prefix} notempty",
              "setValueExpression": "{passengers[0].prefix}",
              "choices": [
                "Mr.",
                "Mrs.",
                "Ms."
              ],
              "choicesOrder": "random",
              "placeholder": "Prefix",
              "allowClear": false
            },
            {
              "type": "text",
              "name": "person-to-notify-email",
              "width": "65%",
              "minWidth": "256px",
              "inputType": "email",
              "placeholder": "Email"
            },
            {
              "type": "text",
              "name": "person-to-notify-phone",
              "width": "35%",
              "minWidth": "208px",
              "startWithNewLine": false,
              "placeholder": "Phone"
            },
            {
              "type": "text",
              "name": "person-to-notify-address",
              "width": "100%",
              "minWidth": "256px",
              "title": "ADDRESS",
              "titleLocation": "top",
              "placeholder": "Address line 1"
            },
            {
              "type": "text",
              "name": "person-to-notify-city",
              "width": "35%",
              "minWidth": "208px",
              "placeholder": "City"
            },
            {
              "type": "text",
              "name": "person-to-notify-state",
              "width": "30%",
              "minWidth": "172px",
              "startWithNewLine": false,
              "placeholder": "State"
            },
            {
              "type": "text",
              "name": "person-to-notify-zip",
              "width": "35%",
              "minWidth": "208px",
              "startWithNewLine": false,
              "placeholder": "Zip Code"
            },
            {
              "type": "dropdown",
              "name": "person-to-notify-country",
              "width": "100%",
              "minWidth": "256px",
              "choicesByUrl": {
                "url": "https://surveyjs.io/api/CountriesExample",
                "valueName": "name"
              },
              "placeholder": "Country",
              "allowClear": false
            }
          ],
          "questionTitleLocation": "hidden",
          "width": "100%",
          "minWidth": "256px"
        },
        {
          "type": "panel",
          "name": "flight",
          "elements": [
            {
              "type": "text",
              "name": "departure-booking-number",
              "width": "65%",
              "minWidth": "256px",
              "title": "DEPARTURE",
              "titleLocation": "top",
              "validators": [
                {
                  "type": "regex",
                  "text": "Your booking number must consist of exactly 6 digits.",
                  "regex": "^\\d{6}$"
                }
              ],
              "maxLength": 6,
              "placeholder": "Please enter your 6-digit booking number"
            },
            {
              "type": "text",
              "name": "departure-flight-number",
              "width": "35%",
              "minWidth": "208px",
              "startWithNewLine": false,
              "title": " ",
              "titleLocation": "top",
              "placeholder": "Flight #"
            },
            {
              "type": "multipletext",
              "name": "departure-date",
              "width": "65%",
              "minWidth": "256px",
              "items": [
                {
                  "name": "date",
                  "inputType": "date",
                  "title": "Date"
                }
              ]
            },
            {
              "type": "multipletext",
              "name": "departure-time",
              "width": "35%",
              "minWidth": "208px",
              "startWithNewLine": false,
              "items": [
                {
                  "name": "time",
                  "inputType": "time",
                  "title": "Time"
                }
              ]
            },
            {
              "type": "dropdown",
              "name": "departure-country",
              "width": "65%",
              "minWidth": "256px",
              "title": "DEPARTING FROM",
              "choicesByUrl": {
                "url": "https://surveyjs.io/api/CountriesExample"
              },
              "placeholder": "Country",
              "allowClear": false
            },
            {
              "type": "text",
              "name": "departure-city",
              "width": "35%",
              "minWidth": "208px",
              "startWithNewLine": false,
              "title": " ",
              "placeholder": "City"
            },
            {
              "type": "dropdown",
              "name": "destination-country",
              "width": "65%",
              "minWidth": "256px",
              "title": "DESTINATION",
              "titleLocation": "top",
              "choicesByUrl": {
                "url": "https://surveyjs.io/api/CountriesExample"
              },
              "placeholder": "Country",
              "allowClear": false
            },
            {
              "type": "text",
              "name": "destination-city",
              "width": "35%",
              "minWidth": "208px",
              "startWithNewLine": false,
              "title": " ",
              "titleLocation": "top",
              "placeholder": "City"
            },
            {
              "type": "checkbox",
              "name": "connecting-flight",
              "width": "100%",
              "minWidth": "256px",
              "choices": [
                {
                  "value": "true",
                  "text": "I have a connecting flight"
                }
              ]
            },
            {
              "type": "multipletext",
              "name": "connecting-flight-date",
              "visibleIf": "{connecting-flight} = ['true']",
              "width": "65%",
              "minWidth": "256px",
              "items": [
                {
                  "name": "date",
                  "inputType": "date",
                  "title": "Date"
                }
              ]
            },
            {
              "type": "multipletext",
              "name": "connecting-flight-time",
              "visibleIf": "{connecting-flight} = ['true']",
              "width": "35%",
              "minWidth": "208px",
              "startWithNewLine": false,
              "items": [
                {
                  "name": "time",
                  "inputType": "time",
                  "title": "Time"
                }
              ]
            },
            {
              "type": "text",
              "name": "connecting-flight-booking-number",
              "visibleIf": "{connecting-flight} = ['true']",
              "width": "65%",
              "minWidth": "256px",
              "title": "DEPARTURE",
              "validators": [
                {
                  "type": "regex",
                  "text": "Your booking number must consist of exactly 6 digits.",
                  "regex": "^\\d{6}$"
                }
              ],
              "maxLength": 6,
              "placeholder": "Please enter your 6-digit booking number"
            },
            {
              "type": "text",
              "name": "connecting-flight-number",
              "visibleIf": "{connecting-flight} = ['true']",
              "width": "35%",
              "minWidth": "208px",
              "startWithNewLine": false,
              "placeholder": "Flight #"
            }
          ],
          "questionTitleLocation": "hidden",
          "width": "100%",
          "minWidth": "256px"
        }
      ]
    }
  ],
  "questionDescriptionLocation": "underInput",
  "questionErrorLocation": "bottom",
  "completeText": "Check In",
  "widthMode": "static",
  "width": "860"
}
```

### `src/app/components/theme_json.js`

```js
export const customTheme = {
    "backgroundImageFit": "cover",
    "backgroundImageAttachment": "scroll",
    "backgroundOpacity": 1,
    "cssVariables": {
        "--sjs2-color-bg-basic-primary": "rgba(255, 255, 255, 1)",
        "--sjs2-color-utility-property-grid": "rgba(255, 255, 255, 1)",
        "--sjs2-color-utility-tabs": "rgba(255, 255, 255, 1)",
        "--sjs2-color-utility-toolbox": "rgba(255, 255, 255, 1)",
        "--sjs2-color-bg-basic-primary-dim": "rgba(248, 248, 248, 1)",
        "--sjs2-color-bg-neutral-tertiary-dim": "rgba(243, 243, 243, 1)",
        "--sjs2-color-utility-surface-survey-panelless": "rgba(243, 243, 243, 1)",
        "--sjs2-color-utility-surface-survey": "rgba(243, 243, 243, 1)",
        "--sjs2-color-bg-basic-secondary": "rgba(249, 249, 249, 1)",
        "--sjs2-color-bg-basic-secondary-dim": "rgba(243, 243, 243, 1)",
        "--sjs2-color-fg-basic-primary": "rgba(0, 0, 0, 0.91)",
        "--sjs2-color-fg-basic-secondary": "rgba(0, 0, 0, 0.45)",
        "--sjs2-color-project-brand-600": "rgba(25, 179, 148, 1)",
        "--sjs2-color-bg-brand-secondary": "rgba(25, 179, 148, 0.1)",
        "--sjs2-color-bg-brand-primary-dim": "rgba(20, 164, 139, 1)",
        "--sjs2-color-fg-brand-on-primary": "rgba(255, 255, 255, 1)",
        "--sjs2-color-fg-brand-primary-disabled": "rgba(255, 255, 255, 0.25)",
        "--sjs2-base-unit-size": "8px",
        "--sjs2-base-unit-spacing": "8px",
        "--sjs2-base-unit-radius": "4px",
        "--sjs2-color-bg-accent-primary": "rgba(255, 152, 20, 1)",
        "--sjs2-color-bg-accent-secondary": "rgba(255, 152, 20, 0.1)",
        "--sjs2-color-bg-accent-secondary-dim": "rgba(255, 152, 20, 0.25)",
        "--sjs2-color-fg-accent-on-primary": "rgba(255, 255, 255, 1)",
        "--sjs2-color-fg-accent-primary-disabled": "rgba(255, 255, 255, 0.25)",
        "--sjs2-border-effect-surface-default": "0px 1px 2px 0px rgba(0, 0, 0, 0.15)",
        "--sjs2-border-effect-floating-default": "0px 2px 6px 0px rgba(0, 0, 0, 0.1),0px 8px 16px 0px rgba(0, 0, 0, 0.1)",
        "--sjs2-border-effect-component-formbox-default": "inset 0px 1px 2px 0px rgba(0, 0, 0, 0.15)",
        "--sjs2-border-effect-component-check-true-default": "inset 0px 1px 2px 0px rgba(0, 0, 0, 0.15)",
        "--sjs2-border-effect-component-check-false-default": "inset 0px 1px 2px 0px rgba(0, 0, 0, 0.15)",
        "--sjs2-color-border-basic-secondary": "rgba(0, 0, 0, 0.09)",
        "--sjs2-color-component-input-default-line": "rgba(0, 0, 0, 0.16)",
        "--sjs2-color-border-basic-secondary-overlay": "rgba(0, 0, 0, 0.16)",
        "--sjs2-color-bg-alert-primary": "rgba(229, 10, 62, 1)",
        "--sjs2-color-bg-alert-secondary": "rgba(229, 10, 62, 0.1)",
        "--sjs2-color-fg-alert-on-primary": "rgba(255, 255, 255, 1)",
        "--sjs2-color-bg-positive-primary": "rgba(25, 179, 148, 1)",
        "--sjs2-color-bg-positive-secondary": "rgba(25, 179, 148, 0.1)",
        "--sjs2-color-fg-positive-on-primary": "rgba(255, 255, 255, 1)",
        "--sjs2-color-bg-note-primary": "rgba(67, 127, 217, 1)",
        "--sjs2-color-bg-note-secondary": "rgba(67, 127, 217, 0.1)",
        "--sjs2-color-fg-note-on-primary": "rgba(255, 255, 255, 1)",
        "--sjs2-color-bg-warning-primary": "rgba(255, 152, 20, 1)",
        "--sjs2-color-bg-warning-secondary": "rgba(255, 152, 20, 0.1)",
        "--sjs2-color-fg-warning-on-primary": "rgba(255, 255, 255, 1)",
        "--sjs2-typography-font-family-text": "RobotoMono-Regular, monospace",
        "--sjs2-typography-font-weight-component-header-title": "700",
        "--sjs2-typography-font-size-component-header-description": "20px",
        "--sjs2-typography-font-weight-component-page-title": "700"
    },
    "themeName": "default",
    "colorPalette": "light",
    "isPanelless": false
};
```

### `src/app/components/creator.component.ts`

```ts
import { Component, OnInit } from "@angular/core";
import { SurveyCreatorModel } from "survey-creator-core";
import "survey-core/survey.i18n";
import "survey-creator-core/survey-creator-core.i18n";
import { formJSON } from "./survey_json";
import { customTheme } from "./theme_json";
import { DefaultFonts } from "survey-creator-core";

import "survey-core/survey-core.css";
import "survey-creator-core/survey-creator-core.css";

import SurveyTheme from "survey-core/themes";
import { registerCreatorTheme, registerSurveyTheme } from "survey-creator-core";

registerSurveyTheme(SurveyTheme); // Add predefined Form Library UI themes
registerCreatorTheme(SurveyTheme); // Add predefined Survey Creator UI themes

let fontIsLoading = true;
let serverHost = window.location.origin;
if (serverHost.indexOf("localhost") < 0 && serverHost.indexOf("surveyjs") < 0)
    serverHost = "https://surveyjs.io";

loadFont({
    serverHost: serverHost,
    fontPath: "fontbase64_robotomonoregular",
    fontFamily: "RobotoMono-Regular"
});

loadFont({
    serverHost: serverHost,
    fontPath: "fontbase64_robotomonoitalic",
    fontFamily: "RobotoMono-Italic"
});

function loadFont({ serverHost, fontPath, fontFamily }) { 
    const fontUrl = serverHost + "/api/" + fontPath;
    fetch(fontUrl)
        .then(response => {
            if (!response.ok) {
                throw new Error(`HTTP error: ${response.status}`);
            }
            return response.text();
        })
        .then(base64Font => {
            // Create a `<style>` element for the loaded font
            var style = document.createElement('style');

            // Set the `innerHTML` aatribute of the `<style>` element
            // to the `@font-face` rule with base64-encoded font data
            style.innerHTML = "@font-face { font-family: '" + fontFamily + "'; src: url(data:application/x-font-woff;charset=utf-8;base64," + base64Font + ") format('truetype'); }";

            // Append the `<style>` element to the document `<head>`
            document.head.appendChild(style);
            fontIsLoading = false;
        });
};

@Component({
    // tslint:disable-next-line:component-selector
    selector: "component-survey-creator",
    templateUrl: "./creator.component.html",
    styleUrls: ["./creator.component.css"]
})
export class SurveyCreatorComponent implements OnInit {
    model: SurveyCreatorModel;
    ngOnInit() {
        const creator = new SurveyCreatorModel({ showThemeTab: true });
        DefaultFonts.push(
            "RobotoMono-Regular, monospace",
            "RobotoMono-Italic, monospace"
        );
        
        creator.JSON = formJSON;
        creator.theme = customTheme;
        creator.activeTab = "theme";
        this.model = creator;
    }
}
```

### `src/app/app.component.html`

```html
<component-survey-creator></component-survey-creator>
```

### `src/app/app.component.ts`

```ts
import { Component } from "@angular/core";

@Component({
    selector: "app-root",
    templateUrl: "./app.component.html"
})
export class AppComponent {
    title = "CodeSandbox";
}
```

### `src/app/app.module.ts`

```ts
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { AppComponent } from "./app.component";
import { SurveyCreatorModule } from "survey-creator-angular";
import { SurveyCreatorComponent } from "./components/creator.component";

@NgModule({
    declarations: [AppComponent, SurveyCreatorComponent],
    imports: [BrowserModule, SurveyCreatorModule],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule { }
```

### `src/environments/environment.prod.ts`

```ts
export const environment = {
    production: true
};
```

### `src/environments/environment.ts`

```ts
// The file contents for the current environment will overwrite these during build.
// The build system defaults to the dev environment which uses `environment.ts`, but if you do
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
// The list of which env maps to which file can be found in `.angular-cli.json`.

export const environment = {
    production: false
};
```

### `src/index.html`

```html
<app-root></app-root>
```

### `src/main.ts`

```ts
import { enableProdMode } from "@angular/core";
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";

import { AppModule } from "./app/app.module";
import { environment } from "./environments/environment";

if (environment.production) {
    enableProdMode();
}

platformBrowserDynamic()
    .bootstrapModule(AppModule)
    .catch(err => console.log(err));
```

### `src/polyfills.ts`

```ts
/**
 * This file includes polyfills needed by Angular and is loaded before the app.
 * You can add your own extra polyfills to this file.
 *
 * This file is divided into 2 sections:
 *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
 *   2. Application imports. Files imported after ZoneJS that should be loaded before your main
 *      file.
 *
 * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
 * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
 * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
 *
 * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
 */

/***************************************************************************************************
 * BROWSER POLYFILLS
 */

/** IE9, IE10 and IE11 requires all of the following polyfills. **/
// import 'core-js/es6/symbol';
// import 'core-js/es6/object';
// import 'core-js/es6/function';
// import 'core-js/es6/parse-int';
// import 'core-js/es6/parse-float';
// import 'core-js/es6/number';
// import 'core-js/es6/math';
// import 'core-js/es6/string';
// import 'core-js/es6/date';
// import 'core-js/es6/array';
// import 'core-js/es6/regexp';
// import 'core-js/es6/map';
// import 'core-js/es6/weak-map';
// import 'core-js/es6/set';

/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js';  // Run `npm install classlist.js`.

/** IE10 and IE11 requires the following for the Reflect API. */
// import 'core-js/es6/reflect';

/** Evergreen browsers require these. **/
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
import "core-js/proposals/reflect-metadata";

/**
 * Required to support Web Animations `@angular/platform-browser/animations`.
 * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
 **/
// import 'web-animations-js';  // Run `npm install web-animations-js`.

/***************************************************************************************************
 * Zone JS is required by default for Angular itself.
 */
import "zone.js/dist/zone"; // Included with Angular CLI.

/***************************************************************************************************
 * APPLICATION IMPORTS
 */
```

### `src/styles.css`

```css
/* You can add global styles to this file and import other style files */
```

### `src/typings.d.ts`

```ts
/* SystemJS module definition */
declare var module: NodeModule;
interface NodeModule {
    id: string;
}
```

### `.angular-cli.json`

```json
{
  "apps": [
    {
      "root": "src",
      "outDir": "dist",
      "assets": [ "assets", "favicon.ico" ],
      "index": "index.html",
      "main": "main.ts",
      "polyfills": "polyfills.ts",
      "prefix": "app",
      "styles": [ "styles.css"  ],
      "scripts": [  ],
      "environmentSource": "environments/environment.ts",
      "environments": {
        "dev": "environments/environment.ts",
        "prod": "environments/environment.prod.ts"
      }
    }
  ]
}
```

### `_tsconfig.json`

```json
{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "allowSyntheticDefaultImports": true,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "resolveJsonModule": true,
    "target": "es2015",
    "module": "es2020",
    "lib": [
      "es2018",
      "dom"
    ]
  }
}
```

### `package.json`

```json
{
  "name": "surveyjs-angular",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build --prod",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "14.1.1",
    "@angular/cdk": "14.1.1",
    "@angular/common": "14.1.1",
    "@angular/compiler": "14.1.1",
    "@angular/core": "14.1.1",
    "@angular/forms": "14.1.1",
    "@angular/platform-browser": "14.1.1",
    "@angular/platform-browser-dynamic": "14.1.1",
    "@angular/router": "14.1.1",
    "core-js": "3.6.4",
    "rxjs": "6.5.4",
    "survey-angular-ui": "latest",
    "survey-creator-core": "latest",
    "survey-core": "latest",
    "survey-creator-angular": "latest",
    "tslib": "1.13.0",
    "zone.js": "0.11.7"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~13.0.0",
    "@angular/cli": "~13.0.0",
    "@types/jasmine": "3.6.3",
    "@types/jasminewd2": "2.0.8",
    "@types/node": "14.14.28",
    "codelyzer": "6.0.1",
    "jasmine-core": "3.6.0",
    "jasmine-spec-reporter": "6.0.0",
    "karma": "6.1.1",
    "karma-chrome-launcher": "3.1.0",
    "karma-coverage-istanbul-reporter": "3.0.3",
    "karma-jasmine": "4.0.1",
    "karma-jasmine-html-reporter": "1.5.4",
    "protractor": "7.0.0",
    "ts-node": "9.1.1",
    "tslint": "~6.1.3",
    "typescript": "4.1.5"
  },
  "keywords": [ "angular", "surveyjs" ],
  "description": "SurveyJS-Angular example project"
}
```

## Other Frameworks

- [React](https://surveyjs.io/survey-creator/examples/add-custom-fonts/reactjs.md)
- [Vue 3](https://surveyjs.io/survey-creator/examples/add-custom-fonts/vue3js.md)
- [jQuery](https://surveyjs.io/survey-creator/examples/add-custom-fonts/jquery.md)
- [Vanilla JS](https://surveyjs.io/survey-creator/examples/add-custom-fonts/vanillajs.md)
