Comunicação entre iframes
Tags: iframe, comunicação, postmessage, chat
Published: 2019-10-07 13:56:15

---
title: Comunicação entre iframes
published: true
description: Iframes ainda estão vivos e tem diversas finalidades. Vamos descobrir como se comunicar e receber dados de dentro deles.
tags: iframe, comunicação, postmessage, chat
---

- [Introdução](#introduction)
- [Problema] (#problem)
- [window.postMessage] (#postMessage)
- [Recebendo o evento] (#from-iframe)
- [Enviando dado para o iframe] (#to-iframe)
- [Conclusão] (#conclusion)

## Introdução <a name="introduction"></a>

[Iframes](https://developer.mozilla.org/pt-BR/docs/Web/HTML/Element/iframe)! Quando ouvimos falar sobre esse elemento parece que estamos voltando no tempo. Como naquelas páginas bonitas em que o menu chamava cada parte do site dentro de um desses elementos. Mas os iframes ainda existem, sempre vão existir, e servem para muitos propósitos.

Há algum tempo eu tive que fazer um chat que iria ser embedado no site dos nossos clientes e então surgiu a primeira questão:

> Como incluir um site dentro de outro?

Fui buscar como outras empresas faziam e óbvio que TODOS usavam iframe. É necessário isolar o escopo, não pode haver vazamento de css/html e muito menos de javascript, algo que o iframe faz muito bem.

## Problema <a name="problem"></a>

Ao inserir o chat em um site, temos dois estados: 

- Aberto 
- Fechado

Um iframe não pode mudar seu tamanho, não temos acesso ao `document` dentro dele. Para isso precisamos _avisar_ o lado de fora do iframe.

## `window.postMessage` <a name="postMessage"></a>

Foi então que descobri o `window.postMessage` ([documentação](https://developer.mozilla.org/docs/Web/API/Window/postMessage)) que permite enviar eventos para uma window (target) diferente. Assim posso deixar algum listener na window no qual incluo o iframe e enviar um evento falando qual o tamanho que o iframe precisa ter.

Para emitir um evento do iframe é tão simples quanto: 

```javascript
window.parent.postMessage('mensagem vinda do iframe', '*')
```

- window.parent: window de destino do evento, a window do iframe contém a propriedade parent, que é a referência para a página em que está incluso
- postMessage: o método em si, recebe dois parâmetros: o dado que será enviado (nesse exemplo enviei uma string simples) e a url de destino (passando * é aceito qualquer origem)

## Recebendo o evento <a name="from-iframe"></a>

Do lado _parent_, ou seja, o que recebe o evento, temos que ficar escutando o evento `message` da window, por exemplo:

```javascript
// window escutando o evento `message` que o postMessage envia
window.addEventListener('message', function(e){
  // para ter acesso ao dado temos que acessar a propriedade data
  console.log(e.data)
})
```

## Enviando dado para o iframe <a name="to-iframe"></a>

Para enviar o dado para o iframe, primeiro precisamos recuperar o elemento:

```
const meuIframe = document.getElementById('meuiframe')
```

Com o elemento podemos chamar o postMessage da mesma forma que fizemos dentro dele, chamando direto a window do mesmo:

```
meuIframe.contentWindow.postMessage('mensagem pro iframe', '*')
```

## Conclusão <a name="conclusion"></a>

Com o postMessage fica simples e seguro, se usar o segundo parâmetro como filtro de destino para se comunicar com iframes.

Fiz dois exemplos simples do uso, [um chat entre páginas](https://github.com/houstondapaz/postmessage-chat-exemplo) e um 
[alterando o tamanho do iframe](https://github.com/houstondapaz/postmessage-chat-exemplo).
 

Qualquer dúvida ou sugestão comenta aí!