Criando sua segunda aplicação com Angular

Criando novas tarefas

Tudo está indo bem, mas precisamos começar a dar um jeito nesses dados hard-coded. Vamos implementando primeiro a funcionalidade de criar novas tarefas.

Adicione o event binding (click)="onAdicionarTarefa()" ao botão + das listas, e implemente o método onAdicionarTarefa no componente Lista de Tarefas, da seguinte forma:

<div class="card bg-light shadow-sm">
  <div class="card-header bg-primary text-white d-flex align-items-center">
    ...
    <button class="btn btn-sm text-white" (click)="onAdicionarTarefa()">
      <i class="fa fa-lg fa-plus"></i>
    </button>
  </div>

  ...
</div>
export class ListaDeTarefasComponent {
  @Input() lista: ListaDeTarefas;

  onAdicionarTarefa() {
    const novaTarefa = { nome: '', concluida: false };
    this.lista.tarefas = [novaTarefa, ...this.lista.tarefas];
  }
}

Isto fará com que a nova tarefa seja criada no topo da lista. A possibilidade de reordenar as tarefas seria de extrema utilidade aqui, mas, embora não tão complexa, estaria muito ainda além do nível de detalhamento deste tutorial.

Foco no nome da tarefa

Algo que podemos fazer para melhorar um pouco a usabilidade é atribuir o foco do navegador ao nome da tarefa recém-criada, facilitando sua edição. Aliás, é justamente por isso que estamos utilizando o atributo contenteditable="true" nos nomes das tarefas e das listas.

Para isso, vamos utilizar um truque simples: se, ao exibir o componente da tarefa, seu nome estiver vazio (que é o caso para uma nova tarefa), atribuiremos o foco ao elemento correspondente.

Comece marcando o elemento <span> do nome da tarefa com a variável de template #nome, no template do componente Tarefa. Em seguida, utilize o decorator @ViewChild para adquirir uma referência ao elemento marcado. Por fim, implemente o método ngAfterViewInit, da interface AfterViewInit, atribuindo o foco ao elemento, caso a tarefa esteja com o nome vazio.

<div class="list-group-item d-flex align-items-center pl-3" [class.text-muted]="tarefa.concluida">
  ...

  <span class="flex-grow-1" contenteditable="true" #nome> {{ tarefa.nome }} </span>

  ...
</div>
export class TarefaComponent implements AfterViewInit {
  @Input() tarefa: Tarefa;

  @ViewChild('nome') nomeRef: ElementRef;

  ngAfterViewInit() {
    if (!this.tarefa.nome) {
      this.nomeRef.nativeElement.focus();
    }
  }
}

Excelente! Agora, após clicar no botão +, já podemos começar a digitar o nome da tarefa.

Porém, existem ainda dois problemas: 1) eu gostaria que ao pressionar enter ou esc, concluíssemos a edição do nome e 2) mesmo digitando um nome para a tarefa, essa alteração acontece somente no DOM, não se refletindo para o estado da aplicação.

Vamos resolver isso a seguir, enquanto implementamos a funcionalidade de editar o nome de uma tarefa.

Deixar uma resposta