Conectar componentes com eventos

Objetivos de aprendizagem

Após concluir esta unidade, você estará apto a:
  • Definir eventos personalizados para seus aplicativos.
  • Criar e acionar eventos de um controlador de componentes.
  • Criar manipuladores de ação para capturar e tratar de eventos enviados por outros componentes.
  • Refatorar um componente grande em componentes menores.

Conectar componentes com eventos

Nesta unidade, vamos cuidar da última funcionalidade não concluída em nosso querido aplicativo de despesas: a caixa de seleção Reembolsado?. Provavelmente, você está pensando que implementar uma caixa de seleção deve ser um tópico curto. Nós bem que poderíamos pegar alguns atalhos e fazer deste um tópico muito curto.

Mas essa unidade, além de fazer funcionar a caixa de seleção, trata de remover todos os atalhos que já tomamos. Nesta unidade vamos “Fazer Certo” o tempo todo. O que, em alguns lugares, quer dizer refazer o trabalho que fizemos anteriormente.

Antes de começarmos, vamos conversar sobre os atalhos que tomamos, o Jeito Certo e por que o Jeito Certo é (um pouco) mais difícil, mas também melhor.

Composição e decomposição

Se você olhar para nosso pequeno aplicativo de despesas na forma do código-fonte e listar os artefatos de código separadamente, terá mais ou menos o seguinte:

  • componente expenses
    • expenses.cmp
    • expensesController.js
    • expensesHelper.js
  • componente expensesList
    • expensesList.cmp
  • componente expenseItem
    • expenseItem.cmp
  • ExpensesController (lado do servidor)
    • ExpensesController.apex

Veja como tudo se encaixa, com os eventos createExpense e updateExpense que você conectará mais tarde.

O aplicativo de despesas é feito de diversos componentes menores.

Mas, se olhar o aplicativo na tela, o que você vê? O que você deveria ver, e o que você verá (para onde quer que você olhe), é que o aplicativo se decompõe em vários outros componentes. Você verá que é possível decompor o aplicativo em partes menores, ainda mais do que já fizemos até agora. No mínimo, esperamos que você veja que o formulário Adicionar despesas realmente deve ser um componente próprio separado. (É por isso que desenhamos uma caixa em torno dele na interface de usuário!)

Por que não fizemos do formulário um componente separado? Não ter feito isso foi, de longe, o maior atalho que pegamos ao longo deste módulo. É pior que a embrulhada que chamamos de “lamentável”, em termos de design de software. A maneira certa de criar um aplicativo de componentes do Lightning é criar componentes independentes e fazer uma composição com eles para criar recursos novos de mais alto nível. Por que não usamos essa abordagem?

Tomamos o atalho, mantivemos o formulário Adicionar despesas dentro do componente principal expenses porque ele guardava o atributo principal de componente de matriz expenses e o código do controlador que o afetava no mesmo componente. Queríamos que a função auxiliar createExpense() pudesse tocar na matriz expenses diretamente. Se movêssemos o formulário Adicionar despesas para um componente separado, isso não teria sido possível.

Por que não? Já falamos um pouco do motivo antes, mas queremos realmente aprofundar isso agora. Supostamente, os componentes do Lightning devem ser autossuficientes. Eles são elementos autônomos que encapsulam toda a funcionalidade essencial. Um componente não deve alcançar outro componente, mesmo um componente secundário, e alterar o que está dentro.

Existem duas maneiras principais de interagir com ou afetar outro componente. A primeira, é uma que já vimos e fizemos bastante: definir atributos na marca do componente. Os atributos públicos de um componente são parte de sua API.

A segunda maneira de interagir com um componente é por eventos. Assim como os atributos, os componentes declaram os eventos enviados e os eventos de que eles podem tratar. E assim como os atributos, esses eventos públicos são parte da API pública do componente. Já usamos e tratamos de eventos, mas os eventos têm se escondido por trás de alguns recursos de conveniência. Nesta unidade, vamos trazer os eventos à tona e criar alguns por conta própria.

Novamente, a metáfora Conectando um circuito

