Skip to content

Latest commit

 

History

History
179 lines (150 loc) · 5 KB

step-9.md

File metadata and controls

179 lines (150 loc) · 5 KB

Quick Jump

Step 9 task:

In this step we're going to allow users to delete talks. Since this action can lead to loss of data, we'll implement a dialog that asks the user whether they're sure that they want to delete the talk.

To start things off, we'll add a new button to our card component and we'll adjust our layout to fit the button. First of all, let's add a new button next to the "Edit talk" button.

card.component.html

<mat-card-actions>
  <div class="author" *ngIf="author">By: {{author}}</div>
  <button mat-button (click)="delete.next()">DELETE</button>
  <button mat-button (click)="edit.next()">EDIT</button>
</mat-card-actions>

The CardComponent also needs a new Output for the delete event. card.component.ts

@Component(})
export class CardComponent {
  ...
  @Output() delete = new EventEmitter<void>();
}

At this point you'll notice that there isn't enough space to fit everything inside the mat-card-actions so we'll move the author text under the talk description.

card.component.html

<mat-card>
  ...
  <mat-card-content>
    {{text}}
    <div *ngIf="author">By: {{author}}</div>
    ...
  </mat-card-content>
  <mat-card-actions>
    <button mat-button (click)="delete.next()">DELETE</button>
    <button mat-button (click)="edit.next()">EDIT</button>
  </mat-card-actions>
</mat-card>

We also have adjust our styling slightly so that the buttons are aligned towards the end of the mat-card-actions and we can remove the .author styles since we won't need them anymore.

card.component.scss

.mat-card-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
}

// Delete this rule completely, it's not used anymore.
.author {
  font-size: 14px;
  margin-left: 8px;
}

Now we can move onto creating the dialog that asks the user to confirm. We'll follow the same pattern as with the edit dialog, however we can simplify it a bit since the dialog only needs two buttons. We need to create the following files:

  • src/app/delete-talk/delete-talk.component.ts
  • src/app/delete-talk/delete-talk.component.html
  • src/app/delete-talk/delete-talk.component.scss

Once we've created all the files, we can declare our simple dialog component. It won't have much logic, besides exposing the talk that is currently being deleted.

delete-talk.component.ts

import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material';
import { Talk } from '../data.service';

@Component({
  selector: 'ng-trello-delete-talk',
  templateUrl: './delete-talk.component.html',
  styleUrls: ['./delete-talk.component.scss'],
})
export class DeleteTalkComponent {
  constructor(@Inject(MAT_DIALOG_DATA) public talk: Talk) {}
}

For the dialog's template, we only need a couple of buttons. Note the cdkFocusInitial attribute on the "Delete" button. It instructs the CDK where to place the user's focus when they open the dialog. Also note that we use the mat-dialog-close directive which allows us to close the dialog declaratively, rather than having to do so through the component.

delete-talk.component.html

Are you sure that you want to delete "{{talk.text}}"?

<mat-dialog-actions align="end">
  <button mat-button [mat-dialog-close]="false">Cancel</button>
  <button cdkFocusInitial mat-button [mat-dialog-close]="true">Delete</button>
</mat-dialog-actions>

To finish things up in the dialog, we can add some styling to make the buttons consistent with the rest of the app.

delete-talk.component.scss

.mat-button {
  text-transform: uppercase;
}

Once our dialog is done, we need to declare it inside the AppModule.

app.module.ts

import { DeleteTalkComponent } from './delete-talk/delete-talk.component';

@NgModule({
  declarations: [
    ...
    DeleteTalkComponent,
  ],
  ...
  entryComponents: [EditTalkComponent, DeleteTalkComponent],
})
export class AppModule { }

Now that our dialog is ready to use, we can wrap everything up by hooking it up in the view.

app.component.html

<ng-trello-card
  ...
  (delete)="deleteTalk(talk, track)"></ng-trello-card>

Finally, we have to implement the deleteTalk method which takes in the talk that we want to delete and the track that it belongs to.

app.component.ts

import { DeleteTalkComponent } from './delete-talk/delete-talk.component';

@Component()
export class AppComponent {
  ...

  deleteTalk(talk: Talk, track: Track) {
    // Open a dialog
    this._dialog.open(DeleteTalkComponent, {data: talk, width: '500px'})
      .afterClosed()
      .subscribe(response => {
        // Wait for it to close and delete the talk if the user agreed.
        if (response) {
          track.talks.splice(track.talks.indexOf(talk), 1);
        }
      });
  }
}

Continue to the next step