Project

Edit Mode For People

Now we want to edit name, surname and e-mail of people:

Edit Person

First of all, we create the necessary DTOs to transfer people's id, name, surname and e-mail. Then we create the functions in PersonAppService for editing people:

public class GetPersonForEditOutput : EntityDto<int>
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public string EmailAddress { get; set; }
}

public class EditPersonInput : EntityDto<int>
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public string EmailAddress { get; set; }
}

Then we create mappers for the edit operations. Create PersonToGetPersonForEditOutputMapper.cs:

using Riok.Mapperly.Abstractions;

namespace Acme.PhoneBookDemo.PhoneBook.Mapper;

[Mapper]
public partial class PersonToGetPersonForEditOutputMapper
{
    public partial GetPersonForEditOutput Map(Person person);
}

Create EditPersonInputToPersonMapper.cs for updating existing persons:

using Riok.Mapperly.Abstractions;

namespace Acme.PhoneBookDemo.PhoneBook.Mapper;

[Mapper]
public partial class EditPersonInputToPersonMapper
{
    public partial void Map(EditPersonInput input, Person person);
}

Then use ObjectMapper in the PersonAppService methods:

public async Task<GetPersonForEditOutput> GetPersonForEdit(EntityDto input)
{
    var person = await _personRepository.GetAsync(input.Id);
    return ObjectMapper.Map<GetPersonForEditOutput>(person);
}

public async Task EditPerson(EditPersonInput input)
{
    var person = await _personRepository.GetAsync(input.Id);
    ObjectMapper.Map(input, person);
}

View

Create edit-person-modal.component.html:

<div
    bsModal
    #modal="bs-modal"
    (onShown)="onShown()"
    class="modal fade"
    tabindex="-1"
    role="dialog"
    aria-labelledby="modal"
    aria-hidden="true"
    [config]="{ backdrop: 'static' }">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            @if(active()){
                <form #editPersonForm="ngForm" novalidate (ngSubmit)="save()">
                    <div class="modal-header">
                        <h4 class="modal-title">{{ 'EditPerson' | localize }}</h4>
                        <button type="button" class="btn-close" aria-label="Close" (click)="close()"></button>
                    </div>

                    <div class="modal-body">
                        <div class="mb-3">
                            <label for="name" class="form-label">{{ 'Name' | localize }}</label>
                            <input
                                #nameInput
                                id="name"
                                type="text"
                                class="form-control"
                                name="name"
                                [(ngModel)]="person().name"
                                required
                                maxlength="32" />
                        </div>

                        <div class="mb-3">
                            <label for="surname" class="form-label">{{ 'Surname' | localize }}</label>
                            <input
                                id="surname"
                                type="text"
                                class="form-control"
                                name="surname"
                                [(ngModel)]="person().surname"
                                required
                                maxlength="32" />
                        </div>

                        <div class="mb-3">
                            <label for="emailAddress" class="form-label">{{ 'EmailAddress' | localize }}</label>
                            <input
                                id="emailAddress"
                                type="email"
                                class="form-control"
                                name="emailAddress"
                                [(ngModel)]="person().emailAddress"
                                required
                                maxlength="255"
                                pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{1,})+$" />
                        </div>
                    </div>

                    <div class="modal-footer">
                        <button type="button" class="btn btn-secondary" (click)="close()" [disabled]="saving()">
                            {{ 'Cancel' | localize }}
                        </button>
                        <button
                            type="submit"
                            class="btn btn-primary"
                            [disabled]="!editPersonForm.form.valid || saving()"
                            [buttonBusy]="saving()"
                            [busyText]="l('SavingWithThreeDot')">
                            <i class="fa fa-save"></i>
                            {{ 'Save' | localize }}
                        </button>
                    </div>
                </form>
            }
        </div>
    </div>
</div>

Add those lines to phonebook.component.html::

        
	// Other Code lines...	

<button
    class="btn btn-sm btn-icon btn-bg-light btn-active-color-warning me-2"
    (click)="editPerson(person.id)"
    title="{{ 'Edit' | localize }}">
    <i class="fa fa-edit"></i>
</button>
                
	// Other Code lines...
				
<createPersonModal #createPersonModal(modalSave)="getPeople()"></createPersonModal>
<editPersonModal #editPersonModal (modalSave)="getPeople()"></editPersonModal>

Add those lines to phonebook.component.ts::

@Component({
    selector: 'app-phone-book',
    templateUrl: './phonebook.component.html',
    animations: [appModuleAnimation()],
    imports: [
      //..
      EditPersonModalComponent
    ],
})
export class PhoneBookComponent extends AppComponentBase implements OnInit {
    //..
    editPersonModal = viewChild.required<EditPersonModalComponent>('editPersonModal');
    
    //..
    editPerson(personId: number): void {
        this.editPersonModal().show(personId);
    }
}

Controller

Create edit-person-modal.component.ts:

import { Component, ElementRef, inject, signal, viewChild, output } from '@angular/core';
import { ModalDirective, ModalModule } from 'ngx-bootstrap/modal';
import { PersonServiceProxy, GetPersonForEditOutput, EditPersonInput } from '@shared/service-proxies/service-proxies';
import { AppComponentBase } from '@shared/common/app-component-base';
import { finalize } from 'rxjs/operators';
import { FormsModule } from '@angular/forms';
import { LocalizePipe } from '@shared/common/pipes/localize.pipe';
import { ButtonBusyDirective } from '@shared/utils/button-busy.directive';
import { CommonModule } from '@angular/common';

@Component({
    selector: 'editPersonModal',
    templateUrl: './edit-person-modal.component.html',
    standalone: true,
    imports: [CommonModule, FormsModule, ModalModule, LocalizePipe, ButtonBusyDirective],
})
export class EditPersonModalComponent extends AppComponentBase {
    private readonly _personService = inject(PersonServiceProxy);

    modalSave = output<any>();

    modal = viewChild.required<ModalDirective>('modal');
    nameInput = viewChild<ElementRef>('nameInput');

    person = signal(new GetPersonForEditOutput());
    active = signal(false);
    saving = signal(false);

    constructor() {
        super();
    }

    show(id: number): void {
        this._personService.getPersonForEdit(id).subscribe((result) => {
            this.person.set(result);
            this.active.set(true);
            this.modal().show();
        });
    }

    onShown(): void {
        this.nameInput()?.nativeElement.focus();
    }

    save(): void {
        this.saving.set(true);

        const input = new EditPersonInput();
        const currentPerson = this.person();
        input.id = currentPerson.id;
        input.name = currentPerson.name;
        input.surname = currentPerson.surname;
        input.emailAddress = currentPerson.emailAddress;

        this._personService
            .editPerson(input)
            .pipe(finalize(() => this.saving.set(false)))
            .subscribe(() => {
                this.notify.success(this.l('SavedSuccessfully'));
                this.close();
                this.modalSave.emit(null);
            });
    }

    close(): void {
        this.modal().hide();
        this.active.set(false);
    }
}

Next

In this document