Esses dois mecanismos, atributos e eventos, são os “soquetes” da API, as maneiras pelas quais você conecta os componentes para formar circuitos completos. Eventos também são, nos bastidores, elétrons que fluem pelo circuito. Mas isso é uma das coisas em que os eventos diferem dos atributos.

Ao definir o atributo onclick em um <lightning:button> para um manipulador de ações em um controlador do componente, você cria um relacionamento direto entre esses dois componentes. Eles estão vinculados e, embora usem APIs públicas para permanecerem independentes, ainda estão acoplados.

Os eventos são diferentes. Componentes não enviam eventos para outro componente. Os eventos não funcionam assim. Os componentes transmitem eventos de um tipo específico. Se existe um componente que responde àquele tipo de evento e esse componente “ouve” seu evento, ele atuará.

Você pode pensar na diferença entre atributos e eventos como a diferença entre circuitos com fio e circuitos sem fio. E não estamos falando de telefones sem fio aqui. Um componente não obtém o “número” de outro componente e o chama. Isso seria um atributo. Não, os eventos são como transmissões sem fio. Seu componente pega o rádio e envia uma mensagem. Tem alguém aí com o rádio ligado e sintonizado na frequência certa? Seu componente não tem como saber e, portanto, você deve escrever seus componentes de maneira que seja OK se ninguém ouvir os eventos transmitidos. (Ou seja, eles podem não ser ouvidos, mas nada deixará de funcionar.)

Enviar um evento de um componente

OK, chega de teoria. Vamos fazer algo específico com nosso aplicativo e ver como os eventos funcionam em código. Vamos começar implementando a caixa de seleção Reembolsado?. Em seguida, vamos pegar o que aprendemos com isso e usar para refatorar o formulário Adicionar despesas em seu próprio componente, da maneira concebida pelo Grande Engenheiro.

Primeiro, vamos nos concentrar no manipulador de cliques em <lightning:input> para o campo Reimbursed__c.

<lightning:input type="toggle"
            label="Reimbursed?"
            name="reimbursed"
            class="slds-p-around_small"
            checked="{!v.expense.Reimbursed__c}"
            messageToggleActive="Yes"
            messageToggleInactive="No"
            onchange="{!c.clickReimbursed}"/>

Antes de nos aprofundarmos no manipulador de cliques, vamos dar um passo atrás para ver o que <lightning:input> tem a oferecer. type ="toggle" é realmente uma caixa de seleção com um design de botão de alternância. class permite que você aplique estilo CSS personalizado ou use utilitários do SLDS. messageToggleActive e messageToggleInactive fornecem rótulos personalizados para as posições marcadas e desmarcadas. Esses atributos úteis são apenas alguns dentre as várias opções em <lightning:input>. Por fim, o atributo onchange de <lightning:input> facilita a conexão do botão de alternância com um manipulador de ações que atualiza o registro quando você desliza para a direita (marcado) ou para a esquerda (desmarcado).

Agora, vamos pensar no que acontece quando a opção está marcada ou desmarcada. Baseado no código que escrevemos para criar uma nova despesa, a atualização de uma despesa provavelmente se parece com isto:

  1. Obter o item expense que mudou.
  2. Criar uma ação de servidor para atualizar o registro de despesa subjacente.
  3. Empacotar expense na ação.
  4. Configurar um retorno de chamada para tratar da resposta.
  5. Acionar a ação, enviando a solicitação ao servidor.
  6. Quando a resposta chega e o retorno de chamada é executado, atualizar o atributo expenses.

Hum, que atributo expenses? Veja a marcação de nosso componente novamente. Não há expenses, apenas uma única expense. Hum, OK, esse componente serve apenas para um item. Existe um atributo expenses no componente expensesList... mas não é nem o expenses “real”. O real é um atributo de componente no componente expenses de nível superior. Hum.

Existe um component.get("v.parent")? Ou teria de ser component.get("v.parent").get("v.parent"), algo que nos deixe obter uma referência para o pai de nosso pai e definir expenses lá?

Por favor, pare Estarão lá.

