<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lucas Teixeira dos Santos Santana</title>
    <description>The latest articles on DEV Community by Lucas Teixeira dos Santos Santana (@santanaluc94).</description>
    <link>https://dev.to/santanaluc94</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F612703%2F593bf5f9-bd44-4995-9521-04c6ffbffd39.jpeg</url>
      <title>DEV Community: Lucas Teixeira dos Santos Santana</title>
      <link>https://dev.to/santanaluc94</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/santanaluc94"/>
    <language>en</language>
    <item>
      <title>Como criar um template de email personalizado no Magento 2</title>
      <dc:creator>Lucas Teixeira dos Santos Santana</dc:creator>
      <pubDate>Wed, 25 Mar 2026 11:57:21 +0000</pubDate>
      <link>https://dev.to/santanaluc94/como-criar-um-template-de-email-personalizado-no-magento-2-2e8c</link>
      <guid>https://dev.to/santanaluc94/como-criar-um-template-de-email-personalizado-no-magento-2-2e8c</guid>
      <description>&lt;h2&gt;
  
  
  Contextualizando
&lt;/h2&gt;

&lt;p&gt;O Magento inclui um &lt;em&gt;template&lt;/em&gt; de e-mail padrão para o corpo de cada mensagem enviada pelo sistema. Este &lt;em&gt;template&lt;/em&gt; de conteúdo é combinado com &lt;em&gt;templates&lt;/em&gt; de cabeçalho (&lt;em&gt;header&lt;/em&gt;) e rodapé (&lt;em&gt;footer&lt;/em&gt;) para criar a mensagem completa.&lt;/p&gt;

&lt;p&gt;A customização pelo painel administrativo é a maneira mais fácil e tem &lt;strong&gt;precedência&lt;/strong&gt; sobre os &lt;em&gt;templates&lt;/em&gt; padrão do sistema e aqueles baseados em temas.&lt;/p&gt;




&lt;h3&gt;
  
  
  Carregar o Template Padrão
&lt;/h3&gt;

&lt;p&gt;No painel administrador acesse: &lt;code&gt;Marketing &amp;gt; Communications &amp;gt; Email Templates &amp;gt; Add New Template&lt;/code&gt;. Na seção &lt;em&gt;Load default template&lt;/em&gt;, selecione o &lt;em&gt;template&lt;/em&gt; que se deseja customizar no seletor &lt;em&gt;Template&lt;/em&gt;. O código HTML e as variáveis do &lt;em&gt;template&lt;/em&gt; aparecerão no formulário, após clicar no botão &lt;em&gt;Load Template&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F14xsuoflpb7gnmcpswfs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F14xsuoflpb7gnmcpswfs.png" alt="Load Default Email Template" width="800" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Após o carregamento do conteúdo do &lt;em&gt;template&lt;/em&gt;, é possível modificar o conteúdo do &lt;em&gt;template&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flh45eel959ij82pi3awj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flh45eel959ij82pi3awj.png" alt="Email Template Configuration" width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Template Name:&lt;/strong&gt; nome do &lt;em&gt;template&lt;/em&gt; para identificação;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Template Subject:&lt;/strong&gt; assunto do e-mail, que pode ser usado para organizar, classificar e filtrar os &lt;em&gt;templates;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Template Content:&lt;/strong&gt; responsável por gerar o HTML conforme a necessidade. Deve-se ter cuidado ao remover, editar e acrescentar chaves duplas;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Template Styles&lt;/strong&gt;: responsável por declarações de estilo CSS necessárias para formatar o &lt;em&gt;template.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para inserir uma &lt;strong&gt;variável&lt;/strong&gt;, posicione o cursor no código onde a variável deve ser inserida e clique em &lt;strong&gt;&lt;em&gt;Insert Variable&lt;/em&gt;&lt;/strong&gt;. Uma &lt;em&gt;tag&lt;/em&gt; de marcação para a variável será inserida no código. A seleção de variáveis varia por &lt;em&gt;template&lt;/em&gt;. Variáveis de Contato da Loja (&lt;em&gt;Store Contact Information&lt;/em&gt;) estão disponíveis em todos os &lt;em&gt;templates&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;É possível pré-visualizar o e-mail através do botão &lt;strong&gt;&lt;em&gt;Preview Template&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criar um Template de E-mail Personalizado
&lt;/h2&gt;

&lt;p&gt;Criar &lt;em&gt;templates&lt;/em&gt; como arquivos físicos no sistema de arquivos do módulo ou tema é a abordagem recomendada para desenvolvedores. Isso permite o controle de versão e facilita a implantação.&lt;/p&gt;

&lt;h3&gt;
  
  
  email_templates.xml
&lt;/h3&gt;

&lt;p&gt;Para criar um &lt;em&gt;template&lt;/em&gt; de e-mail é necessário criar um arquivo chamado &lt;code&gt;email_templates.xml&lt;/code&gt; que deve seguir a estrutura de pasta &lt;code&gt;\{Vendor}{Module}\etc\email_templates.xml.xml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;config&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt; &lt;span class="na"&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"urn:magento:module:Magento_Email:etc/email_templates.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"{template_id}"&lt;/span&gt;
              &lt;span class="na"&gt;label=&lt;/span&gt;&lt;span class="s"&gt;"{Email Template Label}"&lt;/span&gt;
              &lt;span class="na"&gt;file=&lt;/span&gt;&lt;span class="s"&gt;"{path}/{file_name}.html"&lt;/span&gt;
              &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"html"&lt;/span&gt;
              &lt;span class="na"&gt;module=&lt;/span&gt;&lt;span class="s"&gt;"{Vendor}_{Module}"&lt;/span&gt;
              &lt;span class="na"&gt;area=&lt;/span&gt;&lt;span class="s"&gt;"{area}"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Atributos template&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Atributo&lt;/th&gt;
&lt;th&gt;Descrição&lt;/th&gt;
&lt;th&gt;Obrigatório&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;Um identificador único para o &lt;em&gt;template&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;label&lt;/td&gt;
&lt;td&gt;O nome visível no painel administrador&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;file&lt;/td&gt;
&lt;td&gt;O caminho e nome do arquivo HTML do &lt;em&gt;template&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;type&lt;/td&gt;
&lt;td&gt;Tipo de arquivo&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;module&lt;/td&gt;
&lt;td&gt;Nome do módulo no qual será procurado o arquivo de &lt;em&gt;template&lt;/em&gt;.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;area&lt;/td&gt;
&lt;td&gt;Área responsável onde será procurado o arquivo de &lt;em&gt;template&lt;/em&gt; (&lt;code&gt;frontend&lt;/code&gt; ou &lt;code&gt;adminhtml&lt;/code&gt;).&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  template.html
&lt;/h3&gt;

