Angular is a powerful, useful framework for any developer that wants to build applications that can scale gracefully. Angular was created to handle large-scale projects with built-in tools. As a comprehensive JavaScript framework developed by Google, it’s trusted by developers around the world. It’s ideal for data-driven enterprise apps because of its robust tools like dependency injection, two-way data binding, and modular component architecture.
In this guide you'll create a new Angular project from scratch and learn how to integrate essential features as you build, including an Angular rich text editor. Whether you're creating a CRM interface or content-driven tool, this setup gives you everything you need to get started. Angular is a complex framework, so strap in and grab some coffee for this one. Though it will take several steps to get there, at the end of this guide you’ll have a fully functional Angular app to show off.
Prerequisites
To install Angular CLI and work on the Angular project in this guide, you’ll need:
- Node.js: Node Package Manager (NPM) is the standard manager for JavaScript libraries. If you don’t already have it, you can download Node.js and install it.
- A TinyMCE API key: If you don’t have one already, you can set up a TinyMCE API key in two minutes.
Step one: Install Angular CLI
Angular CLI is a command line tool that lets you deploy, create, and edit Angular projects. Install it via NPM in the directory where you’ll build your Angular project:
npm install -g @angular/cli@20
To verify that Angular is installed in your environment, run ng version
. If you’re using the latest version of Angular it should show Angular 20, released in May 2025.
Step two: Create new Angular project via Angular CLI
Now that you have Angular CLI, you’ll use it to create a new Angular project with an Angular CLI command:
ng new angular-project
This creates a folder with the right project architecture for an Angular app. When you create a new project, Angular CLI will ask three questions:
- If you want to create a zoneless app: The answer is Yes. This will create a faster app. Per Angular’s docs “ZoneJS does not have any insight into whether application state actually changed and so this synchronization is triggered more frequently than necessary”, so you’re saving payload size and startup time cost. This is a new project setup question as of Angular 20.
- To choose a CSS style: You’ll need to choose a CSS style. We recommend Less, a CSS library that makes accessing styles quick and easy through variables.
- If you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering): The answer is No, because you want the app to render on the client side, creating a faster render.
The next step is to open the angular-project folder in your favorite IDE and take a look at the Angular app’s architecture.
New Angular project setup: Understand project architecture
If you haven’t built an Angular app before, it’s good to understand the project architecture and how the app functions. Here’s what Angular 20 project files with Less will look like after the project is generated, and before you add your own components:
angular-project/
├── src/
│ ├── app/
│ │ ├── app.config.ts
│ │ ├── app.html
│ │ ├── app.less
│ │ ├── app.routes.ts
│ │ ├── app.spec.ts
│ │ └── app.ts
│ ├── index.html
│ ├── main.ts
│ └── styles.less
├── angular.json
├── tsconfig.app.json
├── tsconfig.json
└── tsconfig.spec.json
If you’re familiar with Typescript and Less, you’ll see some added relevant files used for building and styling our app. Typescript is an excellent way to write JavaScript with stricter typing.
In /app, you’ll see app.ts. This is the source file that holds an Angular app’s root component. Essentially this is the top-level component that manages all of the other components. We’ll talk more about components later, but for now just know that app.ts is important.
/app is also an important directory for Angular components, since this is where they will be added to the app later on.
Build and run your Angular project
To build a new Angular project’s dependencies and see the sample app locally in a browser, you’ll change directory into the angular-project folder in the CLI.
cd angular-project
Then you’ll use Node to install dependencies:
npm install
And last but not least, you’ll launch the Angular app and open it in a browser window to see your setup.
ng serve
ng serve
launches the app to localhost:4200. Voila! you have a running Angular project, ready as a foundation to create any app you’d like. You can leave the app running in the browser and for the most part, you won’t have to rebuild it every time you make a change in order to see those changes in the local instance.
Step three: Create and integrate Angular components
One of Angular’s strengths is its ability to handle large applications at scale. The way that Angular does this is through components. Components are a specific block of code that are reusable throughout the Angular project, with its own CSS and HTML.
An Angular app holds a tree of components. For example, in a Customer Relationship Management (CRM) tool page for contacting customers, there would be a component holding the “To” and “From” fields, a component for writing to customers, and another component to send the message.
Create new components
For this guide, let's go with the CRM example for now, and create a new component that allows the user to send messages to customer accounts. This component will be called ContactCustomerComponent
, and it will hold:
- A “To” and “From” field.
- A rich text editor (RTE) for composing a message.
- A “Send” button to simulate sending the message.
Each of these three items will also be their own component, capable of being reused wherever you need in your Angular app.
Create the ContactCustomerComponent
To create a new component, you’ll navigate to the angular-project/ folder in the CLI and run:
ng generate component contact-customer
🔥 Hot Tip: If you want to see your new work you’ll need to restart your app after major changes have been made, like adding components. If the app is running, use Ctrl+C to stop the app in the CLI and run the generate component command above. Once that’s done, run ng serve
to get your app running again on localhost:4200.
Now that the new component is created, you’ll see a new directory appear under app/contact-customer/ that contains four new files:
contact-customer/
├── contact-customer.html
├── contact-customer.less
├── contact-customer.spec.ts
└── contact-customer.ts
The code you care most about will be in contact-customer.ts, so let’s open that file to add some functionality to our contact customer form. Right now, the component just exists and doesn’t really do anything. You’ll create a container for the form of the contact customers.
You can use the following code and replace contact-customer.ts:
import { Component, signal } from "@angular/core";
import { ContactFieldsComponent } from "../contact-fields/contact-fields";
import { SendButtonComponent } from "../send-button/send-button";
@Component({
selector: "app-contact-customer",
standalone: true,
imports: [ContactFieldsComponent, SendButtonComponent],
templateUrl: "./contact-customer.html",
})
export class ContactCustomerComponent {
// Use signals for reactivity
to = signal("");
from = signal("");
message = signal("");
updateFields(fields: { to: string, from: string }) {
this.to.set(fields.to);
this.from.set(fields.from);
}
handleSend() {
console.log("Sending message");
console.log("From:", this.from());
console.log("To:", this.to());
console.log("Message:", this.message());
// TODO: Send via service or API
}
updateMessage(content: string) {
this.message.set(content);
}
}
And replace everything in contact-customer.html with this:
<div class="contact-page">
<app-contact-fields (fieldsChanged)="updateFields($event)" />
<editor
class="rte"
apiKey="no-api-key"
[init]="{
}"
></editor>
<app-send-button (send)="handleSend()" />
</div>
Now you have a component that holds room for an RTE, To and From fields, and a Send button. It’s time to make ContactFieldsComponent
and SendButtonComponent
, and import TinyMCE, a robust and powerful rich text editor.
⚠️ Note: You’ll see compilation errors in the CLI where you’re running your Angular app. This is normal while you’re creating related components that reference each other, but aren’t all created yet. These errors will disappear naturally once you’ve created ContactFieldsComponent
and SendButtonComponent
.
Create the ContactFieldsComponent
Create a component for the contact “From” and “To” fields using the same process. Start with:
ng generate component contact-fields
Once the project generates your files for the component, visit contact-fields.ts and replace everything in it with this:
import { Component, EventEmitter, Output } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-contact-fields',
standalone: true,
imports: [CommonModule, FormsModule],
template: `
<div class="fields">
<label>
To:
<input type="email" [(ngModel)]="to" (ngModelChange)="emitChange()" />
</label>
<label>
From:
<input type="email" [(ngModel)]="from" (ngModelChange)="emitChange()" />
</label>
</div>
`
})
export class ContactFieldsComponent {
to: string = '';
from: string = '';
@Output() fieldsChanged = new EventEmitter<{ to: string; from: string }>();
emitChange() {
this.fieldsChanged.emit({
to: this.to,
from: this.from
});
}
}
Great start. Don’t run ng serve
again yet since the application build will fail until you add the other components.
Integrate TinyMCE into the ContactCustomerComponent
To add TinyMCE to our form, you’ll need to install it first via NPM:
npm install --save @tinymce/tinymce-angular
Now, because TinyMCE has already done all of the work to create their component, all you need to do is import the TinyMCE EditorModule
to ContactCustomerComponent
.
Your contact-customer.ts file should now include the TinyMCE EditorModule
like this:
import { Component, signal } from '@angular/core';
import { ContactFieldsComponent } from '../contact-fields/contact-fields';
import { SendButtonComponent } from '../send-button/send-button';
import { EditorModule } from '@tinymce/tinymce-angular';
@Component({
selector: 'app-contact-customer',
standalone: true,
imports: [ContactFieldsComponent, EditorModule, SendButtonComponent],
templateUrl: './contact-customer.html'
})
export class ContactCustomerComponent {
...
Just one more step to create the Send button.
Create the SendButtonComponent
At this point you’re familiar with the drill:
- Create the component via Angular CLI.
- Alter the component’s Typescript file to behave the way you need.
For SendButtonComponent
, you’ll run:
ng generate component send-button
And replace everything in the new send-button.ts with this code:
import { Component, EventEmitter, Output } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-send-button',
standalone: true,
imports: [CommonModule],
template: `
<button (click)="send.emit()" class="send-btn">Send</button>
`
})
export class SendButtonComponent {
@Output() send = new EventEmitter<void>();
}
Excellent! You’ve created an Angular component that contains three other components as a flexible and useful customer contact page for a CRM. Now let’s add it to the front page so you can test it out.
Bring all the components together on the main Angular app page
Now that you built the ContactCustomerComponent
, you’ll want to add it to your Angular app to use it. It’s easy enough to do, with a few options for configuration. To integrate the ContactCustomerComponent
into the app, replace everything in app.ts with this:
import { Component } from "@angular/core";
import { ContactCustomerComponent } from "./contact-customer/contact-customer"; // adjust the path as needed
@Component({
selector: "app-root",
standalone: true,
imports: [ContactCustomerComponent],
templateUrl: "./app.html",
styleUrls: ["./app.less"], // fixed typo: was `styleUrl` instead of `styleUrls`
})
export class App {}
And replace everything in app.html with this one line:
<app-contact-customer></app-contact-customer>;
Run ng serve
after your work, and return to http://localhost:4200/. You’ll see a basic CRM form for contacting customers, ready to go! Nice job!
Step four: Configure TinyMCE in Angular
Configuring TinyMCE in Angular is easy. It’s critical to do this so you can get the most out of your CRM page and you can use the RTE that you've built in. To change the editor you’ll edit the configuration for TinyMCE in contact-customer.html. The code looks like this:
<editor
class="rte"
apiKey="no-api-key"
[init]="{
}"
></editor>
The first thing to do is add an API key for TinyMCE. If you don’t already have one, you can get a TinyMCE API key in two minutes.
Now you can change the editor’s init script to configure TinyMCE. Here’s a basic TinyMCE setup to start with. It has expected RTE features built in on startup like lists, alignment, and tables.
[init]="{
height: 500,
plugins: 'lists link image table code help wordcount',
toolbar: 'undo redo | formatselect | bold italic emoticons | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent'
}"
And that’s it!
Step five: Style your Angular application with Less
Your app probably looks like this right now:
This means that it’s not much to look at, the spacing isn’t proper, and the UI in general is plain. We’ll need to install Less, and add a few styles to make it look more like a real web app. To install Less via NPM, run:
npm install -g less
Next, you’ll open the styles.less file, which controls all the universal CSS variables in the Less framework for the whole Angular app.
For some cleaner spacing and a more centralized app, you can add these styles to the file and alter them as you wish:
/* You can add global styles to this file, and also import other style files */
@background: lightblue;
@padding: 1%;
@margin: 1em;
@top: 1em;
@margin-bottom: 1em;
body {
background-color: @background;
}
.fields {
display: flex;
flex-direction: column;
padding-top: @padding;
margin-top: @top;
margin-bottom: @margin-bottom;
}
label {
font-family: Verdana, Geneva, Tahoma, sans-serif;
display: flex;
flex-direction: column;
font-weight: bold;
margin: @margin;
margin-bottom: @margin-bottom;
}
input {
padding: 1em;
font-size: 1rem;
}
.rte {
padding-top: @padding;
margin-top: @top;
margin-bottom: @margin-bottom;
}
.send-btn {
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: large;
font-weight: bold;
background-color: lightgreen;
border-radius: 25px;
display: block;
float: right;
padding: 0.5em 1em 0.5em 1em;
margin-top: @top;
margin-bottom: @margin-bottom;
}
.send-btn:hover {
background-color: antiquewhite;
}
If you choose to implement this styling, your app will look like this:
What’s next? Enhance your Angular CRM app with TinyMCE features
Now you have a foundational contact form that you can build into any kind of Angular app. And if you want to take this foundation and build a CRM app in Angular with TinyMCE, you can! TinyMCE is already used in CRM apps around the world.
You can add all kinds of TinyMCE premium features to support a CRM like Enhanced Tables, Merge Tags, Templates, Image Optimizer, and more. Try TinyMCE with all of these premium features free for 14 days, and use Tiny Docs AI to help you create the perfect rich text editor for your app’s requirements. And if you have questions that need to be answered by a human, send us a message.