Os componentes não alcançam outros componentes e definem valores neles. Não há como dizer: “Olá, avô, vou atualizar expenses.” Os componentes ficam em seus devidos lugares. Quando um componente quer que um componente ancestral altere algo, ele solicita. Educadamente. Enviando um evento.

Agora vem a parte interessante. Enviar um evento se parece com tratar da atualização diretamente. Eis o código para o manipulador clickReimbursed.

({
    clickReimbursed: function(component, event, helper) {
        let expense = component.get("v.expense");
        let updateEvent = component.getEvent("updateExpense");
        updateEvent.setParams({ "expense": expense });
        updateEvent.fire();
    }
})

Opa! É muito simples! E se parece um pouco com o que vimos acima. O código anterior para clickReimbursed faz o seguinte:

  1. Obtém o expense que mudou.
  2. Cria um evento chamado updateExpense.
  3. Empacota expense na ação.
  4. Aciona o evento.

A parte do retorno de chamada está faltando, mas o resto é familiar. Mas o que vai tratar da chamada ao servidor e da resposta do servidor, e atualizar o atributo de matriz expenses principal? E, aliás, como sabemos a respeito desse evento updateExpense?

updateExpense é um evento personalizado, ou seja, um evento que criamos. É possível identificá-lo porque, diferentemente de obter uma ação de servidor, usamos component.getEvent() em vez de component.get(). Além disso, o que obtemos não tem provedor de valor; somente um nome. Definiremos esse evento em breve.

Agora, em relação ao que vai tratar da chamada ao servidor e da resposta, vejamos. Poderíamos implementar a solicitação do servidor e tratar da resposta diretamente aqui no componente expenseItem. Em seguida, enviaríamos um evento para reprocessar o que depende da matriz expenses. Essa seria uma escolha de design perfeitamente válida e manteríamos o componente expenseItem totalmente autossuficiente, o que é desejável.

No entanto, como veremos, o código para criar uma nova despesa e o código para atualizar uma despesa existente são muito semelhantes, tão semelhantes que preferimos evitar o código duplicado. Assim, a escolha de design que fizemos é enviar um evento updateExpense que será tratado pelo componente principal expenses. Mais tarde, quando refatorarmos nosso formulário, faremos o mesmo na criação de uma nova despesa.

Ao ter todos os componentes secundários delegando a responsabilidade sobre o tratamento de solicitações de servidores e o gerenciamento do atributo de matriz expenses, romperemos um pouco com o encapsulamento. Mas se você pensar nesses componentes secundários como os detalhes internos de implementação do componente expenses, sem problemas. O componente principal expenses é autossuficiente.

Você tem uma escolha: consolidação da lógica essencial ou encapsulamento. Você fará compensações nos componentes do Aura como faria em qualquer design de software. Mas lembre-se de documentar os detalhes.

Definir um evento

A primeira coisa a fazer é definir nosso evento personalizado. No Developer Console, selecione Arquivo | Novo | Evento do Lightning e chame o evento de “expensesItemUpdate”. Substitua o conteúdo padrão pela marcação a seguir.

<aura:event type="COMPONENT">
    <aura:attribute name="expense" type="Expense__c"/>
</aura:event>

Existem dois tipos de eventos: componente e aplicativo. Aqui, estamos usando um evento de componente, já que queremos que um componente ancestral capture e trate do evento. Um ancestral é um componente “acima” dele na hierarquia de componentes. Se quiséssemos um tipo de evento de “transmissão geral”, em que qualquer componente pudesse recebê-lo, usaríamos um evento de aplicativo.

As diferenças completas e o uso correto do aplicativo em relação aos eventos de componente não é algo que poderemos abordar aqui. É um tópico mais avançado e com detalhes bem complicados que tirariam a nossa atenção do objetivo deste módulo. Quando você estiver pronto para mais, os Recursos poderão ajudá-lo.

Outra coisa a se notar sobre o evento é como a definição é compacta. Nomeamos o evento quando ele foi criado, expensesItemUpdate, e sua marcação é uma marca de início e de fim <aura:event> e uma marca <aura:attribute>. Um atributo do evento descreve a carga que ele pode carregar. No manipulador de ação clickReimbursed, definimos a carga com uma chamada para setParams(). Aqui, na definição do evento, vemos como o parâmetro do evento é definido e que não há outros parâmetros válidos.