&lt;p&gt;No arquivo de &lt;em&gt;template&lt;/em&gt; deve seguir a estrutura de pastas &lt;code&gt;\{Vendor}\{Module}\view\{area}\email\{path}\{file_name}.html&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!--@subject {Email Subject} @--&amp;gt;&lt;/span&gt;
{{template config_path="design/email/header_template"}}
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{{trans "Olá, %var_name," var_name=$var_name}}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;{{var var_name}}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
{{template config_path="design/email/footer_template"}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Disparo de E-mail
&lt;/h2&gt;

&lt;p&gt;E-mails podem ser disparados utilizando a classe &lt;code&gt;\Magento\Framework\Mail\Template\TransportBuilder&lt;/code&gt;. Esta classe pode ser instanciada através de injeção de dependência no construtor.&lt;/p&gt;

&lt;p&gt;Para disparar um e-mail é utilizado o método &lt;code&gt;getTransport()&lt;/code&gt; da classe de gerenciador de e-mails, mas antes é necessário configurar os dados de remetente, recebedor e configurar as variáveis do e-mail.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Vendor&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Directory&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Magento\Framework\Mail\Template\TransportBuilder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Magento\Framework\Translate\Inline\StateInterface&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;ClassName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;TransportBuilder&lt;/span&gt; &lt;span class="nv"&gt;$transportBuilder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;StateInterface&lt;/span&gt; &lt;span class="nv"&gt;$inlineTranslation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="kt"&gt;TransportBuilder&lt;/span&gt; &lt;span class="nv"&gt;$transportBuilder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;StateInterface&lt;/span&gt; &lt;span class="nv"&gt;$inlineTranslation&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;transportBuilder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$transportBuilder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;inlineTranslation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$inlineTranslation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="mf"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;methodName&lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$templateOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'area'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;\Magento\Framework\App\Area&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;AREA_FRONTEND&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'store'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;storeManager&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getStore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nv"&gt;$templateVars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'{var_name}'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'{var value}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="nv"&gt;$from&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$emailSender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$senderName&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nv"&gt;$to&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$recipientEmail&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;inlineTranslation&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$transport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;transportBuilder&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setTemplateIdentifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{template_id}'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setTemplateOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$templateOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setTemplateVars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$templateVars&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$from&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$to&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getTransport&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nv"&gt;$transport&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;inlineTranslation&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;resume&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Estilização e Variáveis de Template
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;{{template config_path="..."}}&lt;/code&gt;: Estas diretivas carregam o &lt;em&gt;header, footer&lt;/em&gt; e outros &lt;em&gt;templates&lt;/em&gt; de e-mail padrões.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;!--@subject ... @--&amp;gt;&lt;/code&gt;: Define o assunto do e-mail.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{{var ...}}&lt;/code&gt;: Permite a inserção de variáveis passadas pelo código PHP.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Estilização (CSS)
&lt;/h3&gt;

&lt;p&gt;A estilização de e-mails é um desafio no &lt;em&gt;frontend&lt;/em&gt; devido ao suporte limitado de clientes de e-mail para &lt;em&gt;tags&lt;/em&gt; &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; ou folhas de estilo externas.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Estilos Inline:&lt;/strong&gt; A maioria dos estilos de e-mail deve ser aplicada como estilos &lt;em&gt;inline&lt;/em&gt; (no atributo &lt;code&gt;style&lt;/code&gt; das &lt;em&gt;tags&lt;/em&gt; HTML). O Magento utiliza a biblioteca &lt;strong&gt;Emogrifier&lt;/strong&gt; para converter os estilos CSS em estilos &lt;em&gt;inline&lt;/em&gt;.

&lt;ul&gt;
&lt;li&gt;A diretiva &lt;code&gt;{{inlinecss file="css/email-inline.css"}}&lt;/code&gt; no &lt;code&gt;header.html&lt;/code&gt; informa ao Magento quais arquivos less/css devem ser aplicados como estilos &lt;em&gt;inline&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag Style:&lt;/strong&gt; Estilos que não podem ser aplicados &lt;em&gt;inline&lt;/em&gt; (como &lt;em&gt;media queries&lt;/em&gt; ou &lt;em&gt;pseudo-classes&lt;/em&gt; &lt;code&gt;:hover&lt;/code&gt;) devem estar dentro de uma &lt;em&gt;tag&lt;/em&gt; &lt;code&gt;&amp;lt;style type="text/css"&amp;gt;&amp;lt;/style&amp;gt;&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;A diretiva &lt;code&gt;{{css file="css/email.css"}}&lt;/code&gt; no &lt;code&gt;header.html&lt;/code&gt; compila e insere esses estilos não-&lt;em&gt;inline&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Estilos Customizados:&lt;/strong&gt; Estilos adicionados no campo &lt;strong&gt;&lt;em&gt;Template Styles&lt;/em&gt;&lt;/strong&gt; do painel administrador ou em blocos de comentários &lt;code&gt;&amp;lt;!--@styles ... @--&amp;gt;&lt;/code&gt; em arquivos HTML de &lt;em&gt;template&lt;/em&gt; são incluídos na variável &lt;code&gt;{{var template_styles|raw}}&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Variáveis e Localização
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Variáveis do Sistema:&lt;/strong&gt; São &lt;em&gt;placeholders&lt;/em&gt; (como &lt;code&gt;{{config path="..."}}&lt;/code&gt; ou &lt;code&gt;{{var store_email}}&lt;/code&gt;) que são substituídos por valores de configuração da loja no momento da geração do e-mail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Variáveis Customizadas:&lt;/strong&gt; Podem ser criadas e ter seus valores definidos no painel administrador em &lt;code&gt;System &amp;gt; Other Settings &amp;gt; Custom Variables&lt;/code&gt;. Elas podem ser inseridas no &lt;em&gt;template&lt;/em&gt; usando comandos como &lt;code&gt;{{var custom_variable}}&lt;/code&gt; ou &lt;code&gt;{{customVar code=custom_variable}}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Localização (&lt;em&gt;Localization&lt;/em&gt;):&lt;/strong&gt; Para suportar a tradução de conteúdo, todas as &lt;em&gt;strings&lt;/em&gt; nos e-mails devem usar a diretiva &lt;code&gt;{{trans ...}}&lt;/code&gt;. O Magento traduzirá as &lt;em&gt;strings&lt;/em&gt; para o &lt;em&gt;locale&lt;/em&gt; configurado para a &lt;em&gt;store view&lt;/em&gt; que está enviando o e-mail.

&lt;ul&gt;
&lt;li&gt;A diretiva &lt;code&gt;trans&lt;/code&gt; suporta múltiplos parâmetros nomeados. Exemplo: &lt;code&gt;{{trans "Dear %first_name %last_name," first_name=$first_name last_name=$last_name}}&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Finalizando
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Valores entre chaves (&lt;code&gt;{test}&lt;/code&gt;) devem ser alterados na implementação do código.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Habilitando as alterações
&lt;/h3&gt;

&lt;p&gt;Execute o comando PHP para limpar todos os caches de armazenamento em cache do processos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php bin/magento cache:clean
php bin/magento flush
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Diretórios e Arquivos
&lt;/h3&gt;

&lt;p&gt;Segue a a lista de diretórios e arquivos que devem ser criados para a criaçãod e tradução em um módulo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- app/
  - code/
    - {Vendor}/
        - {Module}/
          - etc/
            - module.xml
            - email_templates.xml
          - view/
              - {area}/
                  - email/
                  - {fileName}.html
          - registration.php
          - composer.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>php</category>
      <category>braziliandevs</category>
      <category>magento2</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Como funcionam Bindings de Eventos de Formulário no KnockoutJs</title>
      <dc:creator>Lucas Teixeira dos Santos Santana</dc:creator>
      <pubDate>Mon, 25 Nov 2024 17:02:31 +0000</pubDate>
      <link>https://dev.to/santanaluc94/como-funcionam-bindings-de-eventos-de-formulario-no-knockoutjs-40fe</link>
      <guid>https://dev.to/santanaluc94/como-funcionam-bindings-de-eventos-de-formulario-no-knockoutjs-40fe</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Este conteúdo é basicamente uma tradução dos materiais originais. A intenção é adquirir aprendizado sobre o KnockoutJs para Magento 2 e criar conteúdo em português sobre KnockouJs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Documentação
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/binding-syntax.html" rel="noopener noreferrer"&gt;The data-bind syntax&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/binding-context.html" rel="noopener noreferrer"&gt;Binding context&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/click-binding.html" rel="noopener noreferrer"&gt;The "click" binding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/event-binding.html" rel="noopener noreferrer"&gt;The "event" binding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/submit-binding.html" rel="noopener noreferrer"&gt;The "submit" binding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/enable-binding.html" rel="noopener noreferrer"&gt;The "enable" and "disable" bindings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/value-binding.html" rel="noopener noreferrer"&gt;The "value" binding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/textinput-binding.html" rel="noopener noreferrer"&gt;The "textInput" binding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/hasfocus-binding.html" rel="noopener noreferrer"&gt;The "hasFocus" binding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/checked-binding.html" rel="noopener noreferrer"&gt;The "checked" binding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/options-binding.html" rel="noopener noreferrer"&gt;The "options" binding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/selectedOptions-binding.html" rel="noopener noreferrer"&gt;The "selectedOptions" binding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/uniqueName-binding.html" rel="noopener noreferrer"&gt;The "uniqueName" binding&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Bindings
&lt;/h2&gt;

&lt;p&gt;No KnockoutJs, &lt;em&gt;bindings&lt;/em&gt; são a maneira de conectar a lógica do &lt;em&gt;ViewModel&lt;/em&gt; (os dados e a lógica de negócios) com a &lt;em&gt;View&lt;/em&gt; (HTML). Em resumo, é através dos &lt;em&gt;bindings&lt;/em&gt; que é realizada a interface de usuário refletir automaticamente as mudanças nos seus dados, sem a necessidade de manipular diretamente o DOM.&lt;/p&gt;

&lt;p&gt;Os bindings no KnockoutJs funcionam através do atributo &lt;code&gt;data-bind&lt;/code&gt; em elementos HTML. Esse atributo é onde você especifica o binding que deseja usar e os valores associados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eventos de Formulário
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Click
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;click&lt;/code&gt; adiciona um manipulador de eventos para que a função JavaScript escolhida seja invocada quando o elemento DOM associado for clicado. Isso é mais comumente usado em elementos com tag &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; e &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;, mas na verdade funciona com qualquer elemento DOM visível. O KnockoutJs fornecerá o valor atual do modelo como o primeiro parâmetro.&lt;/p&gt;

&lt;p&gt;Cada vez que for clicado no elemento, isso invocará o método que foi passado na &lt;em&gt;ViewModel&lt;/em&gt;, que por sua vez altera o estado da &lt;em&gt;ViewModel&lt;/em&gt;, o que faz com que a IU seja atualizada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    You've clicked &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"text: numberOfClicks"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt; times
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"click: incrementClickCounter"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Click me&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyBindings&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;numberOfClicks&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;incrementClickCounter&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;previousCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;numberOfClicks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;numberOfClicks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;previousCount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por padrão, o KnockoutJs impedirá que o evento &lt;em&gt;click&lt;/em&gt; execute qualquer ação padrão. Isso significa que ao usar o &lt;em&gt;binding click&lt;/em&gt; em uma tag &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;, o navegador apenas chamará a função e não navegará até o &lt;code&gt;href&lt;/code&gt; do link. A vinculação de clique é normalmente utilizada quando está usando o link como parte de uma UI que manipula a &lt;em&gt;ViewModel&lt;/em&gt;, não como um hiperlink normal para outra página da web. Caso seja necessário que a ação de clique padrão continue, basta retornar &lt;code&gt;true&lt;/code&gt; na função.&lt;/p&gt;

&lt;h3&gt;
  
  
  Event
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;event&lt;/code&gt; permite adicionar um manipulador de eventos para um evento especificado para que a função JavaScript escolhida seja invocada quando esse evento for acionado para o elemento DOM associado. Isso pode ser usado para vincular a qualquer evento, como pressionamento de tecla, passagem do mouse ou saída do mouse.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"event: { mouseover: enableDetails, mouseout: disableDetails }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        Mouse over me
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"visible: detailsEnabled"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        Details
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyBindings&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;detailsEnabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;enableDetails&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;detailsEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;disableDetails&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;detailsEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Submit
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;submit&lt;/code&gt; *&lt;em&gt;é uma diretiva de vinculação de envio em um formulário impedirá a ação de envio padrão do navegador para esse formulário, em outras palavras, o navegador chamará a função de manipulador, mas não enviará o formulário ao servidor. A vinculação de *submit&lt;/em&gt; é normalmente utilizada quando está sendo usado o formulário como uma interface para a &lt;em&gt;ViewModel&lt;/em&gt;, não como um formulário HTML normal. Caso seja necessário que o formulário seja enviado como um formulário HTML normal, basta retornar &lt;code&gt;true&lt;/code&gt; do seu manipulador de envio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"submit: doSomething"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Submit&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyBindings&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doSomething&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// ... now do something&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Enable/Disable
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;enable&lt;/code&gt; faz com que o elemento DOM associado seja habilitado quando seu valor de parâmetro for verdadeiro. O &lt;em&gt;binding&lt;/em&gt; &lt;em&gt;disable&lt;/em&gt; funciona de forma oposta, fazendo com que o elemento DOM associado seja desabilitado quando seu valor for verdadeiro.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'checkbox'&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"checked: hasCellphone"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    I have a cellphone
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
    Your cellphone number:
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'text'&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"value: cellphoneNumber, enable: hasCellphone"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyBindings&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;hasCellphone&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;cellphoneNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Value
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;value&lt;/code&gt; *&lt;em&gt;vincula o valor do elemento DOM associado a uma propriedade na *ViewModel&lt;/em&gt;. Isso normalmente é útil com elementos de formulário como &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; e &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Quando o usuário editar o valor no controle de formulário associado, o valor será atualizado na &lt;em&gt;ViewModel&lt;/em&gt;. Da mesma forma, quando a &lt;em&gt;ViewModel&lt;/em&gt; atualiza o valor, isso atualizará o valor do controle de formulário na tela.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Login name: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"value: userName"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Password: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"value: userPassword"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyBindings&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;        &lt;span class="c1"&gt;// Initially blank&lt;/span&gt;
        &lt;span class="na"&gt;userPassword&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;abc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// Prepopulate&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;value&lt;/code&gt; funciona em conjunto com a vinculação de &lt;code&gt;&amp;lt;options&amp;gt;&lt;/code&gt; para permitir a leitura e gravação de valores que são objetos JavaScript arbitrários, e não apenas valores de &lt;em&gt;string&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  TextInput
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;textInput&lt;/code&gt; vincula um campo (&lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; ou &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt;) a uma propriedade &lt;em&gt;ViewModel&lt;/em&gt;, fornecendo atualizações bidirecionais entre a propriedade &lt;em&gt;ViewModel&lt;/em&gt; e o valor do elemento. O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;textInput&lt;/code&gt; fornece atualizações instantâneas do DOM para todos os tipos de entrada do usuário, incluindo preenchimento automático, arrastar e soltar e eventos da área de transferência.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Login name: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"textInput: userName"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Password: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"textInput: userPassword"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

ViewModel:
&lt;span class="nt"&gt;&amp;lt;pre&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"text: ko.toJSON($root, null, 2)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/pre&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyBindings&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;        &lt;span class="c1"&gt;// Initially blank&lt;/span&gt;
        &lt;span class="na"&gt;userPassword&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;abc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// Prepopulate&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;textInput&lt;/code&gt;, por padrão, só atualiza seu modelo quando o usuário move o foco para fora da caixa de texto. O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;textInput&lt;/code&gt; atualiza seu modelo imediatamente a cada pressionamento de tecla ou outro mecanismo de entrada de texto.&lt;/p&gt;

&lt;h3&gt;
  
  
  HasFocus
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;hasFocus&lt;/code&gt; vincula o estado de foco de um elemento DOM a uma propriedade &lt;em&gt;ViewModel&lt;/em&gt;. É uma ligação bidirecional que ao ser definida a propriedade &lt;em&gt;ViewModel&lt;/em&gt; como &lt;code&gt;true&lt;/code&gt; ou &lt;code&gt;false&lt;/code&gt;, o elemento associado ficará focado ou desfocado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"hasFocus: isSelected"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"click: setIsSelected"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Focus programmatically&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"visible: isSelected"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;The textbox has focus&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyBindings&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;isSelected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="na"&gt;setIsSelected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isSelected&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Checked
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;checked&lt;/code&gt; vincula um controle de formulário verificável, ou seja, uma caixa de seleção (&lt;code&gt;&amp;lt;input type='checkbox'&amp;gt;&lt;/code&gt;) ou um botão de opção (&lt;code&gt;&amp;lt;input type='radio'&amp;gt;&lt;/code&gt;) com uma propriedade na &lt;em&gt;ViewModel&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Check 1 (checked): &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"checked: checkYes"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Check 2 (unchecked): &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"checkbox"&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"checked: checkNo"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt; 

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyBindings&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;checkYes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;checkNo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Options
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;options&lt;/code&gt; controla quais opções devem aparecer em uma lista suspensa (&lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt;) ou lista de seleção múltipla (&lt;code&gt;&amp;lt;select size='6'&amp;gt;&lt;/code&gt;). Esta ligação não pode ser usada com nada além de elementos &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O valor atribuído deve ser um &lt;em&gt;array&lt;/em&gt; (ou &lt;em&gt;Observable Array&lt;/em&gt;). O elemento &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; exibirá então um item para cada item do seu &lt;em&gt;array&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
    Destination country:
    &lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"options: availableCountries"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/select&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"value: newCountry"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"click: addCountry"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Add country&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyBindings&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;addCountry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;availableCountries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newCountry&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;newCountry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;        
        &lt;span class="na"&gt;availableCountries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observableArray&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Argentina&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Brazil&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Chile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  SelectedOptions
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;selectedOptions&lt;/code&gt; controla quais elementos em uma lista de seleção múltipla estão selecionados no momento. Destina-se a ser usado em conjunto com um elemento &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; e a ligação de opções.&lt;/p&gt;

&lt;p&gt;Quando o usuário seleciona ou desmarca um item na lista de seleção múltipla, isso adiciona ou remove o valor correspondente a uma matriz na &lt;em&gt;ViewModel&lt;/em&gt;. Da mesma forma, supondo que seja um &lt;em&gt;Observable Array&lt;/em&gt; na &lt;em&gt;ViewModel&lt;/em&gt;, sempre que adicionar ou remover itens desse &lt;em&gt;array&lt;/em&gt;, os itens correspondentes na UI serão selecionados ou desmarcados. É uma ligação bidirecional.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Choose some countries you'd like to visit:&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"options: availableCountries, selectedOptions: chosenCountries"&lt;/span&gt; &lt;span class="na"&gt;size=&lt;/span&gt;&lt;span class="s"&gt;"5"&lt;/span&gt; &lt;span class="na"&gt;multiple=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/select&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyBindings&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;availableCountries&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observableArray&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;France&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Germany&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Spain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
        &lt;span class="na"&gt;chosenCountries&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observableArray&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Germany&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// Initially, only Germany is selected&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  UniqueName
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;uniqueName&lt;/code&gt; garante que o elemento DOM associado tenha um atributo de nome não vazio. Se o elemento DOM não tiver um atributo &lt;em&gt;name&lt;/em&gt;, essa ligação fornecerá um e o definirá como algum valor de string exclusivo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"value: someModelProperty, uniqueName: true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>braziliandevs</category>
      <category>javascript</category>
      <category>learning</category>
      <category>knockoutjs</category>
    </item>
    <item>
      <title>Como funcionam Bindings de Fluxo de Controle no KnockoutJs</title>
      <dc:creator>Lucas Teixeira dos Santos Santana</dc:creator>
      <pubDate>Mon, 18 Nov 2024 13:48:04 +0000</pubDate>
      <link>https://dev.to/santanaluc94/como-funcionam-bindings-de-fluxo-de-controle-no-knockoutjs-3cbp</link>
      <guid>https://dev.to/santanaluc94/como-funcionam-bindings-de-fluxo-de-controle-no-knockoutjs-3cbp</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Este conteúdo é basicamente uma tradução dos materiais originais. A intenção é adquirir aprendizado sobre o KnockoutJs para Magento 2 e criar conteúdo em português sobre KnockouJs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Documentação
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/binding-syntax.html" rel="noopener noreferrer"&gt;The data-bind syntax&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/binding-context.html" rel="noopener noreferrer"&gt;Binding context&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/foreach-binding.html" rel="noopener noreferrer"&gt;The "foreach" binding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/if-binding.html" rel="noopener noreferrer"&gt;The "if" and "ifnot" bindings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/with-binding.html" rel="noopener noreferrer"&gt;The "with" and "using" bindings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/let-binding.html" rel="noopener noreferrer"&gt;The "let" binding&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Bindings
&lt;/h2&gt;

&lt;p&gt;No KnockoutJs, &lt;em&gt;bindings&lt;/em&gt; são a maneira de conectar a lógica do &lt;em&gt;ViewModel&lt;/em&gt; (os dados e a lógica de negócios) com a &lt;em&gt;View&lt;/em&gt; (HTML). Em resumo, é através dos &lt;em&gt;bindings&lt;/em&gt; que é realizada a interface de usuário refletir automaticamente as mudanças nos seus dados, sem a necessidade de manipular diretamente o DOM.&lt;/p&gt;

&lt;p&gt;Os bindings no KnockoutJs funcionam através do atributo &lt;code&gt;data-bind&lt;/code&gt; em elementos HTML. Esse atributo é onde você especifica o binding que deseja usar e os valores associados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fluxo de Controle
&lt;/h2&gt;

&lt;h3&gt;
  
  
  foreach
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;foreach&lt;/code&gt; é usado para criar repetições em elementos HTML, gerando cópias do mesmo elemento para cada item em uma coleção (como um &lt;em&gt;array&lt;/em&gt; ou um &lt;em&gt;observable array&lt;/em&gt;) no seu modelo de visualização. Isso permite que seja criado facilmente listas ou tabelas dinâmicas que exibem dados do seu modelo.&lt;/p&gt;

&lt;p&gt;Quando é modificado o conteúdo do &lt;em&gt;array&lt;/em&gt; de modelo (adicionando, movendo ou excluindo suas entradas), o &lt;em&gt;binding&lt;/em&gt; do &lt;em&gt;foreach&lt;/em&gt; usa um algoritmo eficiente para descobrir o que mudou, para que possa atualizar o DOM conforme o &lt;em&gt;array&lt;/em&gt;. Isso significa que ele pode lidar com combinações arbitrárias de alterações simuladas.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quando é adicionado algo no &lt;em&gt;array&lt;/em&gt;, o &lt;code&gt;foreach&lt;/code&gt; irá renderizar novas cópias do seu modelo e inseri-las no DOM existente;&lt;/li&gt;
&lt;li&gt;Quando é excluído algo no array, o &lt;code&gt;foreach&lt;/code&gt; simplesmente removerá os elementos DOM correspondentes;&lt;/li&gt;
&lt;li&gt;Quando é reordenado algo no array (mantendo as mesmas instâncias do objeto), o &lt;code&gt;foreach&lt;/code&gt; normalmente apenas moverá os elementos DOM correspondentes para sua nova posição.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"foreach: items"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"text: $data"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"foreach: getItems()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"text: name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt; - &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"text: age"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"foreach: { data: people, as: 'person' }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste caso, a variável &lt;code&gt;$data&lt;/code&gt; faz referência ao item atual que está sendo processado no loop. Isso permite acessar as propriedades ou valores desse item dentro do loop.&lt;/p&gt;

&lt;p&gt;A diretiva &lt;code&gt;as&lt;/code&gt; permite que seja definido um nome personalizado para a variável que representa o item atual no ciclo de iteração do &lt;code&gt;foreach&lt;/code&gt;. Isso pode tornar o código mais legível e significativo.&lt;/p&gt;

&lt;p&gt;Às vezes é necessário que um item do &lt;em&gt;array&lt;/em&gt; não seja excluído, mas sim ocultado, sem realmente perder o registro de sua existência. Isso é conhecido como exclusão não destrutiva. Caso seja necessário ocultar entradas destruídas, defina a opção &lt;code&gt;includeDestroyed&lt;/code&gt; como &lt;code&gt;false&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;'foreach: { data: myArray, includeDestroyed: false }'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    ...
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso seja necessário executar alguma lógica personalizada adicional nos elementos DOM gerados, é possível usar qualquer um dos seguintes retornos de chamada:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;afterRender&lt;/code&gt;: é invocado cada vez que o bloco &lt;code&gt;foreach&lt;/code&gt; é duplicado e inserido no documento, tanto quando foreach é inicializado pela primeira vez quanto quando novas entradas são adicionadas posteriormente ao &lt;em&gt;array&lt;/em&gt; associado;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;afterAdd&lt;/code&gt;: é como &lt;code&gt;afterRender&lt;/code&gt;, exceto que é invocado apenas quando novas entradas são adicionadas ao &lt;em&gt;array&lt;/em&gt; (e não quando &lt;code&gt;foreach&lt;/code&gt; itera pela primeira vez sobre o conteúdo inicial do &lt;em&gt;array&lt;/em&gt;);&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;beforeRemove&lt;/code&gt;: é invocado quando um item do &lt;em&gt;array&lt;/em&gt; é removido, mas antes que os nós DOM correspondentes sejam removidos. Se for especificado um retorno de chamada &lt;code&gt;beforeRemove&lt;/code&gt;, será necessário remover os nós DOM manualmente, ou seja, o KnockoutJs não pode saber quando será permitido remover fisicamente os nós DOM;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;beforeMove&lt;/code&gt;: é invocado quando um item do &lt;em&gt;array&lt;/em&gt; mudou de posição no &lt;em&gt;array&lt;/em&gt;, mas antes que os nós DOM correspondentes tenham sido movidos. Observe que &lt;code&gt;beforeMove&lt;/code&gt; se aplica a todos os elementos do array cujos índices foram alterados, portanto, se for inserido um novo item no início de um &lt;em&gt;array&lt;/em&gt;, o retorno de chamada (se especificado) será acionado para todos os outros elementos, já que sua posição de índice aumentou em um. É possível usar o &lt;code&gt;beforeMove&lt;/code&gt; para armazenar as coordenadas originais da tela dos elementos afetados para poder animar seus movimentos no retorno de chamada afterMove;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;afterMove&lt;/code&gt;: é invocado depois que um item do &lt;em&gt;array&lt;/em&gt; mudou de posição no &lt;em&gt;array&lt;/em&gt; e depois que &lt;code&gt;foreach&lt;/code&gt; atualizou o DOM para corresponder. Observe que &lt;code&gt;afterMove&lt;/code&gt; se aplica a todos os elementos do &lt;em&gt;array&lt;/em&gt; cujos índices foram alterados, portanto, se for inserido um novo item no início de um &lt;em&gt;array&lt;/em&gt;, o retorno de chamada (se especificado) será acionado para todos os outros elementos, já que sua posição de índice aumentou em um.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  if e ifnot
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; do &lt;code&gt;if&lt;/code&gt; faz com que uma seção de marcação apareça em seu documento (e tenha seus atributos de ligação de dados aplicados), somente se uma expressão especificada for avaliada como verdadeira (ou um valor verdadeiro, como um objeto não nulo ou uma &lt;em&gt;string&lt;/em&gt; não vazia).&lt;/p&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; do &lt;code&gt;ifnot&lt;/code&gt; funciona exatamente como a ligação &lt;code&gt;if&lt;/code&gt;, exceto que inverte o resultado de qualquer expressão que seja passado para ela.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;if&lt;/code&gt; e &lt;code&gt;ifnot&lt;/code&gt; desempenham um papel semelhante aos bindings &lt;code&gt;vivsible&lt;/code&gt; e &lt;code&gt;hidden&lt;/code&gt;. A diferença é que, com &lt;code&gt;visible&lt;/code&gt;, a marcação contida sempre permanece no DOM e sempre tem seus &lt;code&gt;data-bind&lt;/code&gt; de dados aplicados – o binding &lt;code&gt;visible&lt;/code&gt; apenas usa CSS para alternar a visibilidade do elemento contêiner. A ligação &lt;code&gt;if&lt;/code&gt;, entretanto, adiciona ou remove fisicamente a marcação contida em seu DOM e só aplica ligações aos descendentes se a expressão for verdadeira. Se a expressão envolver algum valor observável, a expressão será reavaliada sempre que o valor dele mudar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"if: exibirMensagem"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Esta mensagem será exibida se 'exibirMensagem' for verdadeiro.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"ifnot: exibirMensagem"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Esta mensagem será exibida se 'exibirMensagem' for falso.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  with e using
&lt;/h3&gt;

&lt;p&gt;Os &lt;em&gt;bindings&lt;/em&gt; &lt;code&gt;with&lt;/code&gt; e &lt;code&gt;using&lt;/code&gt; criam um novo contexto de ligação, para que os elementos descendentes sejam vinculados no contexto de um objeto especificado.&lt;/p&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;with&lt;/code&gt; adicionará ou removerá dinamicamente elementos descendentes dependendo se o valor associado for &lt;em&gt;falsy.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A opção &lt;code&gt;as&lt;/code&gt; permite definir um &lt;em&gt;alias&lt;/em&gt; para o novo objeto de contexto. Embora seja possível se referir ao objeto usando a variável de contexto &lt;code&gt;$data&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"submit: getTweets"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Twitter account:
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"value: twitterName"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Get tweets&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"with: resultData"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Recent tweets fetched at &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"text: retrievalDate"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ol&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"foreach: topTweets"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"text: text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ol&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"click: $parent.clearResults"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Clear tweets&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AppViewModel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;twitterName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@example&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resultData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// No initial value&lt;/span&gt;

    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTweets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;twitterName&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="nx"&gt;simulatedResults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; What a nice day.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; Building some cool apps.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; Just saw a famous celebrity eating lard. Yum.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resultData&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;retrievalDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;topTweets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulatedResults&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clearResults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resultData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyBindings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AppViewModel&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A ligação &lt;code&gt;using&lt;/code&gt; foi introduzida no KnockoutJs 3.5 como um substituto para o &lt;code&gt;with&lt;/code&gt; quando a renderização de elementos descendentes não é desejada. Como o &lt;code&gt;using&lt;/code&gt; reavalia as ligações descendentes em vez de renderizar novamente, cada ligação descendente incluirá uma dependência adicional no contexto do &lt;code&gt;using&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  let
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;let&lt;/code&gt; permite definir propriedades de contexto de ligação personalizadas que é possível referenciar nas ligações de todos os elementos descendentes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!--ko let: {inventory: {suppliers: suppliers, bins: bins}, calculatedDisplay: someCalculation}--&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"foreach: {data: inventory.suppliers, as: 'supplier'}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"foreach: {data: inventory.bins, as: 'bin'}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"text: calculatedDisplay(supplier, bin)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!--/ko--&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyBindings&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;suppliers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...],&lt;/span&gt;
        &lt;span class="na"&gt;bins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...],&lt;/span&gt;
        &lt;span class="na"&gt;someCalculation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;supplier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="cm"&gt;/* return some calculated value based on parameters */&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>braziliandevs</category>
      <category>javascript</category>
      <category>learning</category>
      <category>knockoutjs</category>
    </item>
    <item>
      <title>Como funcionam Bindings de Texto e Aparência no KnockoutJs</title>
      <dc:creator>Lucas Teixeira dos Santos Santana</dc:creator>
      <pubDate>Mon, 11 Nov 2024 21:03:05 +0000</pubDate>
      <link>https://dev.to/santanaluc94/como-funcionam-bindings-de-texto-e-aparencia-no-knockoutjs-369</link>
      <guid>https://dev.to/santanaluc94/como-funcionam-bindings-de-texto-e-aparencia-no-knockoutjs-369</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Este conteúdo é basicamente uma tradução dos materiais originais. A intenção é adquirir aprendizado sobre o KnockoutJs para Magento 2 e criar conteúdo em português sobre KnockouJs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Documentação
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/binding-syntax.html" rel="noopener noreferrer"&gt;The data-bind syntax&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/binding-context.html" rel="noopener noreferrer"&gt;Binding context&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/visible-binding.html" rel="noopener noreferrer"&gt;The "visible" and "hidden" bindings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/text-binding.html" rel="noopener noreferrer"&gt;The "text" binding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/html-binding.html" rel="noopener noreferrer"&gt;The "html" binding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/css-binding.html" rel="noopener noreferrer"&gt;The "class" and "css" bindings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/style-binding.html" rel="noopener noreferrer"&gt;The "style" binding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/attr-binding.html" rel="noopener noreferrer"&gt;The "attr" binding&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Bindings
&lt;/h2&gt;

