Websites with Angular and Less CSS tutorials
10. The Add Recipe component
av_timer4 minute read

So what you're saying is I can add my own recipes with very little concern to health and safety?

  1. Topics of discussion
  2. Configuring the tinyMCE plugin
  3. The Add Recipe component

1. Topics of discussion

In this tutorial, we will be introducing one final plugin as we create a component that allows us to add a recipe to our website. So, let's have some fun.

2. Installing and configuring the tinyMCE plugin

TinyMCE is a really useful plugin that allows you to format your text, in a similar fashion to a Word document. Behind the scenes it uses html to format it. In order to install it, you need to run the following command in a command prompt opened in the recipe-site folder:

npm install --save @tinymce/tinymce-angular

Now, in our content.module.ts file we need to import the EditorModule module. Add the following line of code at the start of the file:

import { EditorModule } from '@tinymce/tinymce-angular';

I've added the import line here because Visual Studio Code sometimes has problems with packages that start with @. Anyhow, make sure you add EditorModule to your imports array and you should be done. And while we're at it, in the next section we'll be using something called ngModel, which requires you to import the FormsModule in this file as well.

We'll get to actually using the tinyMCE functionality in the next section.

3. The Add Recipe component

We now need to create a new component and a new route, that will allow us to upload our recipe to the website. For this, run the following command:

ng g c components/content/AddRecipe -m=Content --export

Let's also add a route for this in app-routing.module.ts:

{
  path: 'add',
  component: AddRecipeComponent
}

And let's add a new element in our app-navigation.component.html file:

<a class="navigation-item" mat-list-item routerLink="/add" routerLinkActive="active">
  <mat-icon class="material-icons">add_circle</mat-icon><span class="navigation-item-label">Add Recipe</span>
</a>

Now, in the content.service.ts file, add the following method:

public saveRecipe(recipe: Recipe): void {
  console.log(recipe);
  alert("Recipe Saved!");
}

Nothing much happens in that method, though we do log our recipe to the console. When we run the code, I'll tell you how you can view that.

Let's write some logic in our add-recipe.component.ts file:

import { Component, OnInit } from '@angular/core';
import { ContentService } from '../content.service';
import { Recipe } from '../model/recipe-details.model';

@Component({
  selector: 'app-add-recipe',
  templateUrl: './add-recipe.component.html',
  styleUrls: ['./add-recipe.component.less']
})
export class AddRecipeComponent implements OnInit {

  recipe: Recipe;
  constructor(private contentService: ContentService) { }

  public saveRecipe(): void {
    const slug = this.recipe.name.replace(" ", "-").toLowerCase();
    this.recipe.slug = slug;
    this.contentService.saveRecipe(this.recipe);
  }

  public tinymceInit(): any {
    return {
      plugins: "advlist lists image media",
      toolbar: 'styleselect | bold italic underline | alignleft aligncenter alignright alignjustify | image media | bullist numlist outdent indent',
    };
  }

  ngOnInit() {
    this.recipe = new Recipe();
  }
}

What we do here is instantiate a Recipe attribute using the new operator. This is to avoid errors when using said attribute in the html. We also have a method which we will use to save the recipe. The const keyword refers to a variable whose value cannot be changed after it is given to it. The slug is obtained by taking the recipe name, replacing every space with the - sign and then making it all lower case. After we do those operations, we call the saveRecipe method from the ContentService class.

We also have a tinymceInit() method, which we will use in our template in order to...you guessed it...initialize tinyMce. We supply some plugins, which we imported in our angular.json file. We also supply the toolbar content and format. The | sign is used to tell tinyMce to insert a separator. All this will become clear when we will actually visualize the tinyMCE element.

With this in mind, let's move on to the add-recipe.component.html file:

<div class="container container-fluid">
  <div class="row">
    <label class="col-3">Name</label>
    <div class="col-9">
      <input type="text" class="form-control" [(ngModel)]="recipe.name" />
    </div>
  </div>
  <div class="row">
    <label class="col-3">Recipe</label>
    <div class="col-9">
      <editor id="recipe" name="recipe" [(ngModel)]="recipe.recipe" [init]="tinymceInit()"></editor>
    </div>
  </div>
  <div class="row">
    <div class="col-12 text-right">
      <button class="btn btn-sm save-button" (click)="saveRecipe()">Save</button>
    </div>
  </div>
</div>

The first thing we need to discuss is the whole [(ngModel)] directive. This directive is used to link the value from the input element to the name attribute of the recipe component attribute. What that means is that when we modify the input text value, the value for the name attribute is also changed accordingly. This goes both ways, meaning that if you modified the value inside the ts file, it would be also modified in the input element. This is what is known as a two-way binding, where modifying a value in one place also modifies it in the other as well.

The other thing we do is initialize the tinymce editor using the method we created in the component. When you run the app, you may receive an info tab saying the app is not registered or something. Just ignore it. And once tinyMCE is initialized, you will be able to see the toolbar with all the elements defined in the init method, separated by that vertical line I mentioned earlier.

Finally, let's add some styling to the save button:

.save-button {
  background-color: #062739;
  color: #fff;
}

Now, when you build and run the app, you can visit the Add Recipe page. And since I promised you we will view the recipe, when you enter the Add Recipe page, press the F12 key. It should open what is known as Developer Tools. If it is docked on the right, you can use the ... button to dock it to the bottom. And once you enter some data in the fields from the page and press Save, you will be able to see the recipe logged in the Console tab in Developer Tools.

And that's about it for this tutorial. In the next one, we will add two final components to our app. See you then.

COMMENTS
No comments yet...