Isso é basicamente tudo o que precisa ser dito sobre definição de eventos. Você não adiciona detalhes de implementação ou comportamento aos próprios eventos. Eles são apenas pacotes. Na verdade, alguns eventos não têm parâmetros. Eles são apenas mensagens. “Isso aconteceu!” Todo o comportamento sobre o que fazer se “isso” acontecer é definido nos componentes que enviam e recebem o evento.

Enviar um evento

Já vimos como efetivamente acionar um evento, no manipulador de ação clickReimbursed. Mas, para que ele funcione, precisamos fazer mais uma coisa, que é registrar o evento. Adicione essa linha de marcação ao componente expenseItem, logo abaixo das suas definições de atributo.

    <aura:registerEvent name="updateExpense" type="c:expensesItemUpdate"/>

Essa marcação diz que nosso componente aciona um evento, chamado “updateExpense”, do tipo “c:expensesItemUpdate”. Mas “expensesItemUpdate” não era o nome do evento quando o definimos? E o que aconteceu com os tipos de eventos de componente ou aplicativo?

Você tem razão em achar tudo um pouco confuso. É uma mudança um pouco drástica. Talvez ajude pensar em “aplicativo” e “componente” como tipos de evento de estrutura de componentes do Aura, e os tipos que vêm dos nomes dos eventos definidos por você como tipos de evento personalizados, ou tipos de estrutura de evento. Ou seja, ao definir um evento, você define um formato de pacote. Quando você registra para enviar um evento, declara o formato que ele usa.

O processo de definir e registrar um evento ainda pode parecer um pouco estranho. Vamos dar uma olhada. Aqui, em expenseItem, vamos enviar um evento chamado updateExpense. Depois, em expenseForm, vamos enviar um evento chamado createExpense. Ambos os eventos precisam incluir uma despesa para ser salva no servidor. E ambos usam o tipo de evento c:expensesItemUpdate, ou formato de pacote, para enviar seus eventos.

No lado receptor, nosso principal componente expenses se registrará para tratar de ambos os eventos. Embora a chamada do servidor seja a mesma, as atualizações da interface de usuário são ligeiramente diferentes. Como é que expenses sabe se deve criar ou atualizar a despesa no pacote c:expensesItemUpdate? Pelo nome do evento enviado.

Entender essa diferença aqui, e como um evento pode ser usado para várias finalidades, é um momento “Eureca!” no aprendizado sobre componentes do Lightning. Se você ainda não chegou lá, provavelmente, chegará quando vir o resto do código.

Antes de prosseguirmos com o tratamento de eventos, vamos resumir o que é necessário para enviá-los.

  1. Defina um evento personalizado criando um evento do Lightning e dando a ele um nome e atributos.
  2. Registre seu componente para enviar esses eventos escolhendo um tipo de evento personalizado e dando um nome ao uso específico desse tipo.
  3. Acione o evento no código do controlador (ou do auxiliar):
    1. Usar component.getEvent() para criar uma instância de evento específica.
    2. Enviar um evento com fire().

Se você implementou todo o código que acabamos de ver, pode testá-lo. Recarregue seu aplicativo e marque e desmarque uma caixa de seleção Reembolsado? algumas vezes. Se você ignorou alguma etapa, receberá uma mensagem de erro. Se for o caso, verifique seu trabalho novamente. Se você fez tudo certinho... a despesa muda de cor para mostrar o status de Reembolsado?, como se esperava!

Esse comportamento existia mesmo antes de iniciarmos esta unidade. Esse é o efeito do componente <lightning:input> com value="{!v.expense.Reimbursed__c}" definido. Ao alternar o botão, a versão local de expense será atualizada. Mas essa mudança não está sendo enviada para o servidor. Se você olhar o registro da despesa no Salesforce ou recarregar o aplicativo, não verá a mudança.