&lt;p&gt;No KnockoutJs, &lt;em&gt;bindings&lt;/em&gt; são a maneira de conectar a lógica do &lt;em&gt;ViewModel&lt;/em&gt; (os dados e a lógica de negócios) com a &lt;em&gt;View&lt;/em&gt; (HTML). Em resumo, é através dos &lt;em&gt;bindings&lt;/em&gt; que é realizada a interface de usuário refletir automaticamente as mudanças nos seus dados, sem a necessidade de manipular diretamente o DOM.&lt;/p&gt;

&lt;p&gt;Os bindings no KnockoutJs funcionam através do atributo &lt;code&gt;data-bind&lt;/code&gt; em elementos HTML. Esse atributo é onde você especifica o binding que deseja usar e os valores associados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Controlando Texto e Aparência
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Visible
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;visible&lt;/code&gt; é usado para controlar a visibilidade de elementos HTML com base no valor de um &lt;em&gt;observable&lt;/em&gt; da sua &lt;em&gt;ViewModel&lt;/em&gt;. Ele permite mostrar ou ocultar elementos com base em uma condição específica definida na sua &lt;em&gt;ViewModel&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"visible: isContentVisible"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este parágrafo está visível se isContentVisible for true.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando acondição é um valor semelhante a &lt;code&gt;false&lt;/code&gt; (&lt;code&gt;false&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt; ou &lt;code&gt;undefined&lt;/code&gt;), a vinculação &lt;code&gt;visible&lt;/code&gt; define o estilo como &lt;code&gt;none&lt;/code&gt;, fazendo com que ele fique oculto. Isso tem prioridade sobre qualquer estilo de exibição que se pode definir usando CSS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hidden
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;hidden&lt;/code&gt; é usado para ocultar elementos HTML com base no valor de um &lt;em&gt;observable&lt;/em&gt; da sua &lt;em&gt;ViewModel&lt;/em&gt;. Ao contrário do binding &lt;code&gt;*visible*&lt;/code&gt;, que controla a visibilidade dos elementos, o binding &lt;code&gt;*hidden*&lt;/code&gt; oculta os elementos da interface do usuário quando a condição especificada é atendida.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"hidden: isContentHidden"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este parágrafo está oculto se isContentHidden for true.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Text
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;text&lt;/code&gt; é usado para atualizar o conteúdo de elementos HTML com o valor de um &lt;em&gt;observable&lt;/em&gt; da sua &lt;em&gt;ViewModel&lt;/em&gt;. Ele permite que seja insirido o texto de um &lt;em&gt;observable&lt;/em&gt; diretamente no elemento HTML, garantindo que qualquer alteração no valor do &lt;em&gt;observable&lt;/em&gt; seja refletida automaticamente no texto exibido.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"text: message"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este parágrafo exibirá o conteúdo do observable 'message'.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"text: 'Total: $' + totalAmount() + ' USD'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este parágrafo exibirá o total formatado com base no valor do observable 'totalAmount'.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"text: 'Olá, ' + userName()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este parágrafo saudará o usuário com base no valor do observable 'userName'.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se este parâmetro for um valor &lt;em&gt;observable&lt;/em&gt;, a vinculação atualizará o texto do elemento sempre que o valor for alterado. Se o parâmetro não for &lt;em&gt;observable&lt;/em&gt;, ele definirá o texto do elemento apenas uma vez e não o atualizará novamente posteriormente.&lt;/p&gt;

&lt;p&gt;Se o valor fornecido for algo diferente de um número ou uma &lt;em&gt;string,&lt;/em&gt; o texto exibido será equivalente a &lt;code&gt;yourParameter.toString()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Como essa ligação define seu valor de texto usando um nó de texto, é seguro definir qualquer valor de string sem arriscar HTML ou injeção de script.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTML
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;html&lt;/code&gt; é usado para inserir conteúdo HTML dinâmico em elementos da sua interface do usuário. Ele permite que seja atualizado o conteúdo de um elemento com o HTML gerado a partir de um &lt;em&gt;observable&lt;/em&gt; ou de uma expressão da sua &lt;em&gt;ViewModel&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"html: dynamicHtml"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este parágrafo exibirá o conteúdo HTML do observable 'dynamicHtml'.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O KnockoutJs limpa o conteúdo anterior e, em seguida, define o conteúdo do elemento para o valor do parâmetro usando a função html do jQuery ou analisando a &lt;em&gt;string&lt;/em&gt; em nós HTML e anexando cada nó como um filho do elemento, se o jQuery não estiver disponível.&lt;/p&gt;

&lt;p&gt;Se este parâmetro for um &lt;em&gt;observable&lt;/em&gt;, a ligação atualizará o conteúdo do elemento sempre que o valor for alterado. Se o parâmetro não for &lt;em&gt;observable&lt;/em&gt;, ele definirá o conteúdo do elemento apenas uma vez e não o atualizará novamente posteriormente.&lt;/p&gt;

&lt;p&gt;Se o valor fornecido for algo diferente de um número ou uma &lt;em&gt;string,&lt;/em&gt; o texto exibido será equivalente a &lt;code&gt;yourParameter.toString()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Class
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;class&lt;/code&gt; é usado para controlar as classes CSS aplicadas a elementos HTML com base no valor de um &lt;em&gt;observable&lt;/em&gt; ou de uma expressão da sua &lt;em&gt;ViewModel&lt;/em&gt;. Isso permite que seja alterado dinamicamente as classes CSS de um elemento com base em diferentes condições ou estados do seu aplicativo. Uma classe não é um nome de identificador legal, o correto para atribuir uma classe a um elemento HTML é colocar o nome do identificador entre aspas para que se torne uma &lt;em&gt;string&lt;/em&gt; literal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"class: { 'active': isActive, 'highlight': shouldHighlight }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este parágrafo terá as classes 'active' e 'highlight' com base nos valores dos observables 'isActive' e 'shouldHighlight'.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"class: { 'error': hasError(), 'warning': hasWarning() }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este parágrafo terá a classe 'error' se hasError() for true, e terá a classe 'warning' se hasWarning() for true.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"class: 'static-class dynamic-class'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este parágrafo terá a classe 'static-class' e 'dynamic-class' aplicadas a ele.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O valor do parâmetro deve ser uma &lt;em&gt;string&lt;/em&gt; que corresponda à classe(s) CSS que seria desejado adicionar ao elemento. Se o parâmetro fizer referência a um &lt;em&gt;observable&lt;/em&gt;, a associação atualizará as classes sempre que o valor for alterado, removendo quaisquer classes adicionadas anteriormente e adicionando a classe ou classes do novo valor.&lt;/p&gt;

&lt;h3&gt;
  
  
  CSS
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;css&lt;/code&gt; é usado para aplicar estilos CSS dinamicamente a elementos HTML com base no valor de um &lt;em&gt;observable&lt;/em&gt; ou de uma expressão da sua &lt;em&gt;ViewModel&lt;/em&gt;. Isso permite que seja alterado os estilos visuais de um elemento com base em diferentes condições ou estados do seu aplicativo. É possível definir várias classes CSS com base na mesma condição colocando os nomes entre aspas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"css: { 'active': isActive, 'highlight': shouldHighlight }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este parágrafo terá os estilos CSS 'active' e 'highlight' com base nos valores dos observables 'isActive' e 'shouldHighlight'.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"css: { 'error': hasError(), 'warning': hasWarning() }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este parágrafo terá o estilo 'error' se hasError() for true, e terá o estilo 'warning' se hasWarning() for true.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"css: 'static-style dynamic-style'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este parágrafo terá o estilo 'static-style' e 'dynamic-style' aplicados a ele.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deve ser passado um objeto JavaScript no qual os nomes das propriedades são suas classes CSS e seus valores são avaliados como &lt;code&gt;true&lt;/code&gt; ou &lt;code&gt;false&lt;/code&gt;, dependendo se a classe deve ser aplicada no momento.&lt;/p&gt;

&lt;p&gt;Se o parâmetro fizer referência a um valor &lt;em&gt;observable&lt;/em&gt;, a ligação adicionará ou removerá a classe CSS sempre que o &lt;em&gt;observable&lt;/em&gt; for alterado. Se o parâmetro não fizer referência a um &lt;em&gt;observable&lt;/em&gt;, ele adicionará ou removerá a classe apenas uma vez e não o fará novamente posteriormente.&lt;/p&gt;

&lt;h3&gt;
  
  
  Style
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;style&lt;/code&gt; é usado para aplicar estilos CSS inline a elementos HTML com base no valor de um &lt;em&gt;observable&lt;/em&gt; ou de uma expressão da sua &lt;em&gt;ViewModel&lt;/em&gt;. Isso permite que seja alterado os estilos visuais de um elemento diretamente em linha, com base em diferentes condições ou estados do seu aplicativo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"style: { 'color': textColor(), 'font-size': fontSize() + 'px' }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este parágrafo terá cores e tamanhos de fonte diferentes com base nos valores dos observables 'textColor' e 'fontSize'.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"style: { 'color': textColor(), 'font-size': fontSize() + 'px' }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este parágrafo terá cores e tamanhos de fonte diferentes com base nos valores dos observables 'textColor' e 'fontSize'.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"style: { 'width': width() + 'px', 'height': height() + 'px' }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este parágrafo terá largura e altura diferentes com base nos valores dos observables 'width' e 'height'.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"style: 'color: red; background-color: ' + bgColor()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este parágrafo terá cor de texto vermelha e cor de fundo dinâmica com base no valor do observable 'bgColor'.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deve ser passado um objeto JavaScript no qual os nomes das propriedades correspondem aos nomes dos estilos e os valores correspondem aos valores dos estilos que é desejado aplicar.&lt;/p&gt;

&lt;p&gt;Se o parâmetro fizer referência a um &lt;em&gt;observable&lt;/em&gt;, a ligação atualizará os estilos sempre que o &lt;em&gt;observable&lt;/em&gt; for alterado. Se o parâmetro não fizer referência a um &lt;em&gt;observable&lt;/em&gt;, ele definirá os estilos apenas uma vez e não os atualizará posteriormente.&lt;/p&gt;

&lt;p&gt;Se é desejado aplicar um estilo cujo nome não é um identificador JavaScript legal (porque contém um hífen ou algo do genêro), é possível colocá-lo entre aspas ou usar o nome com o estilo &lt;em&gt;camelCase&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;{ 'font-weight': someValue }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;{ fontWeight: someValue }&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se aplicar um valor numérico simples a um estilo que requer uma unidade, o KnockoutJs acrescentará &lt;code&gt;px&lt;/code&gt; ao valor antes de definir o estilo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attr
&lt;/h3&gt;

&lt;p&gt;O &lt;em&gt;binding&lt;/em&gt; &lt;code&gt;attr&lt;/code&gt; é usado para definir ou atualizar atributos HTML em elementos com base no valor de um &lt;em&gt;observable&lt;/em&gt; ou de uma expressão da &lt;em&gt;ViewModel&lt;/em&gt;. Isso permite que seja alterado os atributos de elementos HTML de forma dinâmica, com base em diferentes condições ou estados do seu aplicativo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"attr: { 'disabled': isDisabled(), 'placeholder': inputPlaceholder }"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"attr: { 'src': 'images/' + imageName(), 'alt': 'Imagem ' + imageIndex() }"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"attr: { 'href': 'https://www.exemplo.com/' + pageLink() }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Clique aqui&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"attr: { 'data-something': someValue }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deve ser passado um objeto JavaScript no qual os nomes das propriedades correspondem aos nomes dos atributos e os valores correspondem aos valores dos atributos que seja desejado aplicar.&lt;/p&gt;

&lt;p&gt;Se o parâmetro fizer referência a um &lt;em&gt;observable&lt;/em&gt;, a ligação atualizará o atributo sempre que o &lt;em&gt;observable&lt;/em&gt; for alterado. Se o parâmetro não fizer referência a um &lt;em&gt;observable&lt;/em&gt;, ele definirá o atributo apenas uma vez e não o atualizará posteriormente.&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>javascript</category>
      <category>knockoutjs</category>
      <category>learning</category>
    </item>
    <item>
      <title>Como funcionam Bindings no KnockoutJs</title>
      <dc:creator>Lucas Teixeira dos Santos Santana</dc:creator>
      <pubDate>Mon, 04 Nov 2024 12:12:39 +0000</pubDate>
      <link>https://dev.to/santanaluc94/como-funcionam-bindings-no-knockoutjs-5328</link>
      <guid>https://dev.to/santanaluc94/como-funcionam-bindings-no-knockoutjs-5328</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Este conteúdo é basicamente uma tradução dos materiais originais. A intenção é adquirir aprendizado sobre o KnockoutJs para Magento 2 e criar conteúdo em português sobre KnockouJs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Documentação
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/binding-syntax.html" rel="noopener noreferrer"&gt;The data-bind syntax&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/binding-context.html" rel="noopener noreferrer"&gt;Binding context&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bindings
&lt;/h2&gt;

&lt;p&gt;No KnockoutJs, &lt;em&gt;bindings&lt;/em&gt; são a maneira de conectar a lógica do &lt;em&gt;ViewModel&lt;/em&gt; (os dados e a lógica de negócios) com a &lt;em&gt;View&lt;/em&gt; (HTML). Em resumo, é através dos &lt;em&gt;bindings&lt;/em&gt; que é realizada a interface de usuário refletir automaticamente as mudanças nos seus dados, sem a necessidade de manipular diretamente o DOM.&lt;/p&gt;

&lt;p&gt;Os bindings no KnockoutJs funcionam através do atributo &lt;code&gt;data-bind&lt;/code&gt; em elementos HTML. Esse atributo é onde você especifica o binding que deseja usar e os valores associados.&lt;/p&gt;