Por que não? Só fizemos metade do trabalho para criar um circuito completo para nosso evento. Temos que concluir a conexão do circuito criando o manipulador de evento no outro lado. Esse manipulador de evento tratará de enviar a mudança para o servidor e de tornar a atualização durável.

Manipular um evento

A habilitação do componente expenseItem para enviar um evento exigiu três etapas. A habilitação do componente expenses para receber e tratar desses eventos exige três etapas em paralelo.

  1. Definir um evento personalizado. Já fizemos isso porque expenseItem está enviando o mesmo evento personalizado que expenses está recebendo.
  2. Registrar o componente para tratar do evento. Isso mapeia o evento para um manipulador de ação.
  3. Tratar do evento efetivamente em um manipulador de ação.

Já que concluímos a etapa 1, vamos passar imediatamente para a etapa 2 e registrar expenses para receber e tratar do evento updateExpense. Assim como o registro para enviar um evento, o registro para tratar de um evento é composto de uma única linha de marcação, que pode ser adicionada ao componente expenses logo depois do manipulador init.

     <aura:handler name="updateExpense" event="c:expensesItemUpdate"
        action="{!c.handleUpdateExpense}"/>

Assim como o manipulador init, ele usa a marca <aura:handler> e tem um atributo action que define o manipulador de ação do controlador para o evento. Da mesma forma que você registrou o evento em expenseItem, aqui você define o nome e o tipo do evento; mas observe o uso do atributo event com um nome muito mais sensato para o tipo.

Melhor dizendo, não tem muita coisa aqui que você já não tenha visto. A novidade, específica do tratamento de eventos personalizados, é a combinação dos atributos e saber como esse “soquete” destinatário em expenses corresponde ao “soquete” remetente em expenseItem.

Isso conclui a parte sobre conexões para fazer tudo funcionar. Só falta agora escrever efetivamente o manipulador de ação!

Vamos começar com o manipulador de ação handleUpdateExpense. Eis o código, e não deixe de colocá-lo logo abaixo do manipulador de ações clickCreate.

    handleUpdateExpense: function(component, event, helper) {
        let updatedExp = event.getParam("expense");
        helper.updateExpense(component, updatedExp);
    }

Hum. Interessante. Exceto pela verificação de validação e pela função auxiliar específica à qual estamos delegando o trabalho, parece que esse manipulador de ação é o mesmo que handleCreateExpense.

Agora, vamos adicionar a função auxiliar updateExpense. Assim como fizemos com o manipulador de ação, coloque esse código logo abaixo da função auxiliar createExpense.

    updateExpense: function(component, expense) {
        let action = component.get("c.saveExpense");
        action.setParams({
            "expense": expense
        });
        action.setCallback(this, function(response){
            let state = response.getState();
            if (state === "SUCCESS") {
                // do nothing!
            }
        });
        $A.enqueueAction(action);
    },

Duas coisas que você pode perceber de imediato. Primeiro, tirando as especificidades do retorno de chamada, o método auxiliar updateExpense é idêntico ao método auxiliar createExpense. Isso cheira a oportunidade.

Segundo, sobre as especificidades do retorno de chamada. E aí? Como é que pode a coisa certa ser fazer nada?

Pare para pensar um instante. Antes, quando estávamos testando o envio do evento (ou até antes), vimos que a cor do componente expenseItem mudava ao marcar e desmarcar a caixa de seleção Reembolsado?. Lembra-se da explicação? A cópia local do registro de despesa já está atualizada! Ou seja, pelo menos por agora, quando o servidor nos diz que teve êxito ao atualizar a versão, não precisamos fazer nada.

Observe que esse código só lida com o caso quando o servidor tem êxito ao atualizar o registro de despesa. Teríamos certamente algum trabalho pela frente se houvesse erro. Digamos que o departamento de contabilidade tenha marcado essa despesa como não reembolsável, impossibilitando a definição desse campo como true. Mas isso, como dizem, é assunto para outro dia.

Refatorar as funções auxiliares

Vamos voltar para a oportunidade que vimos de fatorar trechos de código comuns. As duas funções auxiliares são idênticas, exceto quanto ao retorno de chamada. Assim, vamos criar uma nova função mais generalizada que usa callback como parâmetro.

    saveExpense: function(component, expense, callback) {
        let action = component.get("c.saveExpense");
        action.setParams({
            "expense": expense
        });
        if (callback) {
            action.setCallback(this, callback);
        }
        $A.enqueueAction(action);
    },

O parâmetro callback é opcional. Se estiver lá, nós o transmitiremos para action. Simples. E agora, podemos reduzir nossas funções auxiliares específicas para o evento ao código a seguir.

    createExpense: function(component, expense) {
        this.saveExpense(component, expense, function(response){
            let state = response.getState();
            if (state === "SUCCESS") {
                let expenses = component.get("v.expenses");
                expenses.push(response.getReturnValue());
                component.set("v.expenses", expenses);
            }
        });
    },
    updateExpense: function(component, expense) {
        this.saveExpense(component, expense);
    },

createExpense é apenas um pouco mais curto, mas está focado exclusivamente no que fazer quando a resposta volta (o retorno de chamada). E, nossa, updateExpense tem uma linha!

Refatorar o formulário Adicionar despesas

O breve exercício de refatoração foi tão reconfortante e o uso de eventos foi tão (desculpe) empolgante que vamos fazer tudo de novo, mas em maior escala. Rufem os tambores!

A próxima tarefa envolve a extração do formulário Adicionar despesas do componente expenses e sua mudança para um novo componente próprio. A extração da marcação do formulário é fácil: basta copiar e colar. Mas o que mais se move com ele? Antes de começarmos a movimentar peças por aí ao deus-dará, vamos pensar no que se move e no que não muda.

No projeto atual, o manipulador de ações do formulário, clickCreate, lida com a validação da entrada enviando a solicitação ao servidor e atualizando elementos da interface de usuário e de estado local. O formulário continuará precisando de um manipulador de ação e ainda deve lidar com a validação do formulário. Mas queremos deixar o resto para trás, já que vamos manter a lógica de solicitação de nosso servidor consolidada no componente expenses.

Assim, temos de separar as coisas um pouquinho (mas só um pouquinho!). Nosso plano é começar movendo a marcação do formulário e depois só mover o mínimo possível para que ele funcione direito. Vamos refatorar ambos os componentes para que se comuniquem por meio de eventos, em vez de ser por acesso direto ao atributo de componente de matriz expenses.

Vamos começar!

No componente principal expenses, selecione tudo entre os dois comentários <!-- CREATE NEW EXPENSE -->, incluindo os próprios comentários inicial e final. Corte isso e coloque em sua área de transferência. (Sim, corte. Somos intensos.)

Crie um novo componente do Aura e chame-o de “expenseForm”. Cole a marcação do formulário Adicionar despesas copiada no novo componente, entre as marcas <aura:component>.

Volte para o componente expenses. Adicione o novo componente expenseForm à marcação. Essa seção de expenses deve se parecer com o que se segue.

    <!-- NEW EXPENSE FORM -->
    <lightning:layout >
        <lightning:layoutItem padding="around-small" size="6">
            <c:expenseForm/>
        </lightning:layoutItem>
    </lightning:layout>

Agora, você pode recarregar seu aplicativo para ver as alterações. Não deve haver alterações visíveis. Mas, como é de se esperar, o botão Criar despesa não funcionará mais.

Vamos passar rapidamente pela parte restante de mover as coisas.

Em seguida, mova o atributo newExpense do componente expenses para a marcação do componente expenseForm. Isso é usado nos campos do formulário e, portanto, precisa estar no componente do formulário. Ele se move sem a necessidade de alterações; corte de um e cole no outro.

No componente expenseForm, crie os recursos de controlador e de auxiliar.

Mova o manipulador de ações clickCreate do controlador expenses para o controlador expenseForm. O botão está no componente do formulário e, portanto, o manipulador de ação do botão precisa estar nele também. Acredite, isso também não precisa de alterações. (Você já deve ter notado um padrão aqui.)