&lt;p&gt;O atributo &lt;code&gt;data-bind&lt;/code&gt; não é nativo do HTML, embora seja perfeitamente aceitável (é estritamente compatível com HTML 5 e não causa problemas com HTML 4. Mas como o navegador não reconhece esse atributo por padrão, é preciso ativar o Knockout para que ele tenha efeito.&lt;/p&gt;

&lt;h3&gt;
  
  
  Binding syntax
&lt;/h3&gt;

&lt;p&gt;O sistema de vinculação declarativa do KnockoutJs fornece uma maneira concisa e poderosa de vincular dados à IU. Geralmente é fácil e óbvio vincular-se a propriedades de dados simples ou usar uma ligação única. Para ligações mais complexas, ajuda a compreender melhor o comportamento e a sintaxe do sistema de ligação do KnockoutJs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;Today's message is: &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"text: myMessage"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- related bindings: valueUpdate is a parameter for value --&amp;gt;&lt;/span&gt;
Your value: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"value: someValue, valueUpdate: 'afterkeydown'"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
 
&lt;span class="c"&gt;&amp;lt;!-- unrelated bindings --&amp;gt;&lt;/span&gt;
Cellphone: &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"value: cellphoneNumber, enable: hasCellphone"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uma ligação consiste em dois itens, o nome e o valor da ligação, separados por dois pontos. Um elemento pode incluir múltiplas ligações (relacionadas ou não), com cada ligação separada por uma vírgula. Os dados que estão sendo usados nas ligações atuais podem ser referenciados por um objeto. Este objeto é chamado de &lt;strong&gt;contexto de ligação&lt;/strong&gt; (&lt;em&gt;binding context&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;O valor de ligação pode ser um único valor, variável ou literal ou quase qualquer expressão JavaScript válida.&lt;/p&gt;

&lt;p&gt;As vinculações podem incluir qualquer quantidade de espaços em branco (espaços, tabulações e novas linhas), então é possível usá-los para organizar suas vinculações como desejar.&lt;/p&gt;

&lt;p&gt;As ligações podem incluir comentários no estilo JavaScript (&lt;code&gt;//...&lt;/code&gt; e &lt;code&gt;/*...*/&lt;/code&gt;). Por exemplo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Caso seja especificado uma vinculação sem um valor, o KnockoutJs dará à vinculação o valor &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A hierarquia de contexto é criada e gerenciada automaticamente pelo KnockoutJS. A lista a seguir lista os diferentes tipos de contextos de ligação fornecidos pelo KO.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variável de Contexto&lt;/th&gt;
&lt;th&gt;Descrição&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$root&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Esta propriedade sempre se refere ao &lt;em&gt;ViewModel&lt;/em&gt; de nível superior. Isso torna possível acessar métodos de nível superior para manipular &lt;em&gt;ViewModel&lt;/em&gt;. Geralmente esse é o objeto passado para &lt;code&gt;ko.applyBindings&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$data&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Esta propriedade é muito parecida com a palavra-chave &lt;code&gt;this&lt;/code&gt; do Javascript. A propriedade &lt;code&gt;$data&lt;/code&gt; em um contexto de ligação refere-se ao objeto &lt;em&gt;ViewModel&lt;/em&gt; para o contexto atual.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$index&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Esta propriedade contém o índice de um item atual de um &lt;em&gt;array&lt;/em&gt; dentro de um &lt;em&gt;loop&lt;/em&gt; &lt;em&gt;foreach&lt;/em&gt;. O valor de &lt;code&gt;$index&lt;/code&gt; mudará automaticamente conforme e quando a matriz &lt;em&gt;Observable&lt;/em&gt; subjacente for atualizada. Obviamente, este contexto está disponível apenas para ligações &lt;em&gt;foreach&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$parent&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Esta propriedade refere-se ao objeto &lt;em&gt;ViewModel&lt;/em&gt; pai. Isso é útil quando se deseja acessar propriedades externas do &lt;em&gt;ViewModel&lt;/em&gt; de dentro de um &lt;em&gt;loop&lt;/em&gt; aninhado.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$parentContext&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Esta propriedade é diferente da &lt;code&gt;$parent&lt;/code&gt;, pois a &lt;code&gt;$parent&lt;/code&gt; refere-se a dados. Considerando que &lt;code&gt;$parentContext&lt;/code&gt; refere-se ao contexto de ligação.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$rawdata&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Este contexto contém o valor bruto do &lt;em&gt;ViewModel&lt;/em&gt; na situação atual. Esta propriedade se assemelha a &lt;code&gt;$data&lt;/code&gt;, mas a diferença é que, se o &lt;em&gt;ViewModel&lt;/em&gt; for agrupado em &lt;em&gt;Observable&lt;/em&gt;, então &lt;code&gt;$data&lt;/code&gt; será apenas desembrulhado. O &lt;em&gt;ViewModel&lt;/em&gt; e &lt;code&gt;$rawdata&lt;/code&gt; tornam-se dados observáveis reais.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$component&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Este contexto é usado para se referir ao &lt;em&gt;ViewModel&lt;/em&gt; daquele componente, quando está dentro de um determinado componente.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;$componentTemplateNodes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;É uma representação de uma matriz de nós DOM passados para esse componente específico quando se está dentro de um modelo de componente específico.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;O nome da ligação geralmente deve corresponder a uma ligação registrada (integrada ou personalizada) ou ser um parâmetro para outra ligação. Se o nome não corresponder a nenhum deles, o KnockoutJs irá ignorá-lo (sem qualquer erro ou aviso). Portanto, se uma ligação não funcionar, primeiro verifique se o nome está correto.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O valor de ligação pode ser um único valor, variável ou literal ou quase qualquer expressão JavaScript válida. Aqui estão exemplos de vários valores de ligação:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- variable (usually a property of the current view model --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"visible: shouldShowMessage"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
 
&lt;span class="c"&gt;&amp;lt;!-- comparison and conditional, template literals --&amp;gt;&lt;/span&gt;
The item is &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"text: price() &amp;gt; 50 ? `expensive` : `cheap`"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;.
 
&lt;span class="c"&gt;&amp;lt;!-- function call and comparison --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"enable: parseAreaCode(cellphoneNumber()) != '555'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
 
&lt;span class="c"&gt;&amp;lt;!-- function expression --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"click: function (data) { myFunction('param1', data) }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
 
&lt;span class="c"&gt;&amp;lt;!-- object literal (with unquoted and quoted property names) --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;data-bind=&lt;/span&gt;&lt;span class="s"&gt;"with: {emotion: 'happy', 'facial-expression': 'smile'}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>braziliandevs</category>
      <category>learning</category>
      <category>knockoutjs</category>
    </item>
    <item>
      <title>Como funcionam Observables no KnockoutJs</title>
      <dc:creator>Lucas Teixeira dos Santos Santana</dc:creator>
      <pubDate>Mon, 28 Oct 2024 11:47:05 +0000</pubDate>
      <link>https://dev.to/santanaluc94/como-funcionam-observables-no-knockoutjs-1725</link>
      <guid>https://dev.to/santanaluc94/como-funcionam-observables-no-knockoutjs-1725</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Este conteúdo é basicamente uma tradução dos materiais originais. A intenção é adquirir aprendizado sobre o KnockoutJs para Magento 2 e criar conteúdo em português sobre KnockouJs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Documentação
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/observables.html" rel="noopener noreferrer"&gt;KnockoutJs: Observables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/observableArrays.html" rel="noopener noreferrer"&gt;KnockoutJs: Observables Arrays&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/computedObservables.html" rel="noopener noreferrer"&gt;KnockoutJs: Computed Observables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/computed-writable.html" rel="noopener noreferrer"&gt;KnockoutJs: Writable Computed Observables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/computed-pure.html" rel="noopener noreferrer"&gt;KnockoutJs: Pure Computed Observables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/computedObservables.html" rel="noopener noreferrer"&gt;KnockoutJs: Computed Observables&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Observables
&lt;/h2&gt;

&lt;p&gt;O KnockoutJs introduz o conceito de &lt;em&gt;observables&lt;/em&gt;, que são propriedades que podem ser monitoradas e atualizadas automaticamente quando seus valores mudam. Essa funcionalidade permite que a interface do usuário reaja dinamicamente a alterações nos dados do &lt;em&gt;Model&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Para criar um observable no KnockoutJs, é possível utilizar a função &lt;code&gt;ko.observable()&lt;/code&gt; e atribuir um valor inicial a ela. Para acessar o valor atual de um &lt;em&gt;observable&lt;/em&gt;, é possível tratá-lo como uma função. Para só observar algo sem um valor inicial, basta chamar a propriedade &lt;em&gt;Observable&lt;/em&gt; sem parâmetros.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;myObservable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Inicial&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;myObservable&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Irá imprimir 'Inicial'&lt;/span&gt;

&lt;span class="nf"&gt;myObservable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Novo valor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;myObservable&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Irá imprimir 'Novo valor'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ko.isObservable&lt;/code&gt;: retorna &lt;code&gt;true&lt;/code&gt; para &lt;em&gt;observables&lt;/em&gt;, &lt;em&gt;observables arrays&lt;/em&gt; e todos os computed observables;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ko.isWritableObservable&lt;/code&gt;: retorna &lt;code&gt;true&lt;/code&gt; para &lt;em&gt;observables&lt;/em&gt;, &lt;em&gt;observable arrays&lt;/em&gt; e &lt;em&gt;writable&lt;/em&gt; &lt;em&gt;computed observables&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Subscriptions
&lt;/h3&gt;

&lt;p&gt;As &lt;em&gt;subscriptions&lt;/em&gt; em &lt;em&gt;observables&lt;/em&gt; são mecanismos que permitem que seja notificado sempre que o valor de um &lt;em&gt;observable&lt;/em&gt; é alterado. Elas são essenciais para acompanhar as mudanças nos &lt;em&gt;observables&lt;/em&gt; e reagir a essas mudanças, atualizando a interface do usuário ou executando outras ações quando necessário.&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;subscribe()&lt;/code&gt; ***&lt;em&gt;recebe uma função de *callback&lt;/em&gt; que será executada sempre que o valor do &lt;em&gt;observable&lt;/em&gt; for modificado. A função de &lt;em&gt;callback&lt;/em&gt; recebe como argumento o novo valor do &lt;em&gt;observable&lt;/em&gt;. Esta função aceita três parâmetros: &lt;em&gt;callback&lt;/em&gt; é a função que é chamada sempre que a notificação acontece, &lt;em&gt;target&lt;/em&gt; (opcional) define o valor disso na função &lt;em&gt;callback&lt;/em&gt; e &lt;em&gt;event&lt;/em&gt; (opcional; o padrão é &lt;code&gt;change&lt;/code&gt;) é o nome do evento para receber notificação.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;myObservable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Criando uma subscription no observable&lt;/span&gt;
&lt;span class="nx"&gt;myObservable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Novo valor do observable:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;change&lt;/code&gt;&lt;strong&gt;:&lt;/strong&gt; Esse é o evento padrão que aciona a subscription sempre que o valor do &lt;em&gt;observable&lt;/em&gt; é alterado. É o evento mais comum e é usado quando nenhum outro evento é especificado explicitamente;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;beforeChange&lt;/code&gt;&lt;strong&gt;:&lt;/strong&gt; Esse evento é acionado antes que o valor do &lt;em&gt;observable&lt;/em&gt; seja alterado. A função de &lt;em&gt;callback&lt;/em&gt; receberá dois argumentos: o valor atual do &lt;em&gt;observable&lt;/em&gt; e o valor proposto (novo) que será atribuído ao &lt;em&gt;observable&lt;/em&gt;. Isso permite que seja executado ações com base no valor atual antes de ser alterado;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;afterChange&lt;/code&gt;&lt;strong&gt;:&lt;/strong&gt; Esse evento é acionado após o valor do observable ser alterado. A função de callback receberá dois argumentos: o valor anterior do observable (antes da alteração) e o novo valor que foi atribuído ao observable. É útil quando você precisa reagir a uma mudança específica após ela ter ocorrido.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;arrayChange&lt;/code&gt;&lt;strong&gt;:&lt;/strong&gt; Esse evento é específico para Observables Arrays. Ele é acionado quando há uma alteração em um array observable, como adição, remoção ou substituição de itens no array. A função de callback recebe quatro argumentos: os itens afetados (&lt;strong&gt;&lt;code&gt;added&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;deleted&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;status&lt;/code&gt;&lt;/strong&gt; e &lt;strong&gt;&lt;code&gt;index&lt;/code&gt;&lt;/strong&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Outro ponto importante e que é possível armazenar a subscription em uma variável e, se necessário cancelar a inscrição usando o método &lt;code&gt;dispose()&lt;/code&gt;. Isso é útil quando se deseja desativar temporariamente ou permanentemente a atualização da interface do usuário em resposta a alterações nos observables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myObservable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myObservable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Novo valor do observable:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;myObservable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// A subscription será acionada e imprimirá "Novo valor do observable: 42" no console.&lt;/span&gt;

&lt;span class="c1"&gt;// Cancelando a subscription&lt;/span&gt;
&lt;span class="nx"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nf"&gt;myObservable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Nada será impresso no console, pois a subscription foi cancelada.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Métodos para determinar tipos de observables&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;isObservable()&lt;/code&gt;: Este método é usado para verificar se um valor é um &lt;em&gt;observable&lt;/em&gt;. Ele retorna &lt;code&gt;true&lt;/code&gt; se o valor for um &lt;em&gt;observable&lt;/em&gt; (&lt;em&gt;observable, observableArray&lt;/em&gt;, &lt;em&gt;computed&lt;/em&gt; ou &lt;em&gt;writable computed&lt;/em&gt;), e &lt;code&gt;false&lt;/code&gt; caso contrário.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isWritableObservable()&lt;/code&gt;: Este método verifica se um valor é um &lt;em&gt;observable&lt;/em&gt; gravável (&lt;em&gt;writable observable&lt;/em&gt;). Ele retorna &lt;code&gt;true&lt;/code&gt; se o valor for um writable observable e &lt;code&gt;false&lt;/code&gt; caso contrário;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isComputed()&lt;/code&gt;: Este método é usado para verificar se um valor é um &lt;em&gt;Computed Observable&lt;/em&gt;. Ele retorna &lt;code&gt;true&lt;/code&gt; se o valor for um &lt;em&gt;Computed Observable&lt;/em&gt; e &lt;code&gt;false&lt;/code&gt; caso contrário;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isPureComputed()&lt;/code&gt;: Este método verifica se um valor é um &lt;em&gt;Pure Computed Observable&lt;/em&gt;. Um &lt;em&gt;Pure Computed Observable&lt;/em&gt; é aquele que depende apenas de outros &lt;em&gt;pure observables&lt;/em&gt; e não possui lógica interna de gravação. Ele retorna &lt;code&gt;true&lt;/code&gt; se o valor for um &lt;em&gt;Pure Computed Observable&lt;/em&gt; e &lt;code&gt;false&lt;/code&gt; caso contrário.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Observables Arrays
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Observables Arrays&lt;/em&gt; são uma extensão dos observables e são usados para lidar com listas de dados que precisam ser observáveis. Ao contrário de um &lt;em&gt;array&lt;/em&gt; JavaScript padrão, um &lt;em&gt;Observable Array&lt;/em&gt; permite que se acompanhe automaticamente as mudanças nos dados da lista e atualize a interface do usuário de forma reativa.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;myObservableArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observableArray&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Maçã&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Banana&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Laranja&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;myObservable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Limão&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Os &lt;em&gt;Observables Arrays&lt;/em&gt; possuem métodos específicos que permitem adicionar, remover e manipular itens de forma reativa. Alguns desses métodos são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;indexOf(value)&lt;/code&gt;: Retorna o índice do primeiro item do &lt;em&gt;array&lt;/em&gt; que é igual ao seu parâmetro, ou o valor &lt;code&gt;-1&lt;/code&gt; se nenhum valor correspondente for encontrado.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;push(item)&lt;/code&gt;: Adiciona um novo item ao final do &lt;em&gt;array&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pop()&lt;/code&gt;: Remove e retorna o último item do &lt;em&gt;array;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;shift()&lt;/code&gt;: Remove e retorna o primeiro item do &lt;em&gt;array&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;unshift(item)&lt;/code&gt;: Adiciona um novo item ao início do &lt;em&gt;array&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;remove(item)&lt;/code&gt;: Remove um item específico do &lt;em&gt;array&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;removeAll([parametro])&lt;/code&gt;: Remove todos os itens do &lt;em&gt;array&lt;/em&gt;, podendo receber um parametro em forma de &lt;em&gt;array&lt;/em&gt; que removera os itens dentro do(s) parametro(s) passados;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;replace(oldItem, newItem)&lt;/code&gt;: Substitui o item passado no primeiro parâmetro pelo segundo parâmetro;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;reverse()&lt;/code&gt;: Altera a ordem dos itens do &lt;em&gt;array&lt;/em&gt; original e atualiza a interface do usuário para refletir a nova ordem;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;reversed()&lt;/code&gt;: Retorna uma cópia do array revertida;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;splice(index, count, items)&lt;/code&gt;: Permite adicionar ou remover itens em uma posição específica do &lt;em&gt;array;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;slice()&lt;/code&gt;: Retorna uma cópia de um subconjunto do &lt;em&gt;array&lt;/em&gt;, começando no índice &lt;code&gt;start&lt;/code&gt; e indo até o índice &lt;code&gt;end-1&lt;/code&gt;. Os valores de &lt;code&gt;start&lt;/code&gt; e &lt;code&gt;end&lt;/code&gt; são opcionais, e se não forem fornecidos;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sort()&lt;/code&gt;: Determina a ordem dos itens. Se a função não for fornecida, o método ordena os itens em ordem alfabética crescente (para &lt;em&gt;strings&lt;/em&gt;) ou em ordem numérica crescente (para números);&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sorted()&lt;/code&gt;: Retorna uma &lt;strong&gt;cópia&lt;/strong&gt; do &lt;em&gt;array&lt;/em&gt; ordenado. É preferível ao método &lt;code&gt;sort()&lt;/code&gt;, caso seja necessário não alterar o &lt;em&gt;observable array&lt;/em&gt; original, mas precisa exibi-lo em uma ordem específica;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para funções que modificam o conteúdo da matriz, como &lt;em&gt;push&lt;/em&gt; e &lt;em&gt;splice&lt;/em&gt;, os métodos de KO acionam automaticamente o mecanismo de rastreamento de dependência para que todos os ouvintes registrados sejam notificados da alteração e sua interface seja atualizada automaticamente, o que significa que há uma diferença significativa entre usar Métodos de KO (&lt;code&gt;observableArray.push(...)&lt;/code&gt;, etc) e métodos de &lt;em&gt;array&lt;/em&gt; nativos de JavaScript (&lt;code&gt;observableArray().push(...)&lt;/code&gt;), já que os últimos não enviam nenhuma notificação aos assinantes do &lt;em&gt;array&lt;/em&gt; de que seu conteúdo foi mudado.&lt;/p&gt;

&lt;p&gt;Embora seja possível utilizar &lt;em&gt;subscribe&lt;/em&gt; e acessar um &lt;em&gt;observableArray&lt;/em&gt; como qualquer outro observável, o KnockoutJs também fornece um método super rápido para descobrir como um &lt;em&gt;array&lt;/em&gt; observável foi alterado (quais itens acabaram de ser adicionados, excluídos ou movidos). É possível se inscrever nas alterações de &lt;em&gt;array&lt;/em&gt; da seguinte maneira:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obsArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observableArray&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Maçã&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Banana&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Laranja&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nx"&gt;obsArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;thisArg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;arrayChange&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Computed Observables&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Computed Observables&lt;/em&gt; são funções que dependem de um ou mais &lt;em&gt;observables&lt;/em&gt; e serão atualizadas automaticamente sempre que qualquer uma dessas dependências alterar. A função será chamada uma vez a cada vez que qualquer uma de suas dependências alterar, e qualquer valor que retornar será passado para os &lt;em&gt;observables&lt;/em&gt;, como elementos de interface do usuário ou outros &lt;em&gt;computed observables&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A principal diferença entre os &lt;em&gt;Computed Observables&lt;/em&gt; e os &lt;em&gt;Observables&lt;/em&gt; é que os &lt;em&gt;Computed Observables&lt;/em&gt; não armazenam diretamente um valor; em vez disso, eles dependem de outros &lt;em&gt;observables&lt;/em&gt; para calcular seu valor. Isso significa que o valor de um &lt;em&gt;Computed Observable&lt;/em&gt; é sempre atualizado automaticamente quando qualquer um dos &lt;em&gt;observables&lt;/em&gt; de que ele depende é modificado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AppViewModel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Métodos de um Computed Observable&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;dispose()&lt;/code&gt;: Este método é usado para descartar (limpar) um &lt;em&gt;Computed Observable&lt;/em&gt; quando ele não é mais necessário. Ele remove todas as assinaturas e dependências associadas ao &lt;em&gt;Computed Observable&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;extend()&lt;/code&gt;: Este método permite adicionar extensores personalizados a um &lt;em&gt;Computed Observable&lt;/em&gt;. Os extensores são funções que podem modificar o comportamento do &lt;em&gt;Computed Observable;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getDependenciesCount()&lt;/code&gt;: Este método retorna o número de &lt;em&gt;observables&lt;/em&gt; dependentes do &lt;em&gt;Computed Observable&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getDependencies()&lt;/code&gt;: Este método retorna uma matriz contendo os &lt;em&gt;observables&lt;/em&gt; que são dependências do &lt;em&gt;Computed Observable&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getSubscriptionsCount()&lt;/code&gt;: Este método retorna o número de assinaturas atuais do &lt;em&gt;Computed Observable&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isActive()&lt;/code&gt;: Este método retorna um valor booleano que indica se o &lt;em&gt;Computed Observable&lt;/em&gt; está atualmente ativo (um &lt;em&gt;Computed Observable&lt;/em&gt; está ativo se estiver em processo de avaliação devido a uma mudança em suas dependências);&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;peek()&lt;/code&gt;: Este método é semelhante ao operador de parênteses &lt;code&gt;()&lt;/code&gt; usado para acessar o valor atual de um &lt;em&gt;Computed Observable&lt;/em&gt;. No entanto, o método &lt;code&gt;peek&lt;/code&gt; não cria uma dependência entre o &lt;em&gt;Computed Observable&lt;/em&gt; e o local em que é chamado;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;subscribe()&lt;/code&gt;: Este método permite a inscrição para receber notificações sempre que o valor do &lt;em&gt;Computed Observable&lt;/em&gt; for alterado.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  this
&lt;/h3&gt;

&lt;p&gt;O segundo parâmetro para &lt;code&gt;ko.computed&lt;/code&gt; define o valor &lt;code&gt;this&lt;/code&gt; ao avaliar o &lt;em&gt;observable&lt;/em&gt; calculado. Sem passá-lo, não seria possível fazer referência a &lt;code&gt;this.firstName()&lt;/code&gt; ou &lt;code&gt;this.lastName()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Há uma convenção que evita a necessidade de rastrear isso completamente: se o construtor do seu &lt;em&gt;viewmodel&lt;/em&gt; copiar uma referência a &lt;code&gt;this&lt;/code&gt; em uma variável diferente (tradicionalmente chamada de &lt;code&gt;self&lt;/code&gt;), será possível usar &lt;code&gt;self&lt;/code&gt; em todo o seu &lt;em&gt;viewmodel&lt;/em&gt; e não precisa se preocupar com isso redefinido para se referir a outra coisa.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AppViewModel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Smith&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como &lt;code&gt;self&lt;/code&gt; é capturado no fechamento da função, ele permanece disponível e consistente em qualquer função aninhada, como o avaliador do &lt;em&gt;computed observable&lt;/em&gt;. Essa convenção é ainda mais útil quando se trata de manipuladores de eventos.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;Pure&lt;/em&gt; computed observables
&lt;/h3&gt;

&lt;p&gt;Caso um &lt;em&gt;computed observable&lt;/em&gt; simplesmente calcule e retorne um valor com base em algumas dependências observáveis, é melhor declará-lo como &lt;code&gt;ko.pureComputed&lt;/code&gt; em vez de &lt;code&gt;ko.computed&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ko&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pureComputed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando um &lt;em&gt;computed observable&lt;/em&gt; é declarado como &lt;em&gt;pure&lt;/em&gt;, seu avaliador não modifica diretamente outros objetos ou estado, o KnockoutJs pode gerenciar com mais eficiência sua reavaliação e uso de memória. O KnockoutJs irá suspendê-lo ou liberá-lo automaticamente se nenhum outro código tiver uma dependência ativa dele.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writable Computed Observables
&lt;/h3&gt;

&lt;p&gt;Os &lt;em&gt;Writable Computed Observables&lt;/em&gt; são uma extensão dos &lt;em&gt;Computed Observables&lt;/em&gt; que permitem a criação de &lt;em&gt;computed observables&lt;/em&gt; que podem ser atualizados tanto por meio da leitura quanto da gravação. Diferente dos &lt;em&gt;Computed Observables&lt;/em&gt; convencionais, que apenas calculam seu valor com base em outros observables e não armazenam diretamente um valor, os &lt;em&gt;Writable Computed Observables&lt;/em&gt; podem armazenar um valor e também fornecem uma função para atualizar esse valor quando necessário.&lt;/p&gt;

&lt;p&gt;Para criar um &lt;em&gt;Writable Computed Observable&lt;/em&gt;, é necessário utilizar a função &lt;code&gt;ko.computed&lt;/code&gt; com um objeto de configuração que contém duas propriedades principais: &lt;code&gt;read&lt;/code&gt; e &lt;code&gt;write&lt;/code&gt;. A propriedade &lt;code&gt;read&lt;/code&gt; contém a função de cálculo para determinar o valor do &lt;em&gt;observable&lt;/em&gt;, enquanto a propriedade &lt;code&gt;write&lt;/code&gt; contém a função que é chamada quando deseja-se atualizar o valor do &lt;em&gt;observable&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>braziliandevs</category>
      <category>knockoutjs</category>
      <category>learning</category>
    </item>
    <item>
      <title>Introdução ao KnockoutJs</title>
      <dc:creator>Lucas Teixeira dos Santos Santana</dc:creator>
      <pubDate>Mon, 21 Oct 2024 14:17:13 +0000</pubDate>
      <link>https://dev.to/santanaluc94/introducao-ao-knockoutjs-3om4</link>
      <guid>https://dev.to/santanaluc94/introducao-ao-knockoutjs-3om4</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Este conteúdo é basicamente uma tradução dos materiais originais. A intenção é adquirir aprendizado sobre o KnockoutJs para Magento 2 e criar conteúdo em português sobre KnockouJs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Documentação
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/pt-br/dotnet/architecture/maui/mvvm" rel="noopener noreferrer"&gt;Microsoft: MVVM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/documentation/introduction.html" rel="noopener noreferrer"&gt;KnockoutJs: Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://knockoutjs.com/downloads/index.html" rel="noopener noreferrer"&gt;KnockoutJs: Installation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Padrão MVVM
&lt;/h3&gt;

&lt;p&gt;A arquitetura MVVM (Model-View-ViewModel) é um padrão de design de software amplamente utilizado em aplicações de interface de usuário. O MVVM é particularmente útil em aplicações com interfaces de usuário complexas e interativas, pois separa claramente a lógica de negócio do comportamento da interface. Isso facilita a manutenção, testabilidade e escalabilidade do código.&lt;/p&gt;

&lt;p&gt;Quando o usuário interage com a &lt;em&gt;View&lt;/em&gt;, o &lt;em&gt;ViewModel&lt;/em&gt; captura essas ações e atualiza os dados correspondentes no &lt;em&gt;Model&lt;/em&gt;. Quando o &lt;em&gt;Model&lt;/em&gt; é atualizado, o &lt;em&gt;ViewModel&lt;/em&gt; recebe essas alterações e atualiza automaticamente a &lt;em&gt;View&lt;/em&gt;, refletindo as mudanças na interface do usuário. O &lt;em&gt;ViewModel&lt;/em&gt; também pode realizar ações específicas, como enviar requisições ao servidor para buscar ou enviar dados.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Model (Modelo):&lt;/strong&gt; O &lt;em&gt;Model&lt;/em&gt; representa a camada de dados da aplicação. Ele lida com a lógica de negócio, regras de validação, armazenamento e recuperação de dados. O Model geralmente consiste em objetos de dados que representam as entidades e funcionalidades específicas do domínio da aplicação.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;View (Visualização):&lt;/strong&gt; A &lt;em&gt;View&lt;/em&gt; é a camada de apresentação da aplicação, responsável por exibir os dados do &lt;em&gt;Model&lt;/em&gt; e interagir com o usuário. Ela representa a interface gráfica com a qual o usuário interage para visualizar e manipular os dados. Na arquitetura MVVM, a &lt;em&gt;View&lt;/em&gt; é mantida o mais desacoplada possível da lógica de negócio, tornando-a fácil de ser atualizada e substituída.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ViewModel:&lt;/strong&gt; O &lt;em&gt;ViewModel&lt;/em&gt; é a parte central do padrão MVVM. Ele atua como um intermediário entre a &lt;em&gt;View&lt;/em&gt; e o &lt;em&gt;Model&lt;/em&gt;, realizando a comunicação e a ligação de dados bidirecional entre eles. O &lt;em&gt;ViewModel&lt;/em&gt; contém a lógica de apresentação, transformando os dados do &lt;em&gt;Model&lt;/em&gt; em uma forma adequada para exibição na &lt;em&gt;View&lt;/em&gt;. Além disso, o &lt;em&gt;ViewModel&lt;/em&gt; gerencia eventos e respostas do usuário, interagindo com o &lt;em&gt;Model&lt;/em&gt; conforme necessário.&lt;/p&gt;

&lt;h2&gt;
  
  
  KnockoutJs
&lt;/h2&gt;

&lt;p&gt;O Knockout.js é uma biblioteca JavaScript de código aberto que permite a criação de interfaces de usuário dinâmicas e reativas. Ele é especialmente útil para desenvolver aplicações web com interface de usuário complexa e interativa. O KnockoutJs é baseado no padrão de design MVVM (&lt;em&gt;Model-View-ViewModel&lt;/em&gt;), que separa a lógica de negócios (&lt;em&gt;Model&lt;/em&gt;) da apresentação (&lt;em&gt;View&lt;/em&gt;) através de uma camada intermediária chamada &lt;em&gt;ViewModel&lt;/em&gt;. É independente de qualquer outra estrutura.&lt;/p&gt;

&lt;p&gt;O KnockoutJs foi desenvolvido e é mantido como um projeto de código aberto por Steve Sanderson, um funcionário da Microsoft em 5 de julho de 2010.&lt;/p&gt;

&lt;p&gt;KnockoutJs suporta todos os navegadores convencionais - IE 6+, Firefox 3.5+, Chrome, Opera, Safari (desktop/mobile). O atributo &lt;code&gt;data-bind&lt;/code&gt; não é nativo do HTML, embora seja um atributo aceitável (é estritamente compatível com o HTML 5 e não causa problemas com o HTML 4, embora um validador indique que é um atributo não reconhecido). Mas como o navegador não sabe o que isso significa, é necessário ativar o KnockoutJs para fazer efeito.&lt;/p&gt;

&lt;p&gt;Ao usar KnockoutJs, sua camada de &lt;em&gt;view&lt;/em&gt; é simplesmente seu documento HTML com ligações declarativas para vinculá-lo a camada de &lt;em&gt;view-model&lt;/em&gt;. Como alternativa, é possível utilizar &lt;em&gt;models&lt;/em&gt; que geram HTML usando dados de um modelo da camada de &lt;em&gt;view-model&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Basta colocar o bloco de &lt;em&gt;script&lt;/em&gt; na parte inferior de um documento HTML ou colocá-lo na parte superior e agrupar o conteúdo em um manipulador pronto para DOM, como a função &lt;code&gt;$&lt;/code&gt; do &lt;code&gt;jQuery&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ko.applyBindings(myViewModel)&lt;/code&gt;: é um método usado para aplicar o &lt;em&gt;data binding&lt;/em&gt; no KnockoutJs e vincular um &lt;em&gt;ViewModel&lt;/em&gt; (ou &lt;em&gt;Model&lt;/em&gt;) à interface do usuário (&lt;em&gt;View&lt;/em&gt;). Ele conecta o &lt;em&gt;ViewModel&lt;/em&gt; aos elementos HTML no DOM, permitindo que os dados do &lt;em&gt;ViewModel&lt;/em&gt; sejam refletidos automaticamente na interface do usuário e vice-versa. Ao chamar este método, o KnockoutJs percorre o DOM em busca de elementos que possuam as diretivas de &lt;em&gt;data binding&lt;/em&gt; do KnockoutJs e cria as ligações entre esses elementos e as propriedades do &lt;em&gt;ViewModel&lt;/em&gt; especificadas nas diretivas.&lt;/p&gt;

&lt;p&gt;Opcionalmente, é possível passar um segundo parâmetro para definir em qual parte do documento é desejado pesquisar atributos de vinculação de dados. Por exemplo, &lt;code&gt;ko.applyBindings(myViewModel, document.getElementById('someElementId'))&lt;/code&gt;. Isso restringe a ativação ao elemento com ID &lt;code&gt;someElementId&lt;/code&gt; e seus descendentes, o que é útil caso seja desejável ter vários modelos de exibição e associar cada um a uma região diferente da página.&lt;/p&gt;

&lt;h3&gt;
  
  
  Instalação
&lt;/h3&gt;

&lt;p&gt;Basta referenciar o arquivo JavaScript usando uma tag &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; em algum lugar de suas páginas HTML.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'text/javascript'&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'knockout-3.5.1.js'&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obviamente é necessário atualizar o atributo &lt;code&gt;src&lt;/code&gt; para corresponder ao local foi colocado o arquivo baixado.&lt;/p&gt;

&lt;h3&gt;
  
  
  CDN
&lt;/h3&gt;

&lt;p&gt;Para oferecer as velocidades de download mais rápidas, é preferirível referenciar KnockoutJs em um dos seguintes CDNs de terceiros no site oficial do KnockoutJs da &lt;a href="https://knockoutjs.com/downloads/index.html" rel="noopener noreferrer"&gt;guia de instalação&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>braziliandevs</category>
      <category>knockoutjs</category>
      <category>learning</category>
    </item>
    <item>
      <title>Como fazer traduções no Magento 2</title>
      <dc:creator>Lucas Teixeira dos Santos Santana</dc:creator>
      <pubDate>Mon, 08 May 2023 12:24:12 +0000</pubDate>
      <link>https://dev.to/santanaluc94/como-fazer-traducoes-no-magento-2-1ecf</link>
      <guid>https://dev.to/santanaluc94/como-fazer-traducoes-no-magento-2-1ecf</guid>
      <description>&lt;h2&gt;
  
  
  Contextualizando
&lt;/h2&gt;

&lt;h3&gt;
  
  
  O que é i18n?
&lt;/h3&gt;

&lt;p&gt;i18n é um acrônimo que origina-se do inglês "&lt;em&gt;internationalization&lt;/em&gt;", onde 18 é o número de letras entre o primeiro &lt;em&gt;"*i&lt;/em&gt;"&lt;em&gt; e o último &lt;/em&gt;"&lt;em&gt;n&lt;/em&gt;"*. I18n é a prática de desenvolvimento de software de forma a torná-lo capaz de ser adaptado para diferentes idiomas e localidades sem necessidade de alteração do código-fonte. Isso é feito através da separação das strings de texto presentes no código em arquivos de idioma separados, que podem ser facilmente alterados sem afetar o código em si.&lt;/p&gt;

&lt;h3&gt;
  
  
  Como o Magento 2 trabalha com traduções?
&lt;/h3&gt;

&lt;p&gt;O Magento 2 permite que a localidade (idioma) seja alterada para a loja, e através da localidade selecionada o Magento busca e aplica as traduções através dos dicionarios na seguinte sequência:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Traduções através do banco de dados (traduções localizadas no banco de dados possuem preferência e substituem as traduções armazenadas em outros locais;&lt;/li&gt;
&lt;li&gt;Traduções através do tema:

&lt;ol&gt;
&lt;li&gt;Tema pai (&lt;code&gt;app/design/{area}/{ParentTheme}&lt;/code&gt;);&lt;/li&gt;
&lt;li&gt;Tema atual (&lt;code&gt;app/design/{area}/{CurrentTheme}&lt;/code&gt;);&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Traduções através do pacote de linguagem (&lt;code&gt;app/i18n&lt;/code&gt;);&lt;/li&gt;

&lt;li&gt;Traduções através do módulo (&lt;code&gt;app/code/{Vendor}/{Module}/i18n&lt;/code&gt; ou &lt;code&gt;vendor/{vendor}/module-{module}/i18n&lt;/code&gt;).&lt;/li&gt;

&lt;/ol&gt;




&lt;h2&gt;
  
  
  Código para tradução
&lt;/h2&gt;

&lt;h3&gt;
  
  
  String &lt;strong&gt;em arquivos PHP&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Para garantir que uma &lt;em&gt;string&lt;/em&gt; seja adicionada ao dicionário e traduzida, deve ser utilizado o método &lt;code&gt;__('{string content}')&lt;/code&gt; ao gerar uma &lt;em&gt;string&lt;/em&gt; em um arquivo &lt;strong&gt;phtml&lt;/strong&gt; ou &lt;strong&gt;PHP&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?=&lt;/span&gt; &lt;span class="nf"&gt;__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{Custom string}'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;?=&lt;/span&gt; &lt;span class="nf"&gt;__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{Custom string with %1}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;É recomendado, mas não obrigatório, que não coloque variáveis dentro das strings que irão nas funções &lt;code&gt;__()&lt;/code&gt; ou &lt;code&gt;Phrase()&lt;/code&gt;. O scanner que coleta as frases do código não pode interpretar e coletar o valor da variável quando está nesses locais. Em vez disso, você deve colocar o texto completo na função &lt;code&gt;__()&lt;/code&gt; ou &lt;code&gt;Phrase()&lt;/code&gt;. Se você precisar especificar uma variável nesses casos, certifique-se de que ela seja traduzida corretamente sempre que for definida como uma string literal.&lt;/p&gt;

&lt;h3&gt;
  
  
  String &lt;strong&gt;em arquivos XML&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Para garantir que uma &lt;em&gt;string&lt;/em&gt; seja adicionada ao dicionário e traduzida, deve ser utilizado o atributo &lt;code&gt;translate=true&lt;/code&gt; ao gerar uma &lt;em&gt;string&lt;/em&gt; em um arquivo &lt;strong&gt;XML&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;tag&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"{tag_name}"&lt;/span&gt; &lt;span class="na"&gt;xsi:type=&lt;/span&gt;&lt;span class="s"&gt;"string"&lt;/span&gt; &lt;span class="na"&gt;translate=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{Custom string}&lt;span class="nt"&gt;&amp;lt;/item&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As &lt;em&gt;strings&lt;/em&gt; traduzidas que se originam de arquivos &lt;strong&gt;XML&lt;/strong&gt; não serão renderizadas, a menos que sejam chamadas com um método &lt;code&gt;__(${var})&lt;/code&gt; em arquivos &lt;strong&gt;PHP&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;paramName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{tag_name}'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  String &lt;strong&gt;em arquivos JS&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Para garantir que uma &lt;em&gt;string&lt;/em&gt; seja adicionada ao dicionário e traduzida, deve ser importada a biblioteca &lt;code&gt;mage/translate&lt;/code&gt; no arquivo &lt;strong&gt;JS&lt;/strong&gt; e usar a função &lt;code&gt;$.mage.__('{string}')&lt;/code&gt; ou &lt;code&gt;$t('{string}')&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;define &lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jquery&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mage/translate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{Custom string}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;$t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{Custom string}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{Custom string with %1}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;%1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nf"&gt;$t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{Custom string with %1}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;%1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  String &lt;strong&gt;em arquivos de email&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Caso seja necessário traduzir &lt;em&gt;strings&lt;/em&gt; em &lt;em&gt;templates&lt;/em&gt; de e-mail personalizados, basta adicionar as &lt;em&gt;strings&lt;/em&gt; de no arquivo de dicionário do idioma, use a diretiva &lt;code&gt;{{trans}}&lt;/code&gt; para idicar que é uma &lt;em&gt;string&lt;/em&gt; a ser traduzida.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;{{trans "{Custom string}"}}
{{trans "{Custom string with %var" var="{variable value}"}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ Os &lt;em&gt;templates&lt;/em&gt; de e-mail personalizados adicionados através do painel de admintrador não são armazenados no sistema de arquivos e suas strings não são adicionadas ao dicionário. Neste tópico está sendo abordados os arquivos criados via código.&lt;/p&gt;

&lt;h3&gt;
  
  
  Arquivo CSV
&lt;/h3&gt;

&lt;p&gt;O Magento 2 utiliza arquivos de idioma para armazenar as &lt;em&gt;strings&lt;/em&gt; de texto que são exibidas para os usuários. Para isso é necessário criar um arquivo CSV para cada idioma suportado que contêm o texto original e a tradução.&lt;/p&gt;

&lt;p&gt;Um dicionário de tradução é um arquivo de valores separados por vírgula (csv) com pelo menos duas colunas: a frase original na localidade &lt;code&gt;en_US&lt;/code&gt; e uma tradução dessa frase em outra localidade. A nome do arquivo para a localidade usada em lojas com o português brasileiro deve ser &lt;code&gt;pt_BR.csv&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;"{Custom string}","{Custom string translated}"
"{Custom string with %1}","{Custom string with %1 translated}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Finalizando
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Valores entre chaves (&lt;code&gt;{test}&lt;/code&gt;) devem ser alterados na implementação do código.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Habilitando as alterações
&lt;/h3&gt;

&lt;p&gt;Execute o comando PHP para limpar todos os caches de armazenamento em cache do processos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php bin/magento cache:clean
php bin/magento cache:flush
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Diretórios e Arquivos
&lt;/h3&gt;

&lt;p&gt;Segue a a lista de diretórios e arquivos que devem ser criados para a criaçãod e tradução em um módulo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- app/
  - code/
    - {Vendor}/
        - {Module}/
          - etc/
            - module.xml
          - i18n/
              - pt_BR.csv
          - registration.php
          - composer.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>showdev</category>
    </item>
    <item>
      <title>Como criar um indexador (indexer) personalizado no Magento 2</title>
      <dc:creator>Lucas Teixeira dos Santos Santana</dc:creator>
      <pubDate>Mon, 28 Nov 2022 12:34:05 +0000</pubDate>
      <link>https://dev.to/santanaluc94/como-criar-um-indexador-indexer-personalizado-no-magento-2-1n2m</link>
      <guid>https://dev.to/santanaluc94/como-criar-um-indexador-indexer-personalizado-no-magento-2-1n2m</guid>
      <description>&lt;h2&gt;
  
  
  Contextualizando
&lt;/h2&gt;

&lt;h3&gt;
  
  
  O que é indíce (index)?
&lt;/h3&gt;

&lt;p&gt;Índice é um recurso que o servidores de SQL disponibiliza afim de ordenar dados em uma determinada sequência, afim de retornar os resultados de maneira mais eficiente, ou seja, os índices são empregados em uma consulta para ajudar a encontrar registros com um valor específico em uma coluna de forma rápida, para aumentar o desempenho na execução de consultas.&lt;/p&gt;

&lt;p&gt;Os índices fazem a representação dos dados originais para leitura e busca otimizadas, e também, podem conter resultados de agregações e vários cálculos. Os dados de índice sempre podem ser recriados a partir de um dicionário usando um determinado algoritmo.&lt;/p&gt;

&lt;h3&gt;
  
  
  O que é a indexação?
&lt;/h3&gt;

&lt;p&gt;A indexação é como o Magento transforma dados (como produtos e categorias) para melhorar o desempenho da vitrine da loja. À medida que os dados mudam, os dados transformados devem ser atualizados ou reindexados.&lt;/p&gt;




&lt;h2&gt;
  
  
  Código para criação do indexador
&lt;/h2&gt;

&lt;h3&gt;
  
  
  indexer.xml
&lt;/h3&gt;

&lt;p&gt;Este arquivo deve estar localizado na pasta &lt;code&gt;\{Vendor}\{Module}\etc\indexer.xml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;config&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt; &lt;span class="na"&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"urn:magento:framework:Indexer/etc/indexer.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;indexer&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"{index_id}"&lt;/span&gt; &lt;span class="na"&gt;view_id=&lt;/span&gt;&lt;span class="s"&gt;"{view_id}"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"{Vendor}\{Class}\Model\Indexer\{IndexerClassName}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;title&lt;/span&gt; &lt;span class="na"&gt;translate=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{Indexer Title}&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;description&lt;/span&gt; &lt;span class="na"&gt;translate=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{Indexer Description}&lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;fieldset&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"{fieldset_id}"&lt;/span&gt;
                  &lt;span class="na"&gt;source=&lt;/span&gt;&lt;span class="s"&gt;"{Vendor}\{Class}\Model\ResourceModel\Design\Config\Scope\Collection"&lt;/span&gt;
                  &lt;span class="na"&gt;provider=&lt;/span&gt;&lt;span class="s"&gt;"{Vendor}\{Class}\Model\Indexer\Design\Config\FieldsProvider"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;field&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"{field_id}"&lt;/span&gt; &lt;span class="na"&gt;xsi:type=&lt;/span&gt;&lt;span class="s"&gt;"filterable"&lt;/span&gt; &lt;span class="na"&gt;dataType=&lt;/span&gt;&lt;span class="s"&gt;"int"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/fieldset&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;saveHandler&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"{Vendor}\{Class}\Indexer\SaveHandler\{GridName}"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;structure&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"{Vendor}\{Class}\Indexer\{GridStructureName}"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/indexer&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Atributos do indexer
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Atributo&lt;/th&gt;
&lt;th&gt;Descrição&lt;/th&gt;
&lt;th&gt;Obrigatório&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;ID único do índice.&lt;/td&gt;
&lt;td&gt;Sim&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;class&lt;/td&gt;
&lt;td&gt;A classe que processa os métodos do indexador (executeFull, executeList, executeRow).&lt;/td&gt;
&lt;td&gt;Não&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;primary&lt;/td&gt;
&lt;td&gt;O provedor de código.&lt;/td&gt;
&lt;td&gt;Não&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shared_index&lt;/td&gt;
&lt;td&gt;Use esta opção para melhorar o desempenho se seu indexador estiver relacionado a outro indexador.&lt;/td&gt;
&lt;td&gt;Não&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;view_id&lt;/td&gt;
&lt;td&gt;O ID do elemento de visualização definido no arquivo de configuração mview.xml.&lt;/td&gt;
&lt;td&gt;Não&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Nós filhos do indexer
&lt;/h4&gt;

&lt;p&gt;O nó &lt;code&gt;&amp;lt;indexer&amp;gt;&lt;/code&gt; pode alguns nós filhos, o nó &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; (que exibirá como o título do indexador) e o nó &lt;code&gt;&amp;lt;description&amp;gt;&lt;/code&gt; (que exibirá a descrição do indexador).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nó&lt;/th&gt;
&lt;th&gt;Descrição&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;title&lt;/td&gt;
&lt;td&gt;O título a ser exibido na página de indexadores.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;description&lt;/td&gt;
&lt;td&gt;A descrição a ser exibida na página de indexadores.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fieldset&lt;/td&gt;
&lt;td&gt;Descreve os campos, a origem e o provedor de dados da tabela de índices simples.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;saveHandler&lt;/td&gt;
&lt;td&gt;Um ponto de extensão. A classe para processar (excluir, salvar, atualizar) itens ao indexar.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;structure&lt;/td&gt;
&lt;td&gt;A classe que processa (cria, remove) tabelas de índice simples.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Classe Indexer
&lt;/h3&gt;

&lt;p&gt;Está classe deve implementar as interfaces &lt;code&gt;\Magento\Framework\Indexer\ActionInterface&lt;/code&gt; e &lt;code&gt;\Magento\Framework\Mview\ActionInterface&lt;/code&gt;, onde será necessário a implementação de quatro métodos com as seguintes descrições&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;executeFull()&lt;/code&gt;: este método realiza a reindexação completa, ou seja, realiza um processamento de todas as entidades de um dicionário específico. Este método também é o realizado quando for executado pela linha de comando;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;executeList(array $ids)&lt;/code&gt;: este método realiza a reindexação de lista, ou seja, realiza o processamento de um conjunto de entradas de dicionário, onde &lt;code&gt;$ids&lt;/code&gt; é um array dos IDs das entidades;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;executeRow($id)&lt;/code&gt;: este método realiza a reindexação de linhas, ou seja, realiza o processamento de uma única entrada de um dicionário e funciona em tempo de execução para uma única entidade usando plugins;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;execute($ids)&lt;/code&gt;: este método realiza a reindexação de processos no modo “Atualização de Agendamento” pelo arquivo &lt;code&gt;mview.xml&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Vendor&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Class&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="nc"&gt;\Model\Indexer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;IndexerClassName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;\Magento\Framework\Indexer\ActionInterface&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;\Magento\Framework\Mview\ActionInterface&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//code here!&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;executeFull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//code here!&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;executeList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$ids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//code here!&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;executeRow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//code here!&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  mview.xml
&lt;/h3&gt;

&lt;p&gt;Este arquivo deve estar localizado na pasta &lt;code&gt;\{Vendor}\{Module}\etc\mview.xml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;config&lt;/span&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/XMLSchema-instance"&lt;/span&gt; &lt;span class="na"&gt;xsi:noNamespaceSchemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"urn:magento:framework:Mview/etc/mview.xsd"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;view&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"{view_id}"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"{Vendor}\{Class}\Model\Indexer\{IndexerClassName}"&lt;/span&gt; &lt;span class="na"&gt;group=&lt;/span&gt;&lt;span class="s"&gt;"indexer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;subscriptions&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"{table_name}"&lt;/span&gt; &lt;span class="na"&gt;entity_column=&lt;/span&gt;&lt;span class="s"&gt;"{entity_id}"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/subscriptions&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/view&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Atributos do mview
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nós&lt;/th&gt;
&lt;th&gt;Descrição&lt;/th&gt;
&lt;th&gt;Obrigatório&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;O ID do elemento de visualização.&lt;/td&gt;
&lt;td&gt;Sim&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;class&lt;/td&gt;
&lt;td&gt;A classe que processa o método do indexador (execute).&lt;/td&gt;
&lt;td&gt;Sim&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;group&lt;/td&gt;
&lt;td&gt;Lista de opções do widget.&lt;/td&gt;
&lt;td&gt;Sim&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;O nó &lt;code&gt;&amp;lt;view&amp;gt;&lt;/code&gt; só possui apenas um tipo de nó filho, o nó &lt;code&gt;&amp;lt;subscriptions&amp;gt;&lt;/code&gt;, este nó não possui atributos e possui também apenas um tipo de nó como filho, o nó &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt;. O nó &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; não possui nenhum nó filho e possui dois atributos: o atributo &lt;code&gt;name&lt;/code&gt; é responsável por identificar o nome da tabela que será indexada e o atributo &lt;code&gt;entity_column&lt;/code&gt; é o atributo responsável por identificar a coluna de identificador único primário desta tabela.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comandos
&lt;/h3&gt;

&lt;p&gt;É possível verificar o status de cada indexador através do seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/magento indexer:status &lt;span class="o"&gt;{&lt;/span&gt;index_id&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;É possível utilizar o seguinte comando para reindexar todos os indexadores ou indexadores específicos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Reindexar um indexador específico&lt;/span&gt;
bin/magento indexer:reindex &lt;span class="o"&gt;{&lt;/span&gt;index_id&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Reindexar todos os indexadores&lt;/span&gt;
bin/magento indexer:reindex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;É possível especificar a configuração do indexador com o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bin/magento indexer:set-mode &lt;span class="o"&gt;{&lt;/span&gt;realtime|schedule&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;index_id&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;realtime&lt;/code&gt;: Define os indexadores selecionados para atualização ao salvar;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;schedule&lt;/code&gt;: Define os indexadores especificados a serem salvos de acordo com o cronograma do cron.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Finalizando
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Valores entre chaves (&lt;code&gt;{test}&lt;/code&gt;) devem ser alterados na implementação do código.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Habilitando as alterações
&lt;/h3&gt;

&lt;p&gt;Apague os arquivos que são gerados na compilação do Magento e execute o comando PHP para gerar a configuração das injeções de dependência e todas as classes ausentes que precisam ser geradas (proxys, interceptors, etc) e para limpar todos os &lt;em&gt;caches&lt;/em&gt; de armazenamento em &lt;em&gt;cache&lt;/em&gt; do processos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; var/generation/
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; generated/
php bin/magento setup:di:compile
php bin/magento cache:clean
php bin/magento flush
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Diretórios e Arquivos
&lt;/h3&gt;

&lt;p&gt;Segue a a lista de diretórios e arquivos que devem ser criados.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- app/
  - code/
    - {Vendor}/
        - {Module}/
          - etc/
            - indexer.xml
            - mview.xml
            - module.xml
          - Model/
              - Indexer/
                  - {ClassIndexerName}.php
          - registration.php
          - composer.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>php</category>
      <category>braziliandevs</category>
      <category>magento2</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Como configurar e executar alguns tipos de testes para Magento 2</title>
      <dc:creator>Lucas Teixeira dos Santos Santana</dc:creator>
      <pubDate>Mon, 14 Nov 2022 14:43:16 +0000</pubDate>
      <link>https://dev.to/santanaluc94/como-configurar-e-executar-alguns-tipos-de-testes-para-magento-2-4512</link>
      <guid>https://dev.to/santanaluc94/como-configurar-e-executar-alguns-tipos-de-testes-para-magento-2-4512</guid>
      <description>&lt;h2&gt;
  
  
  PHP Code Sniffer (PHPCS)
&lt;/h2&gt;

&lt;p&gt;O &lt;em&gt;PHP Code Sniffer&lt;/em&gt; (em uma tradução livre, pode ser algo como: Analisador de Código) é uma ferramenta para detectar violações nos padrões de código. Os padrões de código são formados por uma coleção de regras definidas pelos desenvolvedores, o padrão inicial do PHPCS é o PEAR. O PHPCS pode apontar para as recomendações padrões do PHP (PSRs). É necessário ter o PHPCS e o &lt;em&gt;Magento Coding Standard&lt;/em&gt; como dependência de desenvolvimento no arquivo &lt;code&gt;composer.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"require-dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"squizlabs/php_codesniffer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{version}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"magento/magento-coding-standard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{version}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para configurar a primeira vez o &lt;em&gt;Magento Coding Standard&lt;/em&gt; no PHPCS deve ser executado o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vendor/bin/phpcs &lt;span class="nt"&gt;--config-set&lt;/span&gt; installed_paths ../../magento/magento-coding-standard/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para executar os testes deve-se chamar o comando &lt;code&gt;phpcs&lt;/code&gt; que estará dentro de &lt;code&gt;./vendor/bin&lt;/code&gt; e referenciar a pasta de destino.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./vendor/bin/phpcs app/code/&lt;span class="o"&gt;{&lt;/span&gt;Vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;Module&lt;span class="o"&gt;}&lt;/span&gt;
./vendor/bin/phpcs vendor/&lt;span class="o"&gt;{&lt;/span&gt;vendor&lt;span class="o"&gt;}&lt;/span&gt;/module-&lt;span class="o"&gt;{&lt;/span&gt;module-name&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ruleset.xml
&lt;/h3&gt;

&lt;p&gt;Caso seja necessário personalizar a execução de testes é possível criar um arquivo &lt;code&gt;ruleset.xml&lt;/code&gt; (a recomendação é chamá-lo de &lt;code&gt;phpcs-ruleset.xml&lt;/code&gt; para não entrar em conflito com os outros arquivos &lt;code&gt;ruleset.xml&lt;/code&gt;) no próprio módulo e configurar para que os testes sejam executados de acordo com a configuração deste arquivo.&lt;/p&gt;

&lt;p&gt;A documentação necessária explicando tudo sobre o arquivo &lt;code&gt;ruleset.xml&lt;/code&gt; está no link &lt;a href="https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-Ruleset" rel="noopener noreferrer"&gt;PHP_CodeSniffer Ruleset&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./vendor/bin/phpcs app/code/&lt;span class="o"&gt;{&lt;/span&gt;Vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;Module&lt;span class="o"&gt;}&lt;/span&gt;
./vendor/bin/phpcs vendor/&lt;span class="o"&gt;{&lt;/span&gt;vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;module&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pear.php.net/package/PHP_CodeSniffer" rel="noopener noreferrer"&gt;PHP CodeSniffer PEAR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/squizlabs/PHP_CodeSniffer/wiki" rel="noopener noreferrer"&gt;PHP CodeSniffer Wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  PHP Mess Detector (PHPMD)
&lt;/h2&gt;

&lt;p&gt;O &lt;em&gt;PHP Mess Detector&lt;/em&gt; (em uma tradução livre, pode ser algo como: Detector de Desordem) é uma ferramenta que analisa o código de uma aplicação em PHP e detecta problemas potenciais e a qualidade. Algumas das inúmeras análises possíveis de serem executadas com o PHP Mess Detector são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Localização de possíveis erros;&lt;/li&gt;
&lt;li&gt;Localização de métodos, atributos e argumentos não utilizados;&lt;/li&gt;
&lt;li&gt;Violação de convenções de nomenclatura;&lt;/li&gt;
&lt;li&gt;Problemas potenciais relacionados ao tamanho do código;&lt;/li&gt;
&lt;li&gt;Verifica a complexidade do código.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;É necessário ter o PHPMD como dependência de desenvolvimento no arquivo &lt;code&gt;composer.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"require-dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"phpmd/phpmd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{version}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para executar os testes com o PHPMD, deve-se chamar o comando &lt;code&gt;phpmd&lt;/code&gt; que estará dentro de &lt;code&gt;./vendor/bin&lt;/code&gt;, referenciar o arquivo &lt;code&gt;ruleset.xml&lt;/code&gt; (a recomendação é chamá-lo de &lt;code&gt;phpmd-ruleset.xml&lt;/code&gt; para não entrar em conflito com os outros arquivos &lt;code&gt;ruleset.xml&lt;/code&gt;) e a pasta de destino.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./vendor/bin/phpmd app/code/&lt;span class="o"&gt;{&lt;/span&gt;Vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;Module&lt;span class="o"&gt;}&lt;/span&gt; text app/code/&lt;span class="o"&gt;{&lt;/span&gt;Vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;Module&lt;span class="o"&gt;}&lt;/span&gt;/phpmd-ruleset.xml
./vendor/bin/phpmd vendor/&lt;span class="o"&gt;{&lt;/span&gt;vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;module&lt;span class="o"&gt;}&lt;/span&gt; text vendor/&lt;span class="o"&gt;{&lt;/span&gt;vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;module&lt;span class="o"&gt;}&lt;/span&gt;/phpmd-ruleset.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O PHP Mess Detector possui alguns parâmetros que permitem adicionar filtros ao processo de análise e definir o formato de saída do resultado do teste.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://phpmd.org/" rel="noopener noreferrer"&gt;PHPMD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/phpmd/phpmd" rel="noopener noreferrer"&gt;Github PHPMD&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ruleset.xml
&lt;/h3&gt;

&lt;p&gt;Caso seja necessário personalizar a execução de testes é possível criar um arquivo ruleset.xml (a recomendação é chamá-lo de phpmd-ruleset.xml para não entrar em conflito com os outros arquivos ruleset.xml) no próprio módulo e configurar para que os testes sejam executados de acordo com a configuração deste arquivo. &lt;/p&gt;

&lt;p&gt;A documentação necessária explicando tudo sobre o arquivo ruleset.xml está no link &lt;a href="https://phpmd.org/rules/index.html" rel="noopener noreferrer"&gt;PHPMD doc&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  PHP Copy/Paste Detector (PHPCPD)
&lt;/h2&gt;

&lt;p&gt;O &lt;em&gt;PHP Copy/Paste Detector&lt;/em&gt; (em uma tradução livre, pode ser algo como: Detector de Copia e Cola) é uma ferramenta para checagem de código duplicado nos arquivos em PHP do módulo. É necessário ter o PHPCPD como dependência de desenvolvimento no arquivo &lt;code&gt;composer.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"require-dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"sebastian/phpcpd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{version}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para executar os testes com o PHPCPD, deve-se chamar o comando &lt;code&gt;phpcpd&lt;/code&gt; que estará dentro do diretório &lt;code&gt;./vendor/bin&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./vendor/bin/phpcpd ./app/code/&lt;span class="o"&gt;{&lt;/span&gt;Vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;Module&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--exclude&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./vendor/e3/&lt;span class="nv"&gt;$1&lt;/span&gt;/Test/ &lt;span class="nt"&gt;--fuzzy&lt;/span&gt; &lt;span class="nt"&gt;--progress&lt;/span&gt; &lt;span class="nt"&gt;--min-lines&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0
./vendor/bin/phpcpd ./vendor/&lt;span class="o"&gt;{&lt;/span&gt;vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;module&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--exclude&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./vendor/e3/&lt;span class="nv"&gt;$1&lt;/span&gt;/Test/ &lt;span class="nt"&gt;--fuzzy&lt;/span&gt; &lt;span class="nt"&gt;--progress&lt;/span&gt; &lt;span class="nt"&gt;--min-lines&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A documentação necessária explicando tudo sobre as opções para a execução do PHPCPD está no link &lt;a href="https://manpages.ubuntu.com/manpages/xenial/man1/phpcpd.1.html" rel="noopener noreferrer"&gt;PHPCPD Manual&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  PHP Static Analysis (PHPStan)
&lt;/h2&gt;

&lt;p&gt;O &lt;em&gt;PHP Static Analysis&lt;/em&gt; (em uma tradução livre, pode ser algo como: Análise Estática) é uma ferramenta focada em encontrar erros no código sem executá-las de fato e sem que sejam feitos testes para as classes, a exatidão de cada linha do código pode ser verificada antes de executar a linha real, ou seja, a PHPStan tem a proposta de adaptar a funcionalidade de um compilador para análise estática do código. Algumas das verificações que o PHPStan realiza são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verifica a utilização das chamadas de classes, verificando se o código está realmente sendo utilizado;&lt;/li&gt;
&lt;li&gt;Verifica a acessibilidade dos métodos e funções e a coesão entre os argumentos das chamadas com sua assinatura;&lt;/li&gt;
&lt;li&gt;Verifica a tipagem do retorno dos métodos e funções;&lt;/li&gt;
&lt;li&gt;Verifica a acessibilidade dos atributos e sua tipagem;&lt;/li&gt;
&lt;li&gt;Verifica a existência de variáveis (respeitando o escopo e laços de repetição);&lt;/li&gt;
&lt;li&gt;Verifica comparações estritas e tipagem de variáveis inúteis.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para utilizar o PHPStan no Magento 2 é necessário uma extensão que permita a análise do código, é recomendável o módulo &lt;a href="https://github.com/inviqa/phpstan-magento2" rel="noopener noreferrer"&gt;PHPStan Inviqa&lt;/a&gt;. Basta instalar esse módulo através do composer, é necessário ter o PHPStan como dependência de desenvolvimento no arquivo &lt;code&gt;composer.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"require-dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"phpstan/phpstan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{version}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"inviqa/phpstan-magento2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{version}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para executar os testes com o PHPStan, deve-se chamar o comando &lt;code&gt;analyse&lt;/code&gt; que estará dentro de &lt;code&gt;./vendor/bin/phpstan&lt;/code&gt;, referenciar o caminho do arquivo &lt;code&gt;phpstan.neon&lt;/code&gt; que será utilizado para configuração e a pasta de destino.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./vendor/bin/phpstan analyse ./app/code/&lt;span class="o"&gt;{&lt;/span&gt;Vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;Module&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--configuration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;phpstan.neon
./vendor/bin/phpstan analyse ./vendor/&lt;span class="o"&gt;{&lt;/span&gt;vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;module&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--configuration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;phpstan.neon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  phpstan.neon
&lt;/h3&gt;

&lt;p&gt;O PHPStan utiliza o formato de configuração chamado &lt;code&gt;neon&lt;/code&gt;, que é muito semelhante ao &lt;code&gt;yml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;parameters:
    bootstrap: ../../../../vendor/inviqa/phpstan-magento2/phpstan-bootstrap.php
    level: 5
    paths:
        - ./
    fileExtensions:
        - php
    excludes_analyse:
        - ./etc/*
        - ./Test/*
        - ./test-reports/*
        - ./view/*
    ignoreErrors:
        - '#Call to an undefined method [a-zA-Z0-9\\_]+::(get|set|uns|has)[A-Z]#'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso seja necessário a customização do arquivo &lt;code&gt;phpstan.neon&lt;/code&gt; basta consultar a documentação abaixo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://phpstan.org/" rel="noopener noreferrer"&gt;PHP Static Analysis Doc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/phpstan/phpstan" rel="noopener noreferrer"&gt;PHP Static Analysis Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>php</category>
      <category>braziliandevs</category>
      <category>testing</category>
      <category>magento2</category>
    </item>
    <item>
      <title>Teste Unitário no PHPUnit para aplicar em arquivos do Magento 2</title>
      <dc:creator>Lucas Teixeira dos Santos Santana</dc:creator>
      <pubDate>Fri, 14 Oct 2022 12:49:18 +0000</pubDate>
      <link>https://dev.to/santanaluc94/teste-unitario-no-phpunit-para-aplicar-em-arquivos-do-magento-2-2k5o</link>
      <guid>https://dev.to/santanaluc94/teste-unitario-no-phpunit-para-aplicar-em-arquivos-do-magento-2-2k5o</guid>
      <description>&lt;h2&gt;
  
  
  PHPUnit
&lt;/h2&gt;

&lt;p&gt;O &lt;strong&gt;PHPUnit&lt;/strong&gt; é uma ferramenta de testes de unidade que disponibiliza um ecossistema necessário para realizar testes de forma automatizada em PHP. O PHPUnit está disponível para aplicações com o PHP a partir da versão 5.5.&lt;br&gt;
Ele é instalado como uma dependência ao projeto e se adéqua com a estrutura do mesmo. Possui uma CLI (Interface de Linha de Comando) própria com opções de personalização para a forma de executar os testes.&lt;br&gt;
O PHPUnit é baseado na ideia que o desenvolvedor deve encontrar erros no código-fonte o mais rápido possível. Semelhante a outros frameworks de teste unitário, ele usa &lt;em&gt;assertions&lt;/em&gt; para verificar se o código-fonte está se comportando como o esperado.&lt;br&gt;
Também suporta a declaração de dependências explícitas entre métodos de teste. Tais dependências não definem a ordem em que os métodos de teste devem ser executados, mas permitem o retorno de uma instância do ambiente do teste por um produtor e a passagem dele para os consumidores dependentes.&lt;/p&gt;

&lt;p&gt;Para executar os testes com o PHPUnit, deve-se chamar o comando &lt;code&gt;phpunit&lt;/code&gt; que estará dentro de &lt;code&gt;./vendor/bin/phpunit&lt;/code&gt; e referenciar o arquivo &lt;code&gt;phpunit.xml&lt;/code&gt; com as configurações que serão utilizados para a execução dos testes.&lt;br&gt;
O Magento 2 por padrão já possui um arquivo &lt;code&gt;phpunit.xml&lt;/code&gt; que pode ser utilizado, ele se encontra no caminho &lt;code&gt;./dev/tests/unit/phpunit.xml.dist&lt;/code&gt;. O terceiro argumento passado no comando para a execução de testes será o caminho do módulo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./vendor/bin/phpunit &lt;span class="nt"&gt;-c&lt;/span&gt; dev/tests/unit/phpunit.xml.dist app/code/&lt;span class="o"&gt;{&lt;/span&gt;Vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;Module&lt;span class="o"&gt;}&lt;/span&gt;
./vendor/bin/phpunit &lt;span class="nt"&gt;-c&lt;/span&gt; dev/tests/unit/phpunit.xml.dist vendor/&lt;span class="o"&gt;{&lt;/span&gt;vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;module&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  phpunit.xml
&lt;/h3&gt;

&lt;p&gt;Caso seja necessário personalizar a execução de testes (&lt;strong&gt;exemplo:&lt;/strong&gt; ignorar a pasta API do módulo) é possível criar um arquivo &lt;code&gt;phpunit.xml&lt;/code&gt; no próprio módulo e configurar para que os testes sejam executados de acordo com a configuração deste arquivo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./vendor/bin/phpunit &lt;span class="nt"&gt;-c&lt;/span&gt; app/code/&lt;span class="o"&gt;{&lt;/span&gt;Vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;Module&lt;span class="o"&gt;}&lt;/span&gt;/phpunit.xml.dist app/code/&lt;span class="o"&gt;{&lt;/span&gt;Vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;Module&lt;span class="o"&gt;}&lt;/span&gt;
./vendor/bin/phpunit &lt;span class="nt"&gt;-c&lt;/span&gt; vendor/&lt;span class="o"&gt;{&lt;/span&gt;vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;module&lt;span class="o"&gt;}&lt;/span&gt;/phpunit.xml.dist vendor/&lt;span class="o"&gt;{&lt;/span&gt;vendor&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;module&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;a href="https://phpunit.readthedocs.io/pt_BR/latest/configuration.html" rel="noopener noreferrer"&gt;O Arquivo de Configuração XML&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Código base para a implantação
&lt;/h2&gt;

&lt;p&gt;Para escrever testes com o PHPUnit no Magento 2 basta criar a estrutura de pastas &lt;code&gt;\{Vendor}\{Module}\Test\Unit\{ClassDirectory}\{ClassName}Test&lt;/code&gt; estender a classe que &lt;code&gt;\PHPUnit\Framework\TestCase&lt;/code&gt;. O PHPUnit localiza os métodos de teste pelo prefixo &lt;code&gt;test&lt;/code&gt; no nome do método, e neste contém asserções para validar que o método retorne um valor real equivalente ao esperado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Classe a ser testada:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Vendor&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;ClassDirectory&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;ClassName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;methodName&lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Code here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Classe de teste:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Vendor&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="nc"&gt;\Test\Unit&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;ClassDirectory&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;PHPUnit\Framework\TestCase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;ClassName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="nc"&gt;Test&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;MethodName&lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Code here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Asserções
&lt;/h3&gt;

&lt;p&gt;Asserções são métodos desenvolvidos pelo PHPUnit para assegurar que o valor de um teste é um valor esperado, ou seja, sãos métodos que executam a unidade e certificam que o resultado gerado no teste é o esperado com sucesso ou falham.&lt;/p&gt;

&lt;p&gt;Os métodos da classe &lt;code&gt;\PHPUnit\Framework\TestCase&lt;/code&gt; que começam com o prefixo &lt;em&gt;assert&lt;/em&gt;, são parte importante dos casos de teste e avaliam se certas condições, decisivas para determinar o sucesso ou falha do teste, geram um resultado esperado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Vendor&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="nc"&gt;\Test\Unit&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;ClassDirectory&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;PHPUnit\Framework\TestCase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;ClassName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="nc"&gt;Test&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;MethodName&lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Code here&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}({&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;É possível verificar a documentação com todas as asserções fornecidas pelo PHPUnit no link “&lt;a href="https://phpunit.readthedocs.io/pt_BR/latest/assertions.html#uso-estatico-vs-nao-estatico-de-metodos-de-assercao" rel="noopener noreferrer"&gt;Asserções do PHPUnit&lt;/a&gt;“.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exceções
&lt;/h3&gt;

&lt;p&gt;Usando o método &lt;code&gt;expectException()&lt;/code&gt;, o PHPUnit verifica se durante a exceção do teste é lançada uma exceção dentro do código testado. Além do método &lt;code&gt;expectException()&lt;/code&gt; os métodos  &lt;code&gt;expectExceptionCode()&lt;/code&gt;, &lt;code&gt;expectExceptionMessage()&lt;/code&gt; e &lt;code&gt;expectExceptionMessageRegExp()&lt;/code&gt; existem para configurar expectativas de exceções lançadas pelo código sob teste.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Vendor&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="nc"&gt;\Test\Unit&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;ClassDirectory&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;PHPUnit\Framework\TestCase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;ClassName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="nc"&gt;Test&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;MethodName&lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;expectException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;\Exception&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Code here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Provedor de Dados
&lt;/h3&gt;

&lt;p&gt;Com um método provedor de dados (&lt;em&gt;data provider&lt;/em&gt;) o PHPUnit permite que o um método de teste seja executado em diferentes cenários, ou seja, consiste em preparar os dados de entradas para que o teste seja executado diversas vezes com dados diferentes.&lt;/p&gt;

&lt;p&gt;Um método provedor de dados deve ser do tipo &lt;code&gt;public&lt;/code&gt;, possuir a anotação &lt;code&gt;@dataProvider&lt;/code&gt; como o nome do método e retornar um &lt;em&gt;array&lt;/em&gt; de &lt;em&gt;arrays&lt;/em&gt;. Cada item do &lt;em&gt;array&lt;/em&gt; de retorno, o método de teste chamara como argumento.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Vendor&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="nc"&gt;\Test\Unit&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;ClassDirectory&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;PHPUnit\Framework\TestCase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;ClassName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="nc"&gt;Test&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @dataProvider {dataProviderName}
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;MethodName&lt;/span&gt;&lt;span class="p"&gt;}({&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Code to test here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dataProviderName&lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Code to provide different input data&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$data1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$data2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$data3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="mf"&gt;...&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$dataN&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Métodos setUp e tearDown
&lt;/h3&gt;

&lt;p&gt;O PHPUnit suporta compartilhamento do código de configuração. Os métodos-modelo &lt;code&gt;setUp()&lt;/code&gt; e &lt;code&gt;tearDown()&lt;/code&gt; são executados uma vez para cada método de teste (e em novas instâncias) da classe do caso de teste. Ambos os métodos devem ser do tipo &lt;code&gt;protected&lt;/code&gt; e não possuir nenhum dado de retorno (&lt;code&gt;void&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Antes que um método seja executado, um método modelo chamado &lt;code&gt;setUp()&lt;/code&gt; é invocado. O método &lt;code&gt;setUp()&lt;/code&gt; é onde os objetos que serão alvo dos testes são criados.&lt;/p&gt;

&lt;p&gt;Uma vez que o método de teste tenha terminado sua execução, seja bem-sucedido ou falho, outro método modelo é invocado &lt;code&gt;tearDown()&lt;/code&gt;. O método &lt;code&gt;tearDown()&lt;/code&gt; é onde os objetos que foram alvo dos testes são limpos, normalmente, implementa-se o método &lt;code&gt;tearDown()&lt;/code&gt; ao alocar recursos externos como arquivos ou sockets no &lt;code&gt;setUp()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Vendor&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="nc"&gt;\Test\Unit&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;ClassDirectory&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;PHPUnit\Framework\TestCase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;ClassName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="nc"&gt;Test&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;setUp&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Code to set up test objects&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;tearDown&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Code to tear down test object&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nc"&gt;MethodName&lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Code to test here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dublê de Testes
&lt;/h3&gt;

&lt;p&gt;É possível verificar a documentação com tudo sobre os dublês de testes do  PHPUnit no link “&lt;a href="https://phpunit.readthedocs.io/pt_BR/latest/test-doubles.html" rel="noopener noreferrer"&gt;Dublês de Testes do PHPUnit&lt;/a&gt;“.&lt;/p&gt;

&lt;p&gt;Os métodos &lt;code&gt;createMock($type)&lt;/code&gt; e &lt;code&gt;getMockBuilder($type)&lt;/code&gt; fornecidos pelo PHPUnit podem ser usados em um teste para gerar automaticamente um objeto que possa atuar como um dublê de teste para a classe original especificada. Esse objeto de dublê de teste pode ser usado em cada contexto onde um objeto da classe original é esperado ou requerido.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$this-&amp;gt;createMock({Class}::class)&lt;/code&gt;:  este método retorna um objeto de dublê de teste para o tipo especificado (interface ou classe). A criação desse dublê de teste é realizada usando os padrões de boas práticas (os métodos &lt;code&gt;__construct()&lt;/code&gt; e &lt;code&gt;__clone()&lt;/code&gt; da classe original não são executados) e os argumentos passados para um método do dublê de teste não serão clonados.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$this-&amp;gt;getMockBuilder({Class}::class)&lt;/code&gt;: este método serve para customizar a geração do dublê de teste usando uma interface fluente. Por padrão, todos os métodos da classe original são substituídos com uma implementação simulada que apenas retorna &lt;code&gt;null&lt;/code&gt; (sem chamar o método original).  É possível configurar essas implementações simuladas para retornar um valor quando chamadas.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;setMethods(array $methods)&lt;/code&gt;: pode ser chamado no objeto &lt;code&gt;getMockBuilder()&lt;/code&gt; para especificar os métodos que devem ser substituídos com um dublê de teste configurável. O comportamento dos outros métodos não muda. Se você chamar &lt;code&gt;setMethods(null)&lt;/code&gt;, então nenhum dos métodos serão substituídos (utilizado até a versão 7.3.X do PHP);&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onlyMethods(array $methods)&lt;/code&gt;: pode ser chamado no objeto &lt;code&gt;getMockBuilder()&lt;/code&gt; para especificar os métodos que devem ser substituídos por um dublê de teste configurável. O comportamento dos outros métodos não muda. Cada método deve existir na classe que está sendo criada como dublê de teste (utilizado a partir da versão 7.4.X do PHP);&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;addMethods(array $methods)&lt;/code&gt;: pode ser chamado no objeto &lt;code&gt;getMockBuilder()&lt;/code&gt; para especificar os métodos que não existem (ainda) na classe de dublê de teste. O comportamento dos outros métodos permanece o mesmo (utilizado a partir da versão 7.4.X do PHP);&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setConstructorArgs(array $args)&lt;/code&gt;: pode ser chamado para fornecer um vetor de parâmetros que é passado ao construtor da classe original (que por padrão não é substituído com uma implementação falsa);&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setMockClassName($name)&lt;/code&gt;: pode ser usado para especificar um nome de classe para a classe de dublê de teste gerada;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;disableOriginalConstructor()&lt;/code&gt;: pode ser usado para desabilitar a chamada ao construtor da classe original;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;disableOriginalClone()&lt;/code&gt;: pode ser usado para desabilitar a chamada ao construtor clone da classe original;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;disableAutoload()&lt;/code&gt;: pode ser usado para desabilitar o &lt;code&gt;__autoload()&lt;/code&gt; durante a geração da classe de dublê de teste.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;$this-&amp;gt;method('{methodName}')&lt;/code&gt;:  o método &lt;code&gt;method('{methodName}')&lt;/code&gt; recebe o nome do método que será testado na classe é tera um retorno &lt;code&gt;void&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$this-&amp;gt;method('{methodName}')-&amp;gt;willReturn('{valueToReturn}')&lt;/code&gt;:  o método &lt;code&gt;method('{methodName}')&lt;/code&gt; recebe o nome do método que será testado na classe. O método &lt;code&gt;willReturn('{valueToReturn}')&lt;/code&gt; retorna um valor simples para corresponder ao teste, esta sintaxe é o mesmo que &lt;code&gt;$this-&amp;gt;method('{methodName}')-&amp;gt;will($this-&amp;gt;returnValue($value))&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$this-&amp;gt;method('{methodName}')-&amp;gt;returnSelf()&lt;/code&gt;: este método retorna o próprio objeto de dublê de teste.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$objectMock-&amp;gt;expects($this-&amp;gt;once())-&amp;gt;method('{methodName}')-&amp;gt;with($this-&amp;gt;equalTo('something'))&lt;/code&gt;: verifica se um método foi chamado, e com quais argumentos foi chamado, os métodos &lt;code&gt;expects()&lt;/code&gt; e &lt;code&gt;with()&lt;/code&gt; são para especificar como essa interação deve se parecer.&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;with()&lt;/code&gt; pode receber qualquer número de argumentos, correspondendo ao número de argumentos sendo falsos. É possível especificar restrições mais avançadas do que uma simples igualdade no argumento do método.&lt;/p&gt;

</description>
      <category>php</category>
      <category>braziliandevs</category>
      <category>magento2</category>
      <category>testing</category>
    </item>
    <item>
      <title>Introdução sobre Testes de Unidade em PHP para aplicar no Magento 2</title>
      <dc:creator>Lucas Teixeira dos Santos Santana</dc:creator>
      <pubDate>Mon, 03 Oct 2022 14:34:48 +0000</pubDate>
      <link>https://dev.to/santanaluc94/introducao-sobre-testes-de-unidade-em-php-para-aplicar-no-magento-2-4cbg</link>
      <guid>https://dev.to/santanaluc94/introducao-sobre-testes-de-unidade-em-php-para-aplicar-no-magento-2-4cbg</guid>
      <description>&lt;h2&gt;
  
  
  Teste de Unidade
&lt;/h2&gt;

&lt;p&gt;O &lt;strong&gt;Teste de Unidade&lt;/strong&gt; é uma verificação automatizada do funcionamento da menor unidade possível de um sistema, ou seja, consiste em validar os dados de entradas e saídas executando cada trecho de código de forma automática, normalmente, através de métodos públicos em um classe de teste.&lt;/p&gt;

&lt;p&gt;Cada teste de unidade deve ser independente, para possibilitar que cada método de uma classe seja testado isoladamente, o que possibilita a manutenção e a escalabilidade dos testes em conjunto com o sistema. O teste de unidade é a primeira abordagem em matéria de confecção de testes mais robustos e confiáveis.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Testes Unitários são primeiramente escritos como uma boa prática para ajudar desenvolvedores a identificar e corrigir defeitos, refatorar o código e servir como documentação para uma unidade de programa sob teste. Para conseguir esses benefícios, testes unitários idealmente deveriam cobrir todos os caminhos possíveis em um programa. Um teste unitário geralmente cobre um caminho específico em uma função ou método. Porém um método de teste não é necessariamente uma entidade encapsulada e independente. Frequentemente existem dependências implícitas entre métodos de teste, escondidas no cenário de implementação de um teste.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Adrian Kuhn&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Algumas técnicas de Testes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Caixa-preta
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Teste de caixa-preta&lt;/strong&gt; é um tipo de teste que verifica a saída dos dados usando entradas de vários tipos. Tais entradas não são escolhidas conforme a estrutura do programa. Este tipo de teste também é conhecido como teste funcional, já que busca garantir que os requisitos funcionais do produto estão consistentes. É comumente realizado utilizando-se da experiência do usuário, ou seja, através da &lt;em&gt;interface&lt;/em&gt; do produto. Também conhecido como teste comportamental, este tipo de teste tenta encontrar erros nas seguintes categorias:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Funções incorretas ou omitidas;&lt;/li&gt;
&lt;li&gt;Erros de interface;&lt;/li&gt;
&lt;li&gt;Erros de estrutura de dados ou de acesso a base de dados externa;&lt;/li&gt;
&lt;li&gt;Erros de comportamento ou desempenho;&lt;/li&gt;
&lt;li&gt;Erros de iniciação e término.&lt;/li&gt;
&lt;li&gt;Aplicado durante os últimos estágios do teste, a atenção é focada no domínio da informação.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Caixa-branca
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Teste de caixa-branca&lt;/strong&gt; é uma técnica de teste que usa a perspectiva interna do sistema para modelar os casos de testes. Difere do teste de caixa-preta em que a perspectiva interna do sistema é desconsiderada, sendo testadas e mensuradas somente as interfaces do sistema.&lt;/p&gt;

&lt;h3&gt;
  
  
  Classe de equivalência
&lt;/h3&gt;

&lt;p&gt;Teste com base na &lt;strong&gt;análise de classe de equivalência&lt;/strong&gt; é uma forma de análise de teste de caixa preta que tenta reduzir o número total de testes possíveis para um conjunto mínimo de testes que revelarão o número máximo de erros possível. Isso consiste em um método que particiona o conjunto de entradas e saídas em um número finito de classe de equivalência que permitem a seleção de um valor de teste representativo para cada classe.&lt;/p&gt;

&lt;p&gt;O teste que resulta do valor representativo para uma classe é chamado de "equivalente" aos outros valores na mesma classe, ou seja, espera-se que o objeto testado se comporte de forma semelhante. Se nenhum erro foi localizado no teste do valor representativo, conclui-se que todos os outros valores "equivalentes" também não identificariam quaisquer erros. Essa técnica pode ser aplicada para ajudar a analisar os testes mais significativos a serem conduzidos quando houver muitos testes potenciais a serem conduzidos no tempo disponível.&lt;/p&gt;

&lt;h3&gt;
  
  
  Análise de valor de limite
&lt;/h3&gt;

&lt;p&gt;Essa técnica complementa o particionamento de equivalência. Para usar a análise do valor limite nos testes, descobrimos os limites do campo que queremos testar, está técnica de teste é utilizada para exercitar os limites do domínio de entrada.&lt;/p&gt;

&lt;p&gt;A técnica nos diz que devemos testar um valor imediatamente abaixo do limite, o valor limite e um valor imediatamente acima do valor limite, ou seja, os valores próximos às extremidades das classes  focalizando a seleção de Casos de Teste. Focaliza o teste em um ponto propício a erros, os limites de uma classe de equivalência. Os valores esperados de entrada e saída devem ser extraídos da especificação do componente, e então agrupados em conjuntos com fronteiras identificáveis.&lt;/p&gt;

&lt;p&gt;Cada conjunto, ou partição, contém valores que se espera que sejam processados pelo componente da mesma forma. É importante considerar ambas as partições válidas e inválidas quando se projetam casos de teste.&lt;/p&gt;

&lt;h3&gt;
  
  
  Matriz ortogonal
&lt;/h3&gt;

&lt;p&gt;O teste de &lt;strong&gt;matriz ortogonal&lt;/strong&gt; é um ponto médio para problemas com domínio de entrada relativamente pequeno, mas grande demais para testes exaustivos. Esta técnica de teste é muito útil quando há um grande número de dados de entrada, e suas combinações não são viáveis e rentáveis de serem testadas individualmente. Testes de matriz ortogonal fornece cobertura suficientemente completa de um aplicativo com o número mínimo de casos de teste.&lt;/p&gt;

&lt;p&gt;É melhor verificar apenas as combinações de dados que são suscetíveis de causar um defeito ao invés de checar todas as variantes possíveis. Se há muitas combinações de dados complicado pode ser muito difícil de determinar as combinações que devem ser verificadas.&lt;/p&gt;

&lt;p&gt;Este método detecta e isola todas as falhas de modo singular (pela análise da informação sobre quais testes revelam erros, pode-se identificar quais valores de parâmetro causam a falha). Detecta todas as falhas de modo duplo. A aplicação da técnica de ***&lt;em&gt;análise combinatória aos casos de teste, de forma que cada combinação escolhida pelo testador seja executada pelo menos uma vez. É conhecido como *3-wise&lt;/em&gt;, &lt;em&gt;4-wise&lt;/em&gt;, &lt;em&gt;n-wise&lt;/em&gt; — quanto maior o N, mais meticuloso é o processo.&lt;/p&gt;

&lt;p&gt;Na combinação &lt;em&gt;1-wise&lt;/em&gt;, cada valor de cada item é incluido pelo menos uma vez em um teste. Numa combinação &lt;em&gt;2-wise&lt;/em&gt;, todos os valores de um par de itens são combinados com os outros valores pelo menos uma vez em um teste, na &lt;em&gt;3-wise&lt;/em&gt; todos os valores de 3 itens são combinados pelos menos uma vez em cada caso… e assim sucessivamente.&lt;/p&gt;

&lt;h3&gt;
  
  
  Orientado a Objetos
&lt;/h3&gt;

&lt;p&gt;O teste &lt;strong&gt;orientado a objetos&lt;/strong&gt; consiste em realizar sequências de envios de mensagens. Essas sequências devem ser escolhidas de maneira a explorar o maior número possível de estados que um objeto possa assumir e as transições entre eles. Pode-se aplicar os testes do tipo caixa branca e caixa preta, contudo podem surgir algumas complicações como o encapsulamento e a herança. Algumas das vantagens dos testes orientados a objetos são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redução no tamanho dos métodos através da utilização de heranças;&lt;/li&gt;
&lt;li&gt;Algoritmos menos complexos, ou seja, algoritmos com poucas linhas de código, o que aumenta a legibilidade e o entendimento do mesmo;&lt;/li&gt;
&lt;li&gt;Facilidade na localização e correção de defeitos;&lt;/li&gt;
&lt;li&gt;Encapsulamento, que previne muitos problemas causados pelo escopo de dados sem controle.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Baseado em Erros
&lt;/h3&gt;

&lt;p&gt;Na técnica do teste com &lt;strong&gt;base em erro&lt;/strong&gt; são procurados erros plausíveis, particularidades da implementação quem podem ocasionar defeitos. Aqui casos de teste são projetados para exercitar o projeto ou o código. Este teste é aplicado tanto a atributos quanto a operações. A determinação de erros plausíveis deve ser feita quando funções ou métodos são invocados, o comportamento da operação deve ser examinado.&lt;/p&gt;

&lt;p&gt;O sistema deve satisfazer aos requisitos do cliente, o planejamento preliminar para criação de testes baseados em erros começa com o modelo de análise. sendo que três tipos de erros são encontrados neste contexto:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resultado inesperado;&lt;/li&gt;
&lt;li&gt;Uso da operação/mensagem errada;&lt;/li&gt;
&lt;li&gt;Invocação incorreta.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Essa técnica tem por objetivo verificar se o software está livre de erros típicos e comuns cometidos pelo desenvolvedor durante o ciclo de desenvolvimento de um software, especificamente durante a fase de implementação.&lt;/p&gt;

&lt;h3&gt;
  
  
  Base em cenário
&lt;/h3&gt;

&lt;p&gt;O teste com &lt;strong&gt;base em cenário&lt;/strong&gt; busca a validação do que o usuário precisar fazer em relação ao que o produto disponibiliza, ou seja, concentra-se no que o usuário faz, não no que o produto faz, detecta as tarefas por meio de casos de uso, que o usuário precisa realizar depois aplicá-las, bem como suas variantes, aos testes. Cenários descobrem erros de interação, mas para isto os casos de teste precisam ser mais complexos e mais realísticos do que os testes baseados em erro.&lt;/p&gt;

&lt;p&gt;O tipo menos detalhado de documentação é o cenário de teste. Um cenário de teste é uma descrição de um objetivo que o usuário pode encontrar ao utilizar o programa. Tipicamente, um cenário de teste vai precisar de diferentes tipos de testes para garantir que o objetivo tenha sido bem testado. Já que os cenários de testes oferecem pouca informação sobre como completar o teste, os testadores tem uma grande flexibilização para buscar uma solução.&lt;/p&gt;

&lt;p&gt;Assim como os casos de teste, a flexibilidade dos cenários oferecem prós e contras similares. O conhecimento de causa e as habilidades em testes podem facilitar os testadores a transformar os cenários em ideias concretas, escolher a abordagem mais lógica e rodar os testes que podem extrair os problemas importantes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mock Objects
&lt;/h3&gt;

&lt;p&gt;Os &lt;strong&gt;mock objects&lt;/strong&gt; (objetos simulados) são objetos que simulam o comportamento de objetos reais de forma controlada. São normalmente criados para testar o comportamento de outros objetos, ou seja, os &lt;em&gt;mock objects&lt;/em&gt; são objetos “falsos” que simulam o comportamento de uma classe ou objeto “real” para que possamos focar o teste na unidade a ser testada.&lt;/p&gt;

&lt;p&gt;Os &lt;em&gt;mock objects&lt;/em&gt; são úteis quando os objetos reais são difíceis de criar ou impossíveis de serem incorporados no teste de unidade, em vez de usar o objeto real que faz a chamada, usa-se um &lt;em&gt;mock object&lt;/em&gt; que simula o comportamento do objeto real.&lt;/p&gt;

</description>
      <category>php</category>
      <category>braziliandevs</category>
      <category>testing</category>
      <category>magento2</category>
    </item>
  </channel>
</rss>