Agora, precisamos fazer algumas mudanças de verdade. Mas elas soarão familiares porque estamos apenas adicionando o envio de eventos, como fizemos antes para expenseItem. E expenseItem, você deve se lembrar, também envia um evento com uma carga expense, que é tratada pelo componente expenses.

No auxiliar expenseForm, crie a função createExpense.

    createExpense: function(component, newExpense) {
        let createEvent = component.getEvent("createExpense");
        createEvent.setParams({ "expense": newExpense });
        createEvent.fire();
    },

Isso se parece muito com o manipulador de ação clickReimbursed em expenseItem.

Se um componente vai enviar um evento, ele precisa registrar esse evento. Adicione o que se segue à marcação do componente expenseForm, logo abaixo do atributo newExpense.

    <aura:registerEvent name="createExpense" type="c:expensesItemUpdate"/>

Agora, concluímos todo o trabalho para implementar o componente expenseForm. Você deve conseguir recarregar o aplicativo e o formulário “funcionará” no sentido de não haver erros, e você deverá conseguir ver as mensagens de formulário adequadas quando digitar dados inválidos. Se estiver usando o Salesforce Lightning Inspector, poderá até ver o evento expensesItemUpdate sendo acionado. Só falta tratar dele.

Antes de tratar do evento, observe como foi fácil fazer a refatoração. A maior parte do código não teve de ser mudada. Foram seis linhas de código novo no total e marcação nas etapas anteriores. Você não deve estar acostumado com esse trabalho agora, mas faça-o algumas vezes e perceberá que está apenas movimentando um pouco de código.

OK, vamos concluir. O expenseForm aciona o evento createExpense, mas também precisamos que o componente expenses o capture. Primeiro, registramos o manipulador de evento createExpense e o conectamos ao manipulador de ação handleCreateExpense. Mais uma vez, isso é apenas uma linha de marcação. Adicione essa linha imediatamente acima ou abaixo do manipulador de evento updateExpense.

    <aura:handler name="createExpense" event="c:expensesItemUpdate"
        action="{!c.handleCreateExpense}"/>

Finalmente, como a última etapa, crie o manipulador de ação handleCreateExpense no controlador expenses. Adicione esse código imediatamente acima ou abaixo do manipulador de ação handleUpdateExpense.

    handleCreateExpense: function(component, event, helper) {
        let newExpense = event.getParam("expense");
        helper.createExpense(component, newExpense);
    },

É simples assim. Todo o trabalho é delegado à função auxiliar createExpense e ela não foi alterada nem se moveu. Nosso manipulador de ação handleCreateExpense está lá para conectar as coisas certas.

Com isso, concluímos a demonstração de como associar componentes, de forma geral, usando eventos. Crie e acione o evento em um componente, capture e trate dele em outro. Circuitos sem fio!

Lição de bônus – pequenos aprimoramentos visuais

Antes de caminharmos em direção ao pôr do sol, ou melhor, antes de enfrentarmos o desafio, vejamos um simples aprimoramento visual.

Gostaríamos de aprimorar um pouquinho o layout do aplicativo adicionando alguns componentes de contêiner. Isso também dá a você a oportunidade de ver o componente expense completo depois de todas as nossas alterações. No componente expense, substitua a marcação expensesList pelo indicado a seguir.

<lightning:layout>
    <lightning:layoutItem padding="around-small" size="6">
        <c:expensesList expenses="{!v.expenses}"/>
    </lightning:layoutItem>
    <lightning:layoutItem padding="around-small" size="6">
        Put something cool here
    </lightning:layoutItem>
</lightning:layout>

Os efeitos das mudanças são para adicionar algumas margens, efetuar preenchimentos e estreitar a lista de despesas. O layout dá espaço para se colocar algo à direita. Na próxima unidade, vamos sugerir alguns exercícios para você fazer sozinho.

Continue a aprender de graça!
Inscreva-se em uma conta para continuar.
O que você ganha com isso?
  • Receba recomendações personalizadas para suas metas de carreira
  • Pratique suas habilidades com desafios práticos e testes
  • Monitore e compartilhe seu progresso com os empregadores
  • Conecte-se a orientação e oportunidades de carreira