<?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: Julio Castillo Anselmi</title>
    <description>The latest articles on DEV Community by Julio Castillo Anselmi (@julcasans).</description>
    <link>https://dev.to/julcasans</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%2F106417%2F4081e09f-6e82-4fe1-bc05-4e1867f5e721.jpg</url>
      <title>DEV Community: Julio Castillo Anselmi</title>
      <link>https://dev.to/julcasans</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/julcasans"/>
    <language>en</language>
    <item>
      <title>Redacta: Elevating Video Content with GitHub Copilot CLI</title>
      <dc:creator>Julio Castillo Anselmi</dc:creator>
      <pubDate>Sun, 15 Feb 2026 23:11:05 +0000</pubDate>
      <link>https://dev.to/julcasans/redacta-elevating-video-content-with-github-copilot-cli-kc9</link>
      <guid>https://dev.to/julcasans/redacta-elevating-video-content-with-github-copilot-cli-kc9</guid>
      <description>&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Redacta is a personal solution born from a specific need: the desire to reclaim knowledge trapped in audio and video formats.&lt;/p&gt;

&lt;p&gt;As someone with a strong visual memory, I’ve always found reading to be far more effective than watching a video or listening to a podcast. Phrases and images stick better in my mind when I can see them on a page. I can scan text to find concepts, refresh my memory on specific sections, or quickly identify the core message of a paragraph.&lt;/p&gt;

&lt;p&gt;However, the world is full of incredible content delivered via video and audio. Unfortunately, I often feel I'm not getting the most out of it because it’s not written down. Searching within a video is a pain, and finding that one specific episode of a podcast I want to revisit is nearly impossible.&lt;/p&gt;

&lt;p&gt;I tried reading raw transcriptions, but they are often unreadable—especially YouTube’s auto-generated captions, which lack punctuation, formatting, and proper structure.&lt;/p&gt;

&lt;p&gt;Redacta was built to solve this. It takes a raw transcription and, using the power of GitHub Copilot and LLMs, transforms it into a well-redacted, properly punctuated document that remains strictly faithful to the original content.&lt;/p&gt;

&lt;p&gt;Since its inception, I’ve expanded Redacta to:&lt;/p&gt;

&lt;p&gt;Illustrate the text: Automatically adding images and schematics to aid visual learning.&lt;br&gt;
Generate Summaries and Posts: Creating different formats tailored for quick reading or deep study.&lt;br&gt;
Break Language Barriers: Translating content into other languages, allowing me to access knowledge originally shared in languages I don't speak fluently.&lt;br&gt;
Redacta isn't just a tool; it's a bridge between the vast world of video/audio content and the way my brain actually processes knowledge.&lt;/p&gt;
&lt;h3&gt;
  
  
  Core Capabilities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Semantic Redaction&lt;/strong&gt;: Transforms disjointed, messy transcripts into cohesive, well-structured documents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visual Enrichment&lt;/strong&gt;: Automatically inserts relevant images and ASCII diagrams to illustrate complex concepts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multilingual Intelligence&lt;/strong&gt;: Processes transcripts and generates outputs in various languages seamlessly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive TUI&lt;/strong&gt;: A beautiful, real-time terminal interface using &lt;code&gt;ink&lt;/code&gt; to monitor progress.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch Mastery&lt;/strong&gt;: Efficiently processes entire directories of transcripts in one go.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Available Commands
&lt;/h3&gt;

&lt;p&gt;Redacta is designed to be flexible. Here are the primary ways to interact with it:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--blog&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generates a polished blog post (&lt;code&gt;_blog.md&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--summary&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creates a concise executive summary (&lt;code&gt;_summary.md&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--language=&amp;lt;lang&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sets the target output language&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--with-illustration&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Adds key images and diagrams for clarity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--with-illustration-all&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deep illustration: adds comprehensive visual aids&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--directory=&amp;lt;dir&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Batch process all &lt;code&gt;.srt&lt;/code&gt; files in a folder&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--model=&amp;lt;id&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Choose your preferred LLM model&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  How to Use It
&lt;/h3&gt;

&lt;p&gt;Getting started with Redacta is straightforward.&lt;/p&gt;
&lt;h4&gt;
  
  
  1. Installation
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; redacta
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  2. Configuration
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CUSTOM_SEARCH_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'your_key'&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CUSTOM_SEARCH_PROJECT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'your_id'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  3. Usage Examples
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Basic cleanup in a specific language:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redacta tutorial.srt &lt;span class="nt"&gt;--language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;spanish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Complete transformation (Blog + Summary + Diagrams):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;redacta lecture.srt &lt;span class="nt"&gt;--blog&lt;/span&gt; &lt;span class="nt"&gt;--summary&lt;/span&gt; &lt;span class="nt"&gt;--with-illustration-all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Proposing Use Cases
&lt;/h3&gt;

&lt;p&gt;Redacta isn't just for cleaning text; it's for unlocking the value in your media library.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Course Accelerator&lt;/strong&gt;: Students can take a semester's worth of video lectures and turn them into a structured, illustrated study guide in minutes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Podcast Content Engine&lt;/strong&gt;: Creators can transform their audio episodes into SEO-friendly blog posts and social media summaries with zero manual writing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technical Documentation&lt;/strong&gt;: Engineers can record a "brain dump" video of a complex architecture and let Redacta generate a formatted technical doc with diagrams.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Meeting Archivist&lt;/strong&gt;: Turn recorded town halls or technical syncs into searchable, structured summaries for team members who couldn't attend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Border Learning&lt;/strong&gt;: Understand high-quality technical content from global experts by translating and formatting transcripts from languages you don't speak.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;To see Redacta in action, let's look at two very different scenarios that showcase its versatility.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. High-Level Technical Education
&lt;/h3&gt;

&lt;p&gt;The first example is a technical talk by Andrej Karpathy about Large Language Models.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source&lt;/strong&gt;: &lt;a href="https://www.youtube.com/watch?v=zjkBMFhNj_g" rel="noopener noreferrer"&gt;Intro to Large Language Models&lt;/a&gt; by Andrej Karpathy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Command&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node ./dist/bin/redacta.js ./examples/Intro_Large_Language_Model_LLM_talk.srt &lt;span class="nt"&gt;--with-illustration&lt;/span&gt; &lt;span class="nt"&gt;--blog&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For technical content, Redacta focuses on structural clarity and visual aids. It doesn't just clean the text; it identifies core architectural concepts and generates ASCII diagrams to bridge the gap between spoken word and visual understanding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generated Snippet (Knowledge Scaffolding):&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A large language model is just two files. For example: the Llama 2 70B model. It consists of the parameters file (weights) and the run file (code).&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+---------------------+           uses         +---------------------+
|                     |-----------------------&amp;gt;|                     |
|  PARAMETERS FILE    |                        |     RUN FILE        |
|  (140GB, float16    |                        |  (C/Python code,    |
|   weights)          |                        |   ~500 lines)       |
|                     |                        |                     |
+---------------------+                        +---------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;This is the raw transcript (input):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;transcript: &lt;a href="https://github.com/julcasans/redacta/blob/main/examples/Intro_Large_Language_Model_LLM_talk.srt" rel="noopener noreferrer"&gt;Intro_Large_Language_Model_LLM_talk.srt&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;And these are the generated texts (output):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;formatted text: &lt;a href="https://github.com/julcasans/redacta/blob/main/examples/Intro_Large_Language_Model_LLM_talk_formatted.md" rel="noopener noreferrer"&gt;Intro_Large_Language_Model_LLM_talk_formatted.md&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;blog: &lt;a href="https://github.com/julcasans/redacta/blob/main/examples/Intro_Large_Language_Model_LLM_talk_blog.md" rel="noopener noreferrer"&gt;Intro_Large_Language_Model_LLM_talk_blog.md&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Art History &amp;amp; Analysis (Multilingual)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Source&lt;/strong&gt;: &lt;a href="https://www.youtube.com/watch?v=SvPIQsO7y4I" rel="noopener noreferrer"&gt;Las 5 alegorías&lt;/a&gt; (Analysis of Baroque Art).&lt;br&gt;
&lt;strong&gt;Command&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node ./dist/bin/redacta.js ./examples/analisis_de_las_5_alegorias.srt &lt;span class="nt"&gt;--with-illustration&lt;/span&gt; &lt;span class="nt"&gt;--summary&lt;/span&gt; &lt;span class="nt"&gt;--language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;English &lt;span class="nt"&gt;--blog&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example highlights Redacta's ability to handle &lt;strong&gt;cross-language translation&lt;/strong&gt; and &lt;strong&gt;precision image insertion&lt;/strong&gt;. The tool translated the Spanish lecture into a structured English blog post while automatically finding the specific masterpieces being discussed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generated Snippet (Visual Context):&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Claesz ingeniously weaves each sense into the composition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hearing&lt;/strong&gt;: Musical instruments evoke the sense of sound.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sight&lt;/strong&gt;: The painting itself, along with a mirror reflecting a wine glass.&lt;/li&gt;
&lt;/ul&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%2F3icz9ibj0ngf9g37v9ss.jpg" 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%2F3icz9ibj0ngf9g37v9ss.jpg" alt="Pieter Claesz Still Life" width="800" height="439"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image: Still Life with Musical Instruments - 1623&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Redacta successfully identified the specific painting (&lt;em&gt;Still Life with Musical Instruments&lt;/em&gt;) from the transcript context and embedded it exactly where the description occurs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;This is the raw transcript (input):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;transcript: &lt;a href="https://github.com/julcasans/redacta/blob/main/examples/analisis_de_las_5_alegorias.srt" rel="noopener noreferrer"&gt;analisis_de_las_5_alegorias.srt&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;And these are the generated texts (output):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;formatted text: &lt;a href="https://github.com/julcasans/redacta/blob/main/examples/analisis_de_las_5_alegorias_formatted.md" rel="noopener noreferrer"&gt;analisis_de_las_5_alegorias_formatted.md&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;blog: &lt;a href="https://github.com/julcasans/redacta/blob/main/examples/analisis_de_las_5_alegorias_blog.md" rel="noopener noreferrer"&gt;analisis_de_las_5_alegorias_blog.md&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;summary: &lt;a href="https://github.com/julcasans/redacta/blob/main/examples/analisis_de_las_5_alegorias_summary.md" rel="noopener noreferrer"&gt;analisis_de_las_5_alegorias_summary.md&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Repository
&lt;/h3&gt;

&lt;p&gt;Here you can find the repository:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/julcasans/redacta" rel="noopener noreferrer"&gt;Redacta&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  My Experience with GitHub Copilot CLI
&lt;/h2&gt;

&lt;p&gt;I used GitHub Copilot CLI from the very first line of code. It wasn't just a helper; it was a fundamental partner in the architectural journey of Redacta.&lt;/p&gt;

&lt;h3&gt;
  
  
  Philosophical Approach: "CLI First, Automation Second"
&lt;/h3&gt;

&lt;p&gt;My workflow followed a strict "CLI First" philosophy. Before writing a single line of automation logic, I used the GitHub Copilot CLI to "sketch" my ideas. I would explain my high-level goal to the CLI and work with it to set up the project structure and basic foundations.&lt;/p&gt;

&lt;p&gt;This prevented over-engineering. I only started building the actual script once I had physically verified the core logic (like specific prompt outputs) manually within the CLI environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros of Using GitHub Copilot CLI
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Iterative Prompt Engineering&lt;/strong&gt;: The biggest advantage was the speed of testing. I started with the 'Editor' prompt—the core of Redacta. In the CLI, I could pipe a raw transcript to Copilot, apply a prompt, and see results in seconds. If the punctuation was off, I'd adjust the prompt and re-run instantly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Boilerplate Prototyping&lt;/strong&gt;: I didn't have to set up unit tests or local environments just to see if an LLM could handle a specific formatting task. The CLI provided a sandbox where I could test models and prompts as if they were simple shell commands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context-Aware Scaffolding&lt;/strong&gt;: When I was ready to move from a manual prompt to a script, I could ask the CLI to read my project files and suggest the automation logic, ensuring the new code fit perfectly with existing patterns.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Seamless Integration with Copilot SDK
&lt;/h3&gt;

&lt;p&gt;The Copilot SDK was the secret weapon that bridged the gap between experimentation and production. Once I was happy with a prompt's performance in the CLI, I used the SDK to embed that exact intelligence into my code. &lt;/p&gt;

&lt;p&gt;The transition was frictionless; the SDK allowed me to keep the same models and prompt structures I had already "stress-tested" in the CLI. This "Copy-Paste Intelligence" approach significantly reduced the debugging time usually associated with integrating LLMs into a codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  High-Impact Improvements
&lt;/h3&gt;

&lt;p&gt;As Redacta grew, the CLI handled the "heavy lifting" that usually slows down a project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript Migration&lt;/strong&gt;: It assisted in migrating the entire project from JavaScript to TypeScript, suggesting types and handling the boilerplate with precision.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing Suite&lt;/strong&gt;: It helped scaffold a comprehensive testing suite with Vitest, ensuring that as I refined the prompts, I wasn't breaking core functionality.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>cli</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>All CORS explained from A to Z</title>
      <dc:creator>Julio Castillo Anselmi</dc:creator>
      <pubDate>Sat, 24 Jun 2023 08:54:05 +0000</pubDate>
      <link>https://dev.to/julcasans/all-cors-explained-from-a-to-z-36mh</link>
      <guid>https://dev.to/julcasans/all-cors-explained-from-a-to-z-36mh</guid>
      <description>&lt;h2&gt;
  
  
  CORS definition
&lt;/h2&gt;

&lt;p&gt;Before defining CORS, some fundamental concepts to understand CORS will be defined.&lt;/p&gt;

&lt;h3&gt;
  
  
  origin
&lt;/h3&gt;

&lt;p&gt;Given a URL, the origin is the first part that is made up of the scheme: the host and the port (if present).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;source = scheme + host + port&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, in &lt;code&gt;https://localhost:8080/surveys&lt;/code&gt; the source is &lt;code&gt;https://localhost:8080&lt;/code&gt; and &lt;code&gt;/survey&lt;/code&gt; is the path&lt;/p&gt;

&lt;h3&gt;
  
  
  same-origin
&lt;/h3&gt;

&lt;p&gt;It refers to the case where the client makes a request to a server and the server has the same origin as the client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://aurora.net/home -&amp;gt; https://aurora.net/api/pos?id=290
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  cross-origin (cross-origin)
&lt;/h3&gt;

&lt;p&gt;The client makes a request to a server whose origin is different from that of the client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://localhost:8080/home -&amp;gt; https://aurora.net/api/pos?id=290
https://localhost:8080/home -&amp;gt; https://127.0.0.1:8080/api/pos?id=290
https://localhost:8080/home -&amp;gt; https://127.0.0.1:3000/api/pos?id=290
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Same-origin policy and CORS
&lt;/h3&gt;

&lt;p&gt;By default and by security policy, browsers only allow HTTP requests to the same origin, that is, to the same domain as the page that makes the request.&lt;/p&gt;

&lt;p&gt;CORS (Cross-Origin Resource Sharing) is the mechanism by which browsers allow a request to be made from one origin to a different one, cross-origin.&lt;/p&gt;

&lt;p&gt;In order to make a CORS request, the client does not have to do anything, it simply launches the request. The browser makes the request and it is the server that must respond if it accepts requests from that origin. It does this by sending the &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; header response. This header can have an asterisk (&lt;code&gt;*&lt;/code&gt;) or a specific origin. The &lt;code&gt;*&lt;/code&gt; means that the server accepts requests from any origin.&lt;br&gt;
The browser reviews the browser's response. If you have the &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; header and it has the value &lt;code&gt;*&lt;/code&gt; or the origin matches the client origin, then the browser accepts the response. Otherwise, it discards it and generally displays a CORS-descriptive error on the console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; 1. browser with origin X makes a request to origin Y
 2. server responds
 3. If the response from the server includes the header `Access-Control-Allow-Origin` Then
 4. If (Access-Control-Allow-Origin == '*') or (Access-Control-Allow-Origin == X) Then
 5. browser accepts the response
 6. If not
 7. discard response and show error
 8. End Yes
 9. If not
10. discard response and show error
11. End Yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; can also be set to &lt;code&gt;null&lt;/code&gt; for unknown origins (such as accessing from a file instead of a website). This is useful while you are in a development or testing phase, this way you don't need to put '*' which is less restrictive. &lt;code&gt;Access-Control-Allow-Origin: null&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Preflight
&lt;/h2&gt;

&lt;p&gt;Above we have seen in a generic way how a cross-origin request should be treated using CORS. Actually, before making a cross-origin request, browsers that implement CORS will "meta" the actual request.&lt;/p&gt;

&lt;p&gt;A preflight is a request that the browser makes before making a CORS request if the request meets one of these criteria:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use an HTTP method other than &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt;, or &lt;code&gt;HEAD&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;Content-Type&lt;/code&gt; header to a value other than:
-application/x-www-form-urlencoded

&lt;ul&gt;
&lt;li&gt;multipart/form-data
-text/plain&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Set additional headers other than:
-&lt;code&gt;Accept&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Accept-Language&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Content-Language&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;The XMLHttpRequest object contains upload events&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The HTTP methods &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt; and &lt;code&gt;HEAD&lt;/code&gt; are called simple methods. Simple methods do not need to be listed in the &lt;code&gt;Control-Allow-Methods&lt;/code&gt; header.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The preflight is a request with the &lt;code&gt;OPTIONS&lt;/code&gt; HTTP method. This "meta" request that the browser makes is for the server to decide how to respond to CORS. In the preflight the browser sends the headers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Origin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Access-Control-Request-Method&lt;/code&gt; (supports only one method)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Access-Control-Request-Headers&lt;/code&gt; (only if the headers are not simple. You can have a comma-separated list of headers)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The server checks if the HTTP origin and method are in its list of allowed origins and methods (it will also check the headers indicated in &lt;code&gt;Access-Control-Request-Headers&lt;/code&gt;, if any). If this check is favorable, it responds with a status code in the range &lt;code&gt;200&lt;/code&gt;. The answer should not wear a bodysuit. The headers sent by the server are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Access-Control-Allow-Methods&lt;/code&gt; (in this case it can be a comma separated list of commands)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Access-Control-Allow-Headers&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example of preflight request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OPTIONS /api/posts HTTP/1.1
User-Agent: Chrome
Host: 127.0.0.1:8080
Accept: */*
Origin: http://localhost:3000
Access-Control-Request-Method: GET
Access-Control-Request-Headers: Security-Level, App-Name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example preflight response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP/1.1 204 No Content
Access-Control-Allow-Origin: http//localhost:3000
Access-Control-Allow-Methods: GET, DELETE
Access-Control-Allow-Headers: Security-Level, App-Name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Request example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /api/posts HTTP/1.1
User-Agent: Chrome
Host: 127.0.0.1:8080
Accept: */*
Origin: http://localhost:3000
Security-Level: High
App-Name: Survey
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The previous algorithm, now modified with the preflights, would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  1. the Javascript client whose origin is X, makes a request P to the server with origin Y.
        P contains the HTTP method M and a set of headers C
  2. If M is a simple HTTP method and all C headers are simple Then
  3. send the request P to the server
  4. If not
  5. prepare a preflight request F with HTTP OPTIONS method and a set of headers C' with:
         Origin = X, Access-Control-Request-Method = M
  6. If in C there are headers that are not simple Then
  7. add to C' the Access-Control-Request-Headers header with the list of non-simple C headers
  8. End Yes
  9. send preflight F to server
10 If server responds to preflight with status in the range of 200 Then
11. send the request P to the server
12. If not
13. Check the Access-Control-Allow-Origin response headers,
           Access-Control-Allow-Methods and Access-Control-Allow-Headers to determine which
           are the validations that have failed and report the error
14. End Yes
15. End Yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Cache. The browser can cache the preflights and thus avoid making an extra request for each client request that would require a preflight. The cache saves on its origin + path entries.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Canvas and images
&lt;/h2&gt;

&lt;p&gt;For images whose &lt;code&gt;src&lt;/code&gt; attribute is a different origin than the client, the browser loads the resource and displays it but does not allow manipulations with it such as &lt;code&gt;toBlob&lt;/code&gt;, &lt;code&gt;toDataURL&lt;/code&gt;, and &lt;code&gt;getImageData&lt;/code&gt;.&lt;br&gt;
To enable CORS in the case of images, there is the &lt;code&gt;crossOrigin&lt;/code&gt; attribute that can take the values &lt;code&gt;anonymous&lt;/code&gt; or &lt;code&gt;user-credentials&lt;/code&gt;. &lt;code&gt;user-credentials&lt;/code&gt; is like &lt;code&gt;withCredentials&lt;/code&gt; in XMLHttpRequest, ie user credentials (eg cookies) are sent with the request. If it is not necessary to send the credentials, it is preferable to send &lt;code&gt;anonymous&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cookies and user credentials
&lt;/h2&gt;

&lt;p&gt;By default the browser does not send user credentials as cookies in cross-origin requests. The browser also does not expose all the response headers that the server sends.&lt;br&gt;
That's why CORS has mechanisms to remedy those restrictions: the &lt;code&gt;Access-Control-Allow-Credentials&lt;/code&gt; and &lt;code&gt;Access-Control-Expose-Headers&lt;/code&gt; response headers.&lt;/p&gt;

&lt;p&gt;So for the use of cookies it is necessary for the client to indicate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withCredentials&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;someUniqueId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server must respond to the preflight and the request with the headers&lt;br&gt;
&lt;code&gt;Access-Control-Allow-Credentials&lt;/code&gt; and &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When the server sends the &lt;code&gt;Access-Control-Allow-Credentials&lt;/code&gt; header with the value &lt;code&gt;true&lt;/code&gt;, it must send the &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; header with a specific origin; &lt;code&gt;Access-Control-Allow-Origin: *&lt;/code&gt; is invalid because accepting cookies from any origin can cause security problems.&lt;/p&gt;

&lt;p&gt;Valid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Access-Control-Allow-Origin: http://localhost:1111
Access-Control-Allow-Credentials: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Invalid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Access-Control-Allow-Origin: \*
Access-Control-Allow-Credentials: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the case where the client has &lt;code&gt;xhr.withCredentials = true&lt;/code&gt; and the server responds with &lt;code&gt;Access-Control-Allow-Origin: true&lt;/code&gt;, the server can set cookies on the client. These cookies will be sent by the browser in successive requests, however, the client will not be able to read these cookies with Javascript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Response headers
&lt;/h2&gt;

&lt;p&gt;The XMLHttpRequest object exposes two methods for reading response headers: &lt;code&gt;getResponseHeader&lt;/code&gt; and &lt;code&gt;getAllResponseHeaders&lt;/code&gt;. In a same-origin request these methods return all the headers sent by the server. When dealing with a cross-origin request, only the plain headers can be read.&lt;/p&gt;

&lt;p&gt;Using the &lt;code&gt;Access-Control-Expose-Headers&lt;/code&gt; header the server can specify which headers the client can read.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Access-Control-Expose-Headers: X-Powered-By
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Simple headers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Cache-Control&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Content-Language&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Content-Type&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Expires&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Last-Modified&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pragma&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Summary of headers used in CORS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Request headers (sent by client browser)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Origin&lt;/code&gt;: Header added by the browser. Contains the origin of the client in the request. Counterpart: &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Access-Control-Request-Method&lt;/code&gt;: Header added by the browser in the preflight. Contains the HTTP method that the client will do on the actual request. Counterpart: &lt;code&gt;Access-Control-Allow-Methods&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Access-Control-Request-Headers&lt;/code&gt;: Header added by the browser in the preflight. Contains the HTTP headers that the client will send in the actual request. Counterpart: &lt;code&gt;Access-Control-Allow-Headers&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Response headers (sent by the server)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt;: The value &lt;code&gt;*&lt;/code&gt; indicates that all origins are allowed&lt;br&gt;
A specific value indicates that the server only accepts requests from that source&lt;br&gt;
The value &lt;code&gt;null&lt;/code&gt; indicates that it only accepts requests from sources that are not a web site, for example a file (only recommended for development and testing). Counterpart: &lt;code&gt;Origin&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Access-Control-Allow-Credentials&lt;/code&gt;: The value &lt;code&gt;true&lt;/code&gt; indicates that the server supports the use of user credentials such as cookies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Access-Control-Allow-Methods&lt;/code&gt;: Has a list of HTTP methods accepted by the server.&lt;br&gt;
It is not necessary to include the simple methods, although it is good practice to do so.&lt;br&gt;
This header should only be sent in response to preflight requests. Counterpart: &lt;code&gt;Access-Control-Request-Methods&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Access-Control-Allow-Headers&lt;/code&gt;: Has a list of HTTP headers accepted by the server.&lt;br&gt;
This header should only be sent in response to preflight requests. Counterpart: &lt;code&gt;Access-Control-Request-Headers&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Access-Control-Max-Age&lt;/code&gt;: Its value specifies the maximum time in seconds that it is recommended to keep a preflight cache, although the browser can have its own maximum value.&lt;br&gt;
This header should only be sent in response to preflight requests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Access-Control-Expose-Headers&lt;/code&gt;: Contains the headers that can be read by the browser. You can have a comma separated list of headers.&lt;br&gt;
It is optional and is not required for the CORS request to be successful.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>cors</category>
      <category>http</category>
      <category>backend</category>
    </item>
    <item>
      <title>Todo CORS explicado de la A a la Z</title>
      <dc:creator>Julio Castillo Anselmi</dc:creator>
      <pubDate>Mon, 02 Jan 2023 19:19:40 +0000</pubDate>
      <link>https://dev.to/julcasans/todo-cors-explicado-de-la-a-a-la-z-4ch0</link>
      <guid>https://dev.to/julcasans/todo-cors-explicado-de-la-a-a-la-z-4ch0</guid>
      <description>&lt;h2&gt;
  
  
  Definición de CORS
&lt;/h2&gt;

&lt;p&gt;Antes de definir CORS se definirán algunos conceptos fundamentales para entender CORS.&lt;/p&gt;

&lt;h3&gt;
  
  
  origen
&lt;/h3&gt;

&lt;p&gt;Dada una URL, el origen es la primera parte que está compuesta por el esquema: el host y el puerto (si está presente).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;origen = esquema + host + puerto&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Por ejemplo, en &lt;code&gt;https://localhost:8080/encuestas&lt;/code&gt; el origen es &lt;code&gt;https://localhost:8080&lt;/code&gt; y &lt;code&gt;/encuesta&lt;/code&gt; es el path&lt;/p&gt;

&lt;h3&gt;
  
  
  mismo-origen (same-origin)
&lt;/h3&gt;

&lt;p&gt;Se refiere al caso en el que cliente hace una petición a un servidor y el servidor tiene el mismo origen que el cliente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://aurora.net/home -&amp;gt; https://aurora.net/api/pos?id=290
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  origen-cruzado (cross-origen)
&lt;/h3&gt;

&lt;p&gt;El cliente hace una petición a un servidor cuyo origen es distinto al del cliente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://localhost:8080/home -&amp;gt; https://aurora.net/api/pos?id=290
https://localhost:8080/home -&amp;gt; https://127.0.0.1:8080/api/pos?id=290
https://localhost:8080/home -&amp;gt; https://127.0.0.1:3000/api/pos?id=290
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Política de mismo-origen y CORS
&lt;/h3&gt;

&lt;p&gt;Por defecto y por política de seguridad, los navegadores sólo permiten hacer peticiones HTTP al mismo origen, es decir al mismo dominio del de la página que hace la petición.&lt;/p&gt;

&lt;p&gt;CORS (Cross-Origin Resource Sharing) es el mecanismo por el cual los navegadores permiten que una petición se haga desde un origen a otro distinto, origen-cruzado.&lt;/p&gt;

&lt;p&gt;Para poder realizar una petición CORS el cliente no debe hacer nada, simplemente lanza la petición. El navegador hace la petición y es el servidor el que debe responder si acepta peticiones desde ese origen. Esto lo hace enviando la cabecera (header response) &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt;. Esta cabecera puede tener un asterisco (&lt;code&gt;*&lt;/code&gt;) o un origen específico. El &lt;code&gt;*&lt;/code&gt; significa que el servidor acepta peticiones de cualquier origen.&lt;br&gt;
El navegador revisa la respuesta del navegador. Si tiene la cabecera &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; y ésta tiene el valor &lt;code&gt;*&lt;/code&gt; o el origen coincide con el origen del cliente, entonces el navegador acepta la respuesta. En caso contrario la descarta y generalmente muestra en consola un error descriptivo de CORS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; 1. navegador con origen X hace petición a origen Y
 2. servidor responde
 3. Si la respuesta del servidor incluye la cabecera `Access-Control-Allow-Origin` Entonces
 4.   Si (Access-Control-Allow-Origin == '*') o (Access-Control-Allow-Origin == X) Entonces
 5.     navegador acepta la respuesta
 6.   Si no
 7.     descarta respuesta y muestra error
 8.   Fin Si
 9. Si no
10.   descarta respuesta y muestra error
11. Fin Si
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; también puede tomar el valor &lt;code&gt;null&lt;/code&gt; para orígenes desconocidos (como por ejemplo en el caso de acceder desde un fichero en vez de un sitio web). Esto es útil mientras se está en una fase de desarrollo o pruebas, de esta manera no hace falta poner '*' que es menos restrictivo. &lt;code&gt;Access-Control-Allow-Origin: null&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Preflight
&lt;/h2&gt;

&lt;p&gt;Arriba se ha visto de manera genérica cómo se debe tratar una petición de origen-cruzado usando CORS. En realidad, antes de hacer una petición de origen-cruzado, los navegadores que implementan CORS harán una "meta" petición previa (preflight) a la petición real.&lt;/p&gt;

&lt;p&gt;Un preflight es una petición que hace el navegador antes de efectuar una petición CORS si dicha petición cumple uno de estos criterios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usa un método HTTP distinto de &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt;, o &lt;code&gt;HEAD&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Establece la cabecera &lt;code&gt;Content-Type&lt;/code&gt; con un valor distinto de:

&lt;ul&gt;
&lt;li&gt;application/x-www-form-urlencoded&lt;/li&gt;
&lt;li&gt;multipart/form-data&lt;/li&gt;
&lt;li&gt;text/plain&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Establece cabeceras adicionales distintas de:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Accept&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Accept-Language&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Content-Language&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;El objeto XMLHttpRequest contiene eventos upload&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;A los métodos HTTP &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt; y &lt;code&gt;HEAD&lt;/code&gt; se los denomina métodos simples. Los métodos simples no necesitan ser listados en la cabecera &lt;code&gt;Control-Allow-Methods&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;El preflight es una petición con el método HTTP &lt;code&gt;OPTIONS&lt;/code&gt;. Esta "meta" petición que hace el navegador sirve para que el servidor decida cómo responder al CORS. En el preflight el navegador envía las cabeceras:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Origin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Access-Control-Request-Method&lt;/code&gt; (admite sólo un método)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Access-Control-Request-Headers&lt;/code&gt; (sólo si las cabeceras no son simples. Puede tener una lista de cabeceras separada por comas)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;El servidor comprueba si el origen y el método HTTP están en su lista de orígenes y métodos permitidos (también comprobará las cabeceras indicadas en &lt;code&gt;Access-Control-Request-Headers&lt;/code&gt;, si es que lo hay). Si esta comprobación es favorable responde con un código de status en el rango &lt;code&gt;200&lt;/code&gt;. La respuesta no debería llevar un body. Las cabeceras enviadas por el servidor son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Access-Control-Allow-Methods&lt;/code&gt; (en este caso puede ser una lista de comandos separados por coma)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Access-Control-Allow-Headers&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ejemplo de petición preflight:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OPTIONS /api/posts HTTP/1.1
User-Agent: Chrome
Host: 127.0.0.1:8080
Accept: */*
Origin: http://localhost:3000
Access-Control-Request-Method: GET
Access-Control-Request-Headers: Security-Level, App-Name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ejemplo de respuesta preflight:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP/1.1 204 No Content
Access-Control-Allow-Origin: http//localhost:3000
Access-Control-Allow-Methods: GET, DELETE
Access-Control-Allow-Headers: Security-Level, App-Name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ejemplo de petición:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /api/posts HTTP/1.1
User-Agent: Chrome
Host: 127.0.0.1:8080
Accept: */*
Origin: http://localhost:3000
Security-Level: High
App-Name: Encuesta
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El algoritmo anterior, ahora modificado con los preflight quedaría así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; 1. el cliente Javascript cuyo origen es X, hace una petición P al servidor con origen Y.
       P contiene el método HTTP M y un conjunto de cabeceras C
 2. Si M es un método HTTP simple y todas las cabeceras de C son simples Entonces
 3.   enviar la petición P al servidor
 4. Si no
 5.   preparar una petición preflight F con método HTTP OPTIONS y un conjunto de cabeceras C' con:
        Origin = X, Access-Control-Request-Method = M
 6.   Si en C hay cabeceras que no son simples Entonces
 7.     agregar a C' la cabecera Access-Control-Request-Headers con el listado de cabeceras no simples de C
 8.   Fin Si
 9.   enviar preflight F al servidor
10    Si servidor responde el preflight con status en el rango de 200 Entonces
11.     enviar la petición P al servidor
12.   Si no
13.     comprobar las cabeceras de respuesta Access-Control-Allow-Origin,
          Access-Control-Allow-Methods y Access-Control-Allow-Headers para determinar cuáles
          son las validaciones que han fallado e informar el error
14.   Fin Si
15. Fin Si
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Cache. El navegador puede guardar en caché los preflights y así evitar hacer una petición extra por cada petición del cliente que requeriría preflight. La caché guarda en sus entradas origen + path.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Canvas e imágenes
&lt;/h2&gt;

&lt;p&gt;En el caso de imágenes cuyo atributo &lt;code&gt;src&lt;/code&gt; es un origen distinto al del cliente, el navegador carga el recurso y lo muestra pero no permite hacer manipulaciones con ella como &lt;code&gt;toBlob&lt;/code&gt;, &lt;code&gt;toDataURL&lt;/code&gt; y &lt;code&gt;getImageData&lt;/code&gt;.&lt;br&gt;
Para habilitar el CORS en el caso de imágenes, existe el atributo &lt;code&gt;crossOrigin&lt;/code&gt; que puede tomar los valores &lt;code&gt;anonymous&lt;/code&gt; o &lt;code&gt;user-credentials&lt;/code&gt;. &lt;code&gt;user-credentials&lt;/code&gt; es como el &lt;code&gt;withCredentials&lt;/code&gt; de XMLHttpRequest, es decir que las credenciales de usuario (por ejemplo, cookies) se envían con la petición. Si no es necesario enviar las credenciales, es preferible enviar &lt;code&gt;anonymous&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cookies y credenciales de usuario
&lt;/h2&gt;

&lt;p&gt;Por defecto el navegador no envía las credenciales de usuario como las cookies en las peticiones de origen-cruzado. El navegador tampoco expone todos las cabeceras de respuesta que envía el servidor.&lt;br&gt;
Por eso CORS tiene mecanismos para remediar esas restricciones: las cabeceras de respuesta &lt;code&gt;Access-Control-Allow-Credentials&lt;/code&gt; y &lt;code&gt;Access-Control-Expose-Headers&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Entonces para que el uso de cookies es necesario que el cliente indique:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;xhr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withCredentials&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;someUniqueId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El servidor debe responder al preflight y a la petición con las cabeceras&lt;br&gt;
&lt;code&gt;Access-Control-Allow-Credentials&lt;/code&gt; y &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Cuando servidor envía la cabecera &lt;code&gt;Access-Control-Allow-Credentials&lt;/code&gt; con el valor &lt;code&gt;true&lt;/code&gt;, debe enviar la cabecera &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; con un origen específico; &lt;code&gt;Access-Control-Allow-Origin: *&lt;/code&gt; es inválido porque aceptar cookies de cualquier origen puede generar problemas de seguridad.&lt;/p&gt;

&lt;p&gt;Válido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Access-Control-Allow-Origin: http://localhost:1111
Access-Control-Allow-Credentials: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inválido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Access-Control-Allow-Origin: \*
Access-Control-Allow-Credentials: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En el caso en el que el cliente tiene &lt;code&gt;xhr.withCredentials = true&lt;/code&gt; y el servidor responde con &lt;code&gt;Access-Control-Allow-Origin: true&lt;/code&gt;, el servidor puede establecer cookies en el cliente. Estas cookies serán enviadas por el navegador en las peticiones sucesivas, sin embargo, el client no podrá leer dichas cookies con Javascript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cabeceras de respuesta
&lt;/h2&gt;

&lt;p&gt;El objeto XMLHttpRequest expone dos métodos para leer las cabeceras de respuesta: &lt;code&gt;getResponseHeader&lt;/code&gt; y &lt;code&gt;getAllResponseHeaders&lt;/code&gt;. En una petición mismo-origen estos métodos devuelven todas las cabeceras enviadas por el servidor. Cuando se trata de una petición de origen-cruzado, sólo se pueden leer las cabeceras simples.&lt;/p&gt;

&lt;p&gt;Usando la cabecera &lt;code&gt;Access-Control-Expose-Headers&lt;/code&gt; el servidor puede especificar qué cabeceras puede leer el cliente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Access-Control-Expose-Headers: X-Powered-By
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Cabeceras simples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Cache-Control&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Content-Language&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Content-Type&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Expires&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Last-Modified&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pragma&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Resumen de cabeceras usadas en CORS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Cabeceras de petición (enviadas por el navegador cliente)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Origin&lt;/code&gt;: Cabecera que añade el navegador. Contiene el origen del cliente en la petición. Contraparte: &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Access-Control-Request-Method&lt;/code&gt;: Cabecera que añade el navegador en el preflight. Contiene el método HTTP que se hará el cliente en la petición real. Contraparte: &lt;code&gt;Access-Control-Allow-Methods&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Access-Control-Request-Headers&lt;/code&gt;: Cabecera que añade el navegador en el preflight. Contiene las cabeceras HTTP que enviará el cliente en la petición real. Contraparte: &lt;code&gt;Access-Control-Allow-Headers&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cabeceras de respuesta (enviadas por el servidor)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt;: El valor &lt;code&gt;*&lt;/code&gt; indica que se permiten todos los orígenes&lt;br&gt;
Un valor específico indica que el servidor sólo acepta peticiones de ese origen&lt;br&gt;
El valor &lt;code&gt;null&lt;/code&gt; indica que sólo acepta peticiones de orígenes que no son un sitio web, por ejemplo un fichero (sólo recomendado para desarrollo y pruebas). Contraparte: &lt;code&gt;Origin&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Access-Control-Allow-Credentials&lt;/code&gt;: El valor &lt;code&gt;true&lt;/code&gt; indica que el servidor soporta el uso de credenciales de usuario tales como las cookies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Access-Control-Allow-Methods&lt;/code&gt;: Tiene una lista de métodos HTTP aceptados por el servidor.&lt;br&gt;
No es necesario incluir los métodos simples, aunque es buena práctica hacerlo.&lt;br&gt;
Esta cabecera sólo debe enviarse en respuesta a peticiones preflight. Contraparte: &lt;code&gt;Access-Control-Request-Methods&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Access-Control-Allow-Headers&lt;/code&gt;: Tiene una lista de cabeceras HTTP aceptadas por el servidor.&lt;br&gt;
Esta cabecera sólo debe enviarse en respuesta a peticiones preflight. Contraparte:&lt;code&gt;Access-Control-Request-Headers&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Access-Control-Max-Age&lt;/code&gt;: Su valor especifica el tiempo máximo en segundos que se recomienda mantener en caché un preflight, aunque el navegador puede tener su propio valor máximo.&lt;br&gt;
Esta cabecera sólo debe enviarse en respuesta a peticiones preflight.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Access-Control-Expose-Headers&lt;/code&gt;: Contiene las cabeceras que pueden ser leídos por el navegador. Puede tener una lista de cabeceras separada por comas.&lt;br&gt;
Es opcional y no es necesario para que la petición CORS sea exitosa.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>github</category>
      <category>opensource</category>
      <category>discuss</category>
    </item>
    <item>
      <title>LitElement in depth: the update lifecycle</title>
      <dc:creator>Julio Castillo Anselmi</dc:creator>
      <pubDate>Sat, 07 Mar 2020 10:50:07 +0000</pubDate>
      <link>https://dev.to/julcasans/litelement-in-depth-the-update-lifecycle-18nk</link>
      <guid>https://dev.to/julcasans/litelement-in-depth-the-update-lifecycle-18nk</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;📣 &lt;strong&gt;UPDATE!&lt;/strong&gt; 📣&lt;br&gt;
&lt;em&gt;Now lit-html and LitElement are unified under &lt;a href="https://lit.dev/" rel="noopener noreferrer"&gt;Lit&lt;/a&gt;.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;I'm writing new posts about &lt;strong&gt;Lit&lt;/strong&gt;, meanwhile you can:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;read this post because the principles are the same&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;upgrade your code with this &lt;a href="https://lit.dev/docs/releases/upgrade/" rel="noopener noreferrer"&gt;guide&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;visit &lt;em&gt;Lit&lt;/em&gt; site to know what's new&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;You can also use &lt;a href="https://lit.dev/docs/libraries/standalone-templates/" rel="noopener noreferrer"&gt;lit-html standalone&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Although &lt;strong&gt;lit-html&lt;/strong&gt; is very efficient rendering, it is better to render only when necessary. That is why &lt;strong&gt;LitElement&lt;/strong&gt; differs the re-rendering of the UI by batching the property updates. In other words, re-rendering is done asynchronously to ensure efficiency and good performance. Let's see how the update process works.&lt;/p&gt;

&lt;p&gt;Recall from the previous post that all the properties defined in the &lt;code&gt;properties&lt;/code&gt; getter become properties "controlled" by &lt;strong&gt;LitElement&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For each property defined in the &lt;code&gt;properties&lt;/code&gt; getter, &lt;strong&gt;LitElement&lt;/strong&gt; will generate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;code&gt;hasChanged&lt;/code&gt; function&lt;/li&gt;
&lt;li&gt;a setter and a getter&lt;/li&gt;
&lt;li&gt;an observed attribute&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;fromAttribute&lt;/code&gt; function &lt;/li&gt;
&lt;li&gt;a &lt;code&gt;toAttribute&lt;/code&gt; function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In particular, we are interested in the &lt;code&gt;hasChanged&lt;/code&gt; function and the setters because they play an important role in the update life cycle.&lt;/p&gt;

&lt;p&gt;Almost all the "magic" is based on the setter that causes the component to be re-rendered when the property changes. First, it checks if the property has changed (invoking the &lt;code&gt;hasChanged&lt;/code&gt; function) and, if that is the case, it will make a rendering request.&lt;br&gt;
Also, if the property is reflected in an attribute, the setter will update the observed attribute using the &lt;code&gt;toAttribute&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;LitElement&lt;/strong&gt; class we find the following methods that participate in the update of the UI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;requestUpdate&lt;/li&gt;
&lt;li&gt;performUpdate&lt;/li&gt;
&lt;li&gt;shouldUpdate&lt;/li&gt;
&lt;li&gt;update&lt;/li&gt;
&lt;li&gt;render&lt;/li&gt;
&lt;li&gt;firstUpdated&lt;/li&gt;
&lt;li&gt;updated&lt;/li&gt;
&lt;li&gt;updateComplete&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we have seen the main pieces involved in the re-rendering, we will go into detail on how this process occurs.&lt;/p&gt;
&lt;h1&gt;
  
  
  The update cycle in action
&lt;/h1&gt;

&lt;p&gt;Imagine you have a function with this piece of code:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#myElement&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Movements&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//previous value was 'No title'&lt;/span&gt;
&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;book.ico&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//previous value was undefined&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateComplete&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;1. The &lt;code&gt;title&lt;/code&gt; property setter is executed. This setter calls &lt;code&gt;hasChanged&lt;/code&gt; function of the &lt;code&gt;title&lt;/code&gt; property. As it has changed, it returns &lt;code&gt;true&lt;/code&gt; and in that case it calls &lt;code&gt;performUpdate&lt;/code&gt;, a method of the &lt;strong&gt;LitElement&lt;/strong&gt; class. This method verifies if there is a previous request pending, in that case it does nothing. If there isn't, it will create a micro-task (a promise) to execute the rendering. This is &lt;strong&gt;LitElement&lt;/strong&gt;'s way of asynchronously executing the &lt;code&gt;render&lt;/code&gt; method and batch property changes.&lt;/li&gt;
&lt;li&gt;2. We continue with the following line. Now the &lt;code&gt;icon&lt;/code&gt; property setter  is executed. The setter calls &lt;code&gt;hasChanged&lt;/code&gt; function, which returns &lt;code&gt;true&lt;/code&gt;, so it calls the&lt;code&gt;performUpdate&lt;/code&gt; method, but as a UI update operation is already pending, it does nothing else.&lt;/li&gt;
&lt;li&gt;3. Finally, our code is awaiting for the &lt;code&gt;updateComplete&lt;/code&gt; promise to be resolved, that will occur when the update cycle is over.&lt;/li&gt;
&lt;li&gt;4. Now that there are no tasks on the stack, it is time to execute the micro task that was scheduled (in the step 1). It does the following:&lt;/li&gt;
&lt;li&gt;4.1. It invokes &lt;code&gt;shouldUpdate&lt;/code&gt;, another method of the &lt;strong&gt;LitElement&lt;/strong&gt; class. This method receives the properties that have changed and their old values. The purpose of this method is to evaluate all the batched changes that have occurred and based on that decide whether or not the update should be done. By default it returns &lt;code&gt;true&lt;/code&gt;, but &lt;strong&gt;LitElement&lt;/strong&gt; gives us this hook in case we want to put a special logic to avoid the update. Following our example, &lt;code&gt;shouldUpdate&lt;/code&gt; receives &lt;code&gt;title =&amp;gt; 'No title'&lt;/code&gt;, &lt;code&gt;icon =&amp;gt; undefined&lt;/code&gt; and returns &lt;code&gt;true&lt;/code&gt;, so the update continues.&lt;/li&gt;
&lt;li&gt;4.2. It executes the &lt;code&gt;update&lt;/code&gt; method of the &lt;strong&gt;LitElement&lt;/strong&gt; class. Here the changes are reflected to the attributes to maintain synchrony between properties and attributes (only for those properties defined with &lt;code&gt;reflect&lt;/code&gt;). Then it calls the &lt;code&gt;render&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;4.2.1. The &lt;code&gt;render&lt;/code&gt; function is executed, the DOM is updated.&lt;/li&gt;
&lt;li&gt;4.2.2. If it is the first time the component is rendered, the &lt;code&gt;firstUpdated&lt;/code&gt; method will be executed. It's a hook that &lt;strong&gt;LitElement&lt;/strong&gt; gives us to over-write if we need to do initialization tasks once the component is rendered.&lt;/li&gt;
&lt;li&gt;4.2.3. Then the &lt;code&gt;updated&lt;/code&gt; method of the &lt;strong&gt;LitElement&lt;/strong&gt; class is executed. This is another hook. Unlike &lt;code&gt;firstUpdated&lt;/code&gt;, this method will always be called after every rendering.&lt;/li&gt;
&lt;li&gt;4.2.4. The &lt;code&gt;updateComplete&lt;/code&gt; promise get resolved.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftamasjwt0m9p9uak4sbi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftamasjwt0m9p9uak4sbi.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;👉 All the properties defined in the &lt;code&gt;properties&lt;/code&gt; getter become properties "controlled" by LitElement and any update of their values ​​will cause a rendering. This is why we should put there only the properties that affect the visual representation of the component: those that we have used in the template.&lt;br&gt;
For example, if we have a &lt;code&gt;debug&lt;/code&gt; property that is used to indicate if traces are written by &lt;code&gt;console.log&lt;/code&gt;, changing this property should not cause an UI update.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Live example
&lt;/h2&gt;

&lt;p&gt;To understand it better, I have made this very silly component. The important part is that I have traced each method of the update lifecycle.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/litelement-update-cycle?" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When the component is rendered the first time you can find among the traces that there is an invocation to the &lt;code&gt;firstUpdated&lt;/code&gt; method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I have traced the &lt;code&gt;_requestUpdate&lt;/code&gt; and &lt;code&gt;_enqueueUpdate&lt;/code&gt; methods that are private methods of &lt;code&gt;UpdatingElement&lt;/code&gt; which is the class of which &lt;code&gt;LitElement&lt;/code&gt; class extends. Although these methods are not an "official" part of the update lifecycle, seeing how &lt;strong&gt;LitElement&lt;/strong&gt; uses them internally helps to understand the update process. We can see that &lt;code&gt;_requestUpdate&lt;/code&gt; is called for every property that changes but &lt;code&gt;_enqueueUpdate&lt;/code&gt; it's called only once: with the first property that changed. When there's an update process pending, &lt;code&gt;_enqueueUpdate&lt;/code&gt; is not invoked again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The first time you press the button, it will update the &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;icon&lt;/code&gt; properties. At this moment the component will be already rendered so you won't find a call to &lt;code&gt;firstUpdate&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The second time you press the button, it will update again the &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;icon&lt;/code&gt; properties with the same values it did before. As the property values have no changes, the update cycle is not triggered.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I have included the source code of the &lt;code&gt;UpdatingElement&lt;/code&gt; class because I think you can understand it and see in detail how the UI update process is implemented.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  requestUpdate
&lt;/h1&gt;

&lt;p&gt;Sometimes it may be necessary to manually trigger the re-rendering cycle. It is not enough to invoke the &lt;code&gt;render&lt;/code&gt; method, because as we have seen, the process is much more complex. For these cases, &lt;strong&gt;LitElement&lt;/strong&gt; provides the &lt;code&gt;requestUpdate&lt;/code&gt; method that will trigger the whole lifecycle update.&lt;/p&gt;

&lt;p&gt;A typical case where we should invoke &lt;code&gt;requestUpdate&lt;/code&gt; is when we define our own setter and we want that a change in the property to cause a re-rendering. As we have seen before, for each controlled property &lt;strong&gt;LitElement&lt;/strong&gt; generates a setter that evaluates whether the property has changed and if so, it updates the UI. But when we write our own setter, we lose the setter that would be generated by &lt;strong&gt;LitElement&lt;/strong&gt;, because of this, we have to do by ourselves what &lt;strong&gt;LitElement&lt;/strong&gt; does. We should do:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &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;_title&lt;/span&gt; &lt;span class="o"&gt;!===&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&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;oldValue&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="nx"&gt;_title&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;_title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&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;requestUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;oldValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Called from within a custom property setter&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;blockquote&gt;
&lt;p&gt;👉 When we invoke &lt;code&gt;requestUpdate&lt;/code&gt; from a setter we must pass the property name and the old value as arguments. On the other hand, if we force a re-render from elsewhere, &lt;code&gt;requestUpdate&lt;/code&gt; has no arguments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  This is the end
&lt;/h1&gt;

&lt;p&gt;With this last topic about the UI update lifecycle we complete the basics of &lt;strong&gt;LitElement&lt;/strong&gt;. You already have the fundamental knowledge to continue your path in &lt;strong&gt;lit-html&lt;/strong&gt; and &lt;strong&gt;LitElement&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To go deeper in these libraries I highly recommend reading the official documentation. It's It is very clear, concise and very well organised. In addition, each topic is accompanied by a live example in &lt;a href="https://stackblitz.com/" rel="noopener noreferrer"&gt;Stackblitz&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lit.dev/" rel="noopener noreferrer"&gt;Lit project guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also suggest you read the source code of &lt;strong&gt;lit-html&lt;/strong&gt; and &lt;strong&gt;LitElement&lt;/strong&gt;. It is relatively short, well documented and with what you already know you will not find it difficult to understand. This way everything will be much clearer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/lit/lit/" rel="noopener noreferrer"&gt;Lit source code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Last but not least, two important contributions from the community: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/web-padawan/awesome-lit" rel="noopener noreferrer"&gt;awesome lit&lt;/a&gt; - A wonderful collection of resources made by &lt;a href="https://twitter.com/serhiikulykov" rel="noopener noreferrer"&gt;@serhiikulykov&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://open-wc.org/" rel="noopener noreferrer"&gt;open-wc&lt;/a&gt; - Web component recommendations with a bunch of powerful and battle-tested setup for sharing open source web components.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Last words...
&lt;/h1&gt;

&lt;p&gt;With this post I finish my series on LitElement. I hope you found it useful and enjoyed it as much as I did writing it. Thank you for having come this far! ❤️&lt;/p&gt;

</description>
      <category>webcomponents</category>
      <category>litelement</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>PolymerElement is dead, long live LitElement!</title>
      <dc:creator>Julio Castillo Anselmi</dc:creator>
      <pubDate>Wed, 20 Nov 2019 22:03:36 +0000</pubDate>
      <link>https://dev.to/julcasans/polymerelement-is-dead-long-live-litelement-5f45</link>
      <guid>https://dev.to/julcasans/polymerelement-is-dead-long-live-litelement-5f45</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;📣 &lt;strong&gt;UPDATE!&lt;/strong&gt; 📣&lt;br&gt;
&lt;em&gt;Now lit-html and LitElement are unified under &lt;a href="https://lit.dev/"&gt;Lit&lt;/a&gt;.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;I'm writing new posts about &lt;strong&gt;Lit&lt;/strong&gt;, meanwhile you can:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;read this post because the principles are the same&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;upgrade your code with this &lt;a href="https://lit.dev/docs/releases/upgrade/"&gt;guide&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;visit &lt;em&gt;Lit&lt;/em&gt; site to know what's new&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;You can also use &lt;a href="https://lit.dev/docs/libraries/standalone-templates/"&gt;lit-html standalone&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hello my friends! We've finally reached the main subject of this series: &lt;strong&gt;LitElement&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  A new class to rule web components
&lt;/h1&gt;

&lt;p&gt;To understand what &lt;strong&gt;LitElement&lt;/strong&gt; is and what it does for us, we will return to where we left in the previous post. Let's remember what we did last time, we used &lt;strong&gt;lit-html&lt;/strong&gt; to create a web component capable of re-rendering when the value of a component's property changed.&lt;/p&gt;

&lt;p&gt;To achieve that, we had to create a class with a constructor that was responsible for creating the shadow DOM and reflecting the values ​​of the HTML attributes to the component properties. Then, to get the component re-render every time a property changes we had to write a setter for each one of them and call the &lt;strong&gt;lit-html&lt;/strong&gt; &lt;code&gt;render&lt;/code&gt; function inside that setter.&lt;br&gt;
And last but not least, we had to write code in order to keep HTML properties and attributes in sync.&lt;/p&gt;

&lt;p&gt;All this results in repetitive code that increases according to the number of properties that the component has. To create a better developer experience, the &lt;strong&gt;Polymer&lt;/strong&gt; team thought that it would be good to have a class that handles all this burden for us. As well as they made &lt;strong&gt;PolymerElement&lt;/strong&gt;, but this time they had to evolve and take advantage of their wonderful &lt;strong&gt;lit-html&lt;/strong&gt;, so it wouldn't be a new version of &lt;strong&gt;PolymerElement&lt;/strong&gt;, it had to be totally new, and so they created &lt;strong&gt;LitElement&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LitElement&lt;/strong&gt; not only frees us from repetitive code, it also makes &lt;strong&gt;lit-html&lt;/strong&gt; rendering even more efficient by making it happen asynchronously.&lt;/p&gt;

&lt;p&gt;So, &lt;strong&gt;LitElement&lt;/strong&gt; is a lightweight class to create web components. It handles for us all the repetitive code needed to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use shadow DOM&lt;/li&gt;
&lt;li&gt;keep in sync HTML attributes and component properties&lt;/li&gt;
&lt;li&gt;efficiently render (using &lt;strong&gt;lit-html&lt;/strong&gt;) the component every time a property changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see the minimal code that a &lt;strong&gt;LitElement&lt;/strong&gt; needs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Import the LitElement base class and html helper function&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LitElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lit-element&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Import other element if it needed&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;package-name/other-element.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Extend the LitElement base class&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyElement&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;LitElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="cm"&gt;/**
   * Implement `render` to define a template for your element.
   *
   * You must provide an implementation of `render` for any element
   * that uses LitElement as a base class.
   */&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * `render` must return a lit-html `TemplateResult`.
     *
     * To create a `TemplateResult`, tag a JavaScript template literal
     * with the `html` helper function:
     */&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
      &amp;lt;!-- template content --&amp;gt;
      &amp;lt;p&amp;gt;A paragraph&amp;lt;/p&amp;gt;
      &amp;lt;other-element&amp;gt;&amp;lt;/other-element&amp;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;span class="c1"&gt;// Register the new element with the browser.&lt;/span&gt;
&lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&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;my-element&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MyElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you've seen the only requirement is to implement the &lt;code&gt;render&lt;/code&gt; function that draws the component's UI. This function must return a &lt;code&gt;TemplateResult&lt;/code&gt; and that is because it will call the &lt;code&gt;render&lt;/code&gt; function provided by &lt;strong&gt;lit-html&lt;/strong&gt; (notice we also import the &lt;code&gt;html&lt;/code&gt; function). This is very important because everything that we've seen in &lt;a href="https://dev.to/julcasans/lit-html-templates-from-zero-to-hero-2afm"&gt;previous posts&lt;/a&gt; of &lt;strong&gt;lit-html&lt;/strong&gt; applies to &lt;strong&gt;LitElement&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We could summarize &lt;strong&gt;LitElement&lt;/strong&gt; in a very simplistic formula:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;LitElement&lt;/code&gt; = &lt;code&gt;lit-html&lt;/code&gt; + &lt;code&gt;shadow DOM&lt;/code&gt; + &lt;code&gt;auto async render&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  LitElement's render function
&lt;/h1&gt;

&lt;p&gt;The &lt;code&gt;render&lt;/code&gt; function has a great importance in &lt;strong&gt;LitElement&lt;/strong&gt; because it defines how the component will look. When you see the defined template you should understand how the component will be painted in every situation. There's no other place where the component's UI can be modified or updated. And what is more, whenever a property changes (the component's state changes) &lt;strong&gt;LitElement&lt;/strong&gt; will call the &lt;code&gt;render&lt;/code&gt; function to update the component representation. So it turns out that the UI is expressed as function of the component's state.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;UI = f(state)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;According to this functional approach the template should be written as a pure function of the properties of the component, such that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It doesn't change the status of the component&lt;/li&gt;
&lt;li&gt;It has no side effects&lt;/li&gt;
&lt;li&gt;It only depends on the properties of the component&lt;/li&gt;
&lt;li&gt;It always returns the same value if the properties have not changed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This results in a great developer experience because you don't need to worry about how to update the component when something has changed. It will be re-rendered according to the new state and the performance impact of the rendering action has no value due to the efficiency of &lt;strong&gt;lit-html&lt;/strong&gt; plus the asynchronous optimization added by &lt;strong&gt;LitElement&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Without this solution, we would have rendered the component once (the first time) and would have written additional code to update some part of the component for each possible state change and, in general, this code would have had many conditions and considerations. In the long run, updating the visual representation depending on the changes in the state of the component becomes an arduous task and a lot of code to maintain.&lt;/p&gt;

&lt;p&gt;Also in the re-render approach, the component's UI is defined declaratively and in one place. The classic approach (update UI parts) is imperative and the logic is distributed in many functions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Our first LitElement component
&lt;/h1&gt;

&lt;p&gt;Do you remember the &lt;code&gt;&amp;lt;password-checker&amp;gt;&lt;/code&gt; component that we created with &lt;strong&gt;lit-html&lt;/strong&gt; in the previous post?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lit-html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PasswordChecker&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&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;attachShadow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;open&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;password&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;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&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;get&lt;/span&gt; &lt;span class="nf"&gt;password&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="nx"&gt;_password&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nf"&gt;password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&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;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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;update&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;render&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;template&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;shadowRoot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;eventContext&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="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;passwd&lt;/span&gt;&lt;span class="p"&gt;)&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;re&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(?=&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;\d)(?=&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;a-z&lt;/span&gt;&lt;span class="se"&gt;])(?=&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;A-Z&lt;/span&gt;&lt;span class="se"&gt;])&lt;/span&gt;&lt;span class="sr"&gt;.&lt;/span&gt;&lt;span class="se"&gt;{4,}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;passwd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;template&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="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
      &amp;lt;span&amp;gt;Your password is &amp;lt;strong&amp;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;isValid&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;password&lt;/span&gt;&lt;span class="p"&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;valid 👍&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;INVALID 👎&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/strong&amp;gt;&amp;lt;/span&amp;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;isValid&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;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;
        &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;div&amp;gt;Strength: &amp;lt;progress value=&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;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; max="5"&amp;lt;/progress&amp;gt;&amp;lt;/div&amp;gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;``&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&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;password-checker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PasswordChecker&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's see how that component is implemented using &lt;strong&gt;LitElement&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LitElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lit-element&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PasswordChecker&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;LitElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;properties&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="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;passwd&lt;/span&gt;&lt;span class="p"&gt;)&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;re&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(?=&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;\d)(?=&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;a-z&lt;/span&gt;&lt;span class="se"&gt;])(?=&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;A-Z&lt;/span&gt;&lt;span class="se"&gt;])&lt;/span&gt;&lt;span class="sr"&gt;.&lt;/span&gt;&lt;span class="se"&gt;{4,}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;passwd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&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="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
      &amp;lt;span&amp;gt;Your password is &amp;lt;strong&amp;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;isValid&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;password&lt;/span&gt;&lt;span class="p"&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;valid 👍&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;INVALID 👎&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/strong&amp;gt;&amp;lt;/span&amp;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;isValid&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;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;
        &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;div&amp;gt;Strength: &amp;lt;progress value=&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;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; max="5"&amp;lt;/progress&amp;gt;&amp;lt;/div&amp;gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;``&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&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;password-checker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PasswordChecker&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing to notice is that there is no constructor. We don't need it in this case. We don't need to add a &lt;em&gt;shadow root&lt;/em&gt; because &lt;strong&gt;LitElement&lt;/strong&gt; does that for us. When &lt;strong&gt;LitElement&lt;/strong&gt; renders a component, it calls &lt;strong&gt;lit-html&lt;/strong&gt;'s &lt;code&gt;render&lt;/code&gt; function and that function expects an argument that is a node where to paint the component. &lt;strong&gt;LitElement&lt;/strong&gt; creates the &lt;strong&gt;shadow root&lt;/strong&gt; for the component and passes it to the &lt;strong&gt;lit-html&lt;/strong&gt;'s &lt;code&gt;render&lt;/code&gt; function. It's very similar to what we did in the &lt;code&gt;update&lt;/code&gt; function of the &lt;strong&gt;lit-html&lt;/strong&gt; version.&lt;br&gt;
If for whatever reason we don't want our component to use shadow DOM, we can overwrite the &lt;code&gt;createRenderRoot&lt;/code&gt; function and return a &lt;code&gt;this&lt;/code&gt; value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;createRenderRoot&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although &lt;strong&gt;LitElement&lt;/strong&gt; does many things for us, it also lets us customize the default behaviour by overriding some functions. We'll see that &lt;strong&gt;LitElement&lt;/strong&gt; is very flexible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Properties and update
&lt;/h2&gt;

&lt;p&gt;Our &lt;strong&gt;lit-html&lt;/strong&gt; version of &lt;code&gt;&amp;lt;password-checker&amp;gt;&lt;/code&gt; had a setter for the property &lt;code&gt;password&lt;/code&gt; and in that function we updated the HTML attribute and invoked the &lt;code&gt;render&lt;/code&gt; function. &lt;strong&gt;LitElement&lt;/strong&gt; does the same thing for us. &lt;em&gt;All the brilliance things happens when we define the getter function &lt;code&gt;properties&lt;/code&gt;&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;properties&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="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&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;Every property that is defined inside this function will be controlled by &lt;strong&gt;LitElement&lt;/strong&gt; so that a change of its value will cause the component to be re-rendered.&lt;br&gt;
Thus for each declared property &lt;strong&gt;LitElement&lt;/strong&gt; will provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an observed attribute&lt;/li&gt;
&lt;li&gt;accessors&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hasChanged&lt;/code&gt; function&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fromAttribute&lt;/code&gt; function&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;toAttribute&lt;/code&gt; function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see in detail what they are:&lt;/p&gt;
&lt;h3&gt;
  
  
  Observed attribute
&lt;/h3&gt;

&lt;p&gt;Suppose your component has a property called &lt;code&gt;birthYear&lt;/code&gt;, you will be able to use the attribute &lt;code&gt;birthyear&lt;/code&gt; in the markup&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;my-comp&lt;/span&gt; &lt;span class="na"&gt;birthyear=&lt;/span&gt;&lt;span class="s"&gt;"1973"&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;and &lt;strong&gt;LitElement&lt;/strong&gt; will assign that value to the property but it previously converts the &lt;code&gt;String&lt;/code&gt; value to the property's type (&lt;code&gt;Number&lt;/code&gt; in this case) using the &lt;code&gt;fromAttribute&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;👉 Notice that, by default, the attribute's name is the property's name in lowercase. You can change it by using the &lt;code&gt;attribute&lt;/code&gt; key in the property definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;properties&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;birthYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// the observed attribute will be birth-year instead of birthyear&lt;/span&gt;
      &lt;span class="na"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;birth-year&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although by default &lt;strong&gt;LitElement&lt;/strong&gt; passes values from attributes to properties, the opposite is not true. If you want a change in a property value to be reflected in HTML attribute you must explicitly tell so using the key &lt;code&gt;reflect&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;properties&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;birthYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// the observed attribute will be birth-year instead of birthyear&lt;/span&gt;
      &lt;span class="na"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;birth-year&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="na"&gt;reflect&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  hasChanged
&lt;/h3&gt;

&lt;p&gt;It's a function that checks if the new value is different from the previous value. In that case it returns &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;⚠️ Be careful with values that are objects or arrays because the comparison is made at top level, it doesn't do a shallow comparison, so if you evaluate &lt;code&gt;obj1 === obj2&lt;/code&gt; you're comparing references. In that cases you should override &lt;code&gt;hasChanged&lt;/code&gt; to do the proper comparison.&lt;/p&gt;

&lt;h3&gt;
  
  
  fromAttribute
&lt;/h3&gt;

&lt;p&gt;It is the function that converts the &lt;code&gt;String&lt;/code&gt; value of the observed attribute to the real type of the property. You can provide your custom converter by overriding &lt;code&gt;fromAttribute&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  toAttribute
&lt;/h3&gt;

&lt;p&gt;It is the function used to convert the property value into a &lt;code&gt;String&lt;/code&gt; value so that it can be assigned to the observed attribute in the markup code (HTML). This function is used by &lt;strong&gt;LitElement&lt;/strong&gt; when the property has been set to &lt;code&gt;reflect&lt;/code&gt;.&lt;br&gt;
If you need a custom converter, then override &lt;code&gt;toAttribute&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Accessors
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;LitElement&lt;/strong&gt; generates accessors, a &lt;em&gt;getter&lt;/em&gt; and a &lt;em&gt;setter&lt;/em&gt;, for declared properties. In the &lt;em&gt;setter&lt;/em&gt; relies almost all the &lt;em&gt;'magic'&lt;/em&gt; that causes the component to be re-rendered when a property changes. First it checks if the property has changed (invoke &lt;code&gt;hasChanged&lt;/code&gt; function) and if that's the case, then it will trigger an UI update.&lt;br&gt;
Also if, the property is reflected to an attribute, the setter will update the observed attribute using the function &lt;code&gt;toAttribute&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you provide your own &lt;em&gt;getter&lt;/em&gt; or &lt;em&gt;setter&lt;/em&gt; or both, then &lt;strong&gt;LitElement&lt;/strong&gt; won't create any accessor for that property. Just keep in mind that if you write your own setter and you want that a change causes a re-render, you'll have to make the same things that ** LitElement ** 's getter does.&lt;br&gt;
You can also avoid auto-generated getter and setter using the key &lt;code&gt;noAccessor&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;properties&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;birthYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;noAccessor&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I summarize these points in an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// properties getter&lt;/span&gt;
&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;properties&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="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// by default, every declared property: &lt;/span&gt;
    &lt;span class="c1"&gt;//  - has an observed attribute,&lt;/span&gt;
    &lt;span class="c1"&gt;//  - when the attribute changes, it updates the property&lt;/span&gt;
    &lt;span class="c1"&gt;//  - has a getter and a setter&lt;/span&gt;
    &lt;span class="c1"&gt;//  - changes in value triggers a render update&lt;/span&gt;
    &lt;span class="c1"&gt;//  - has a default hasChanged function&lt;/span&gt;
    &lt;span class="c1"&gt;//  - has default converters: fromAttribute, toAttribute&lt;/span&gt;
    &lt;span class="c1"&gt;//  - all of this can be customized&lt;/span&gt;
    &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// type is the minimum required information&lt;/span&gt;
    &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="na"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;last-name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
               &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;enrolled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="na"&gt;reflect&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;noAccessor&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="nf"&gt;hasChanged&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="nx"&gt;oldValue&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="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zipCode&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nx"&gt;oldValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zipCode&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="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;       &lt;span class="p"&gt;{&lt;/span&gt;
                 &lt;span class="na"&gt;converter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                   &lt;span class="nf"&gt;toAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                   &lt;span class="p"&gt;}&lt;/span&gt;
                   &lt;span class="nf"&gt;fromAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;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;As last remarks, we observe that the &lt;code&gt;properties&lt;/code&gt; getter is very similar to the &lt;code&gt;properties&lt;/code&gt; getter that we used in &lt;strong&gt;PolymerElement&lt;/strong&gt; but the &lt;strong&gt;LitElement&lt;/strong&gt; version lacks the following features:&lt;/p&gt;

&lt;h3&gt;
  
  
  initial value
&lt;/h3&gt;

&lt;p&gt;In &lt;strong&gt;PolymerElement&lt;/strong&gt;'s &lt;code&gt;properties&lt;/code&gt; getter we can assign an initial value to a property, but that's not possible in &lt;strong&gt;LitElement&lt;/strong&gt;, we must do that in the constructor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// PolymerElement &lt;/span&gt;
&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;properties&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;birthYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1973&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="c1"&gt;// LitElement&lt;/span&gt;
&lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Don't forget to call super() !!!&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;birthYear&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1973&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;
  
  
  observed properties
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;LitElement&lt;/strong&gt; has no observed attributes. You can use a setter to perform actions when the property changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// PolymerElement &lt;/span&gt;
&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;properties&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;birthYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_yearChanged&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// LitElement&lt;/span&gt;
&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nf"&gt;birthYear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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 check if property hasChanged&lt;/span&gt;
  &lt;span class="c1"&gt;// and request UI update should go here&lt;/span&gt;
  &lt;span class="c1"&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;_birthYear&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// private _birthYear with getter birthYear&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;_yearChanged&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;
  
  
  computed properties
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;LitElement&lt;/strong&gt; doesn't have computed properties. To achieve the same result use getters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// PolymerElement &lt;/span&gt;
&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;properties&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;birthYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
           &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_computeAge(birthYear)&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// LitElement&lt;/span&gt;
&lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;age&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="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="nf"&gt;getFullYear&lt;/span&gt;&lt;span class="p"&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="nx"&gt;birthYear&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;Well, we've had enough already.&lt;br&gt;
So far the first part about &lt;strong&gt;LitElement&lt;/strong&gt;. In the next post I will tell you in detail how is the asynchronous rendering process and the life cycle of a &lt;strong&gt;LitElement&lt;/strong&gt; component.&lt;br&gt;
See you!&lt;/p&gt;

</description>
      <category>webcomponents</category>
      <category>litelement</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Use lit-html to create web components (à la React)</title>
      <dc:creator>Julio Castillo Anselmi</dc:creator>
      <pubDate>Fri, 05 Jul 2019 21:23:51 +0000</pubDate>
      <link>https://dev.to/julcasans/using-lit-html-to-create-web-components-a-la-react-118g</link>
      <guid>https://dev.to/julcasans/using-lit-html-to-create-web-components-a-la-react-118g</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;📣 &lt;strong&gt;UPDATE!&lt;/strong&gt; 📣&lt;br&gt;
&lt;em&gt;Now lit-html and LitElement are unified under &lt;a href="https://lit.dev/" rel="noopener noreferrer"&gt;Lit&lt;/a&gt;.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;I'm writing new posts about &lt;strong&gt;Lit&lt;/strong&gt;, meanwhile you can:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;read this post because the principles are the same&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;upgrade your code with this &lt;a href="https://lit.dev/docs/releases/upgrade/" rel="noopener noreferrer"&gt;guide&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;visit &lt;em&gt;Lit&lt;/em&gt; site to know what's new&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;You can also use &lt;a href="https://lit.dev/docs/libraries/standalone-templates/" rel="noopener noreferrer"&gt;lit-html standalone&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This post was going to be about directives in &lt;code&gt;lit-html&lt;/code&gt;, which is the way we can extend the library but I didn't want to keep delaying the arrival to our central theme of the series that is &lt;code&gt;LitElement&lt;/code&gt;. So I decided to leave the directives for later and enter the doors of &lt;code&gt;LitElement&lt;/code&gt;. I'm going to show you how to create web components using &lt;code&gt;lit-html&lt;/code&gt; and we'll see how we get to &lt;code&gt;LitElement&lt;/code&gt; from there. Let's get started!&lt;/p&gt;

&lt;h1&gt;
  
  
  The idea
&lt;/h1&gt;

&lt;p&gt;We are going to build a web component using only &lt;code&gt;lit-html&lt;/code&gt; but with a similar approach to &lt;strong&gt;React&lt;/strong&gt;, that is, we'll have a declarative template that defines exactly how the component UI is for its entire state and we'll also make that when a component property changes, a new rendering will update its UI.&lt;/p&gt;

&lt;p&gt;To define the UI, instead of JSX, we'll use template literals and the &lt;code&gt;html&lt;/code&gt; tag as we have seen in previous posts.&lt;br&gt;
We also know that &lt;code&gt;lit-html&lt;/code&gt; is super efficient rendering so we won't have any issues if we invoke the &lt;code&gt;render&lt;/code&gt; function every time a property changes.&lt;/p&gt;

&lt;p&gt;The component that we will create will be very simple at a visual and functional level. Do not expect us to make a mega component, not for now. In this publication we want to focus on the basic concepts for creating web components.&lt;/p&gt;

&lt;p&gt;So our component will be a password checker: a component that given a password it tells if it is valid or invalid and if it is valid it also tells us how strong it is.&lt;/p&gt;

&lt;p&gt;The rules that apply are these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The password is valid if:

&lt;ul&gt;
&lt;li&gt;it has at least 4&lt;/li&gt;
&lt;li&gt;It has at least one lower case letter.&lt;/li&gt;
&lt;li&gt;It has at least one capital letter.&lt;/li&gt;
&lt;li&gt;it has at least one digit&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If it is valid, a bar that measures its strength is shown.&lt;/li&gt;
&lt;li&gt;If it is invalid, the strength bar is not shown.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Valid password example&lt;/strong&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;password-checker&lt;/span&gt; &lt;span class="na"&gt;password=&lt;/span&gt;&lt;span class="s"&gt;"aB1sgX4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/password-checker&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9z5ld452env57idlnp6t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9z5ld452env57idlnp6t.png" width="260" height="68"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Invalid password example&lt;/strong&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;password-checker&lt;/span&gt; &lt;span class="na"&gt;password=&lt;/span&gt;&lt;span class="s"&gt;"aB1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/password-checker&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fud7l9w0phgcspm06vas4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fud7l9w0phgcspm06vas4.png" width="266" height="53"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  The code
&lt;/h1&gt;

&lt;p&gt;We create a &lt;code&gt;password-checker.js&lt;/code&gt; file and in the first line we'll import the &lt;code&gt;html&lt;/code&gt; and &lt;code&gt;render&lt;/code&gt; functions from &lt;code&gt;lit-html&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lit-html&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;Then, as we do with any other web component, we create a class that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;extends &lt;code&gt;HTMLElement&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;has a constructor that creates the component's shadow DOM.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Also, our component has a property to keep the password and it should be initialized with the value defined by the user in the HTML file, as we can see here: &lt;code&gt;&amp;lt;password-checker password="aB1"&amp;gt;&lt;/code&gt;. We do that in the last line of the constructor.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PasswordChecker&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&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;attachShadow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;open&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;password&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;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now let's think of the visual representation and define the template:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nf"&gt;template&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="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
      &amp;lt;span&amp;gt;Your password is &amp;lt;strong&amp;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;isValid&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;password&lt;/span&gt;&lt;span class="p"&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;valid 👍&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;INVALID 👎&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/strong&amp;gt;&amp;lt;/span&amp;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;isValid&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;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; 
        &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;div&amp;gt;Strength: &amp;lt;progress value=&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;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; max="5"&amp;lt;/progress&amp;gt;&amp;lt;/div&amp;gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;``&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;The template uses a conditional expression to show the strength bar only if the password is valid. Also note that the property &lt;code&gt;password&lt;/code&gt; is the essential part of the template, its value defines how the component is presented. Any change to the &lt;code&gt;password&lt;/code&gt; property has to trigger an UI update causing a re-rendering of the component. How can we achieve that?&lt;/p&gt;

&lt;p&gt;It's easy, we create a setter for the &lt;code&gt;password&lt;/code&gt; property so that when updating its value we force an update of the component. We also want the &lt;code&gt;password&lt;/code&gt; attribute of the HTML element to have the new value. This is the code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nf"&gt;password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&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;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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;update&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;password&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="nx"&gt;_password&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;render&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;template&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;shadowRoot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;eventContext&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As we define a setter we also define a getter.&lt;br&gt;
The &lt;code&gt;update&lt;/code&gt; function invokes the &lt;code&gt;render&lt;/code&gt; function that will cause the component's UI to be updated. &lt;/p&gt;

&lt;p&gt;👉 The point to remark here is that we call the &lt;code&gt;render&lt;/code&gt; function passing the &lt;em&gt;shadowRoot&lt;/em&gt; of the component so that the template goes inside the component's shadow DOM. The third argument has the context that will be used in the event handlers (if there were). So we can have in our template something like this: &lt;br&gt;
&lt;code&gt;&amp;lt;button @click=${this.start}&amp;gt;Start&amp;lt;/button&amp;gt;&lt;/code&gt;. The &lt;code&gt;this&lt;/code&gt; in &lt;code&gt;@click=${this.start}&lt;/code&gt; has the context passed in the &lt;code&gt;eventContext&lt;/code&gt; property. If we don't pass the context, &lt;code&gt;this.start&lt;/code&gt; will fail.&lt;/p&gt;

&lt;p&gt;Finally we register the web component:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&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;password-checker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PasswordChecker&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The final code, all together is like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lit-html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PasswordChecker&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&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;attachShadow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;open&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;password&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;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&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;get&lt;/span&gt; &lt;span class="nf"&gt;password&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="nx"&gt;_password&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="nf"&gt;password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;_password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&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;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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;update&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;render&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;template&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;shadowRoot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;eventContext&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="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;passwd&lt;/span&gt;&lt;span class="p"&gt;)&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;re&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(?=&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;\d)(?=&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;a-z&lt;/span&gt;&lt;span class="se"&gt;])(?=&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;A-Z&lt;/span&gt;&lt;span class="se"&gt;])&lt;/span&gt;&lt;span class="sr"&gt;.&lt;/span&gt;&lt;span class="se"&gt;{4,}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;passwd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;template&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="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
      &amp;lt;span&amp;gt;Your password is &amp;lt;strong&amp;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;isValid&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;password&lt;/span&gt;&lt;span class="p"&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;valid 👍&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;INVALID 👎&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/strong&amp;gt;&amp;lt;/span&amp;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;isValid&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;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; 
        &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;div&amp;gt;Strength: &amp;lt;progress value=&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;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; max="5"&amp;lt;/progress&amp;gt;&amp;lt;/div&amp;gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;``&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&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;password-checker&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PasswordChecker&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Recap
&lt;/h1&gt;

&lt;p&gt;This is the recipe we have used to create web components &lt;em&gt;à la&lt;/em&gt; React.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Import &lt;code&gt;html&lt;/code&gt; and &lt;code&gt;render&lt;/code&gt; from &lt;code&gt;lit-html&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create a class that extends HTMLElement.&lt;/li&gt;
&lt;li&gt;Write a constructor that:

&lt;ul&gt;
&lt;li&gt;creates the shadow DOM.&lt;/li&gt;
&lt;li&gt;initializes properties from values in the HTML tag.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Write the template for the components UI.&lt;/li&gt;
&lt;li&gt;Write an update function that calls &lt;code&gt;render&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;For every property that a value change requires an update of the UI:

&lt;ul&gt;
&lt;li&gt;write a setter that updates the UI and synchronizes the property with its related HTML attribute.&lt;/li&gt;
&lt;li&gt;Write a getter.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Register the component. &lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;
  
  
  Live on Glitch
&lt;/h1&gt;

&lt;p&gt;You can see the code and play with it on my Glitch page.&lt;br&gt;
&lt;/p&gt;
&lt;div class="glitch-embed-wrap"&gt;
  &lt;iframe src="https://glitch.com/embed/#!/embed/handy-train?path=index.html" alt="handy-train on glitch"&gt;&lt;/iframe&gt;
&lt;/div&gt;



&lt;h1&gt;
  
  
  Final thoughts
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Similar to React but not like React
&lt;/h3&gt;

&lt;p&gt;The approach we used to create the component is similar to React but it is not exactly the same. We could say that the way we define the template it's the same but with a different implementation: React uses &lt;code&gt;JSX&lt;/code&gt;, a language that must be processed to generate JavaScript code, and &lt;code&gt;lit-html&lt;/code&gt; is based on JavaScript features so it doesn't require extra processing.&lt;br&gt;
The part in which they differ is in the update of the UI: React updates the component when we make a call to the &lt;code&gt;setState&lt;/code&gt; function and in our approach the update occurs 'automatically' when a property changes. It may seem a very subtle difference but it will be more evident when we see this same idea in &lt;code&gt;LitElement&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  lit-html in the real world
&lt;/h3&gt;

&lt;p&gt;Previously we have seen that &lt;code&gt;lit-html&lt;/code&gt; doesn't require a component model and therefore we can use it in a variety of projects even mixing it with other frameworks and libraries. And now we have just seen that with this library we can implement web components which makes it even more powerful and easier to integrate into other projects.&lt;/p&gt;

&lt;p&gt;There are several projects that use &lt;code&gt;lit-hmtl&lt;/code&gt;. I leave here some of them. The source of this information is this fantastic collection of resources on &lt;code&gt;lit-html&lt;/code&gt; that I recommend you take a look: &lt;a href="https://github.com/web-padawan/awesome-lit" rel="noopener noreferrer"&gt;Awesome Lit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Of course I also recommend &lt;a href="https://lit.dev/docs/libraries/standalone-templates/" rel="noopener noreferrer"&gt;the official &lt;code&gt;lit-html&lt;/code&gt; documentation&lt;/a&gt; that is clear and complete.&lt;/p&gt;

&lt;p&gt;Some projects based on &lt;code&gt;lit-html&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Festify/fit-html" rel="noopener noreferrer"&gt;Fit-html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ruphin/gluonjs" rel="noopener noreferrer"&gt;GluonJs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/SAP/ui5-webcomponents" rel="noopener noreferrer"&gt;ui5 WebComponents&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  LitElement is coming...
&lt;/h3&gt;

&lt;p&gt;Finally, in the next post I'll talk about &lt;code&gt;LitElement&lt;/code&gt;! See you soon.&lt;/p&gt;

</description>
      <category>lit</category>
      <category>litelement</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>lit-html templates from zero to hero</title>
      <dc:creator>Julio Castillo Anselmi</dc:creator>
      <pubDate>Mon, 17 Jun 2019 20:33:20 +0000</pubDate>
      <link>https://dev.to/julcasans/lit-html-templates-from-zero-to-hero-2afm</link>
      <guid>https://dev.to/julcasans/lit-html-templates-from-zero-to-hero-2afm</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;📣 &lt;strong&gt;UPDATE!&lt;/strong&gt; 📣&lt;br&gt;
&lt;em&gt;Now lit-html and LitElement are unified under &lt;a href="https://lit.dev/"&gt;Lit&lt;/a&gt;.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;I'm writing new posts about &lt;strong&gt;Lit&lt;/strong&gt;, meanwhile you can:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;read this post because the principles are the same&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;upgrade your code with this &lt;a href="https://lit.dev/docs/releases/upgrade/"&gt;guide&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;visit &lt;em&gt;Lit&lt;/em&gt; site to know what's new&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;You can also use &lt;a href="https://lit.dev/docs/libraries/standalone-templates/"&gt;lit-html standalone&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After a very smooth introduction to &lt;code&gt;lit-html&lt;/code&gt;, I will go hard and get my hands dirty. I will show you how to write templates so this will be a session full of code!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I know you are here because you want to learn &lt;code&gt;LitElement&lt;/code&gt;, so you read this title and find out that we continue with &lt;code&gt;lit-html&lt;/code&gt;. The reason why I've structured these sessions this way is because &lt;code&gt;lit-html&lt;/code&gt; is the basis for &lt;code&gt;LitElement&lt;/code&gt; and also because I want you to see the great potential and versatility of &lt;code&gt;lit-html&lt;/code&gt; by itself, probably the perfect match for a small or medium project. I assure you that everything you learn about &lt;code&gt;lit-html&lt;/code&gt; will be used in &lt;code&gt;LitElement&lt;/code&gt;. Be patient, we will arrive soon.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Writing templates
&lt;/h2&gt;

&lt;p&gt;☝️Remember from last post: templates are written using tagged template literals. We tag the template literal with the &lt;code&gt;html&lt;/code&gt; function provided by &lt;code&gt;lit-html&lt;/code&gt;. This function returns a &lt;code&gt;TemplateResult&lt;/code&gt; object. &lt;br&gt;
&lt;code&gt;render&lt;/code&gt; is the other function provided by &lt;code&gt;lit-html&lt;/code&gt;. &lt;code&gt;render&lt;/code&gt; receives a &lt;code&gt;TemplateResult&lt;/code&gt; object and renders it into the DOM.&lt;/p&gt;

&lt;p&gt;This is a very simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// import functions from lit-html library&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lit-html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// define the template as function that takes the data&lt;/span&gt;
&lt;span class="c1"&gt;// and returns a TemplateResult object&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
    &amp;lt;p&amp;gt;Hello &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// node where the template will be rendered&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mainNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// render the template&lt;/span&gt;
&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Silvia&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;mainNode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// render the template again with different data&lt;/span&gt;
&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Benjamin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;mainNode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dynamic parts of a template are JavaScript expressions that are binded with values. &lt;code&gt;TemplateResult&lt;/code&gt; supports bindings of certain data types that we will see now. &lt;/p&gt;

&lt;h3&gt;
  
  
  Supported bindings
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Text&lt;/strong&gt;: An expression that is resolved as text can be used as the text content of a node. Be aware that an empty string ('') in a text binding will render an empty text node.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Attribute&lt;/strong&gt;: an expression that returns a text can be used as the value of an attribute. When an attribute behaves like a boolean (it is present or not) we denote it with the name of the attribute preceded by &lt;code&gt;?&lt;/code&gt;. The value of the expression must be boolean, if it is &lt;code&gt;true&lt;/code&gt; &lt;code&gt;lit-html&lt;/code&gt; puts the attribute and if it is &lt;code&gt;false&lt;/code&gt; it removes it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Property&lt;/strong&gt;: An expression can also be binded to a JavaScript node's property. We write the property name with a &lt;code&gt;.&lt;/code&gt; at the beginning. In that case, the type of expression must match the type of the property (it could be any type even a complex object).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Event&lt;/strong&gt;: An expression can be the handler of an event. For this we write the event name preceded by &lt;code&gt;@&lt;/code&gt; and in this case we have several alternatives for the binding.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Global handler function&lt;/em&gt;: the expression resolves to a global function that will handle the event.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Inline function&lt;/em&gt;: the expression resolves to an inline function.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Instance function&lt;/em&gt;: the expression resolves to a function that belongs to your object.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Event listener object&lt;/em&gt;: the expression returns an object that &lt;em&gt;must have&lt;/em&gt; a function named &lt;code&gt;clickHandler&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;HTML node element&lt;/strong&gt;: the expression can return a DOM node.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;TemplateResult&lt;/strong&gt;: the expression can be another &lt;code&gt;TemplateResult&lt;/code&gt; object. This makes it possible to have composition of nested templates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Iterable of &lt;code&gt;TemplateResult&lt;/code&gt; objects&lt;/strong&gt;: expressions that returns an array or iterables of &lt;code&gt;TemplateResult&lt;/code&gt; objects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Promise&lt;/strong&gt;: the expression can return a promise that must be resolved returning a valid binding value.&lt;br&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Text binding&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;someText&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;div&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/div&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**** Given theses variables and values... **************

let someText = 'Lorem ipsum';
let user = { name : 'JEN', firstName: 'MONROE' };  

***** The code above will render... *********************

&amp;lt;p&amp;gt;Lore ipsum&amp;lt;/p&amp;gt;
&amp;lt;div&amp;gt;Jen Monroe&amp;lt;/div&amp;gt;
*********************************************************/&lt;/span&gt;


&lt;span class="c1"&gt;// Attribute binding&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;div class=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;Stylish text.&amp;lt;/div&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**** Given these variables and values... *****************

let classList = ['main', 'required', 'modern'].join(' ');

***** The code above will render... ***********************

&amp;lt;div class="main required modern"&amp;gt;Stylish text.&amp;lt;/div&amp;gt;
***********************************************************/&lt;/span&gt;


&lt;span class="c1"&gt;// Attribute binding (boolean)&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;input type="submit" ?disabled=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;formWithErrors&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; value="Submit"&amp;gt;
     &amp;lt;span ?hidden=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;formWithErrors&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;Form has errors!&amp;lt;/span&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="cm"&gt;/**** Given these variables and values... *****************

let formWithErrors = true;

***** The code above will render... ***********************

&amp;lt;input type="submit" disabled value="Submit"&amp;gt;`;
&amp;lt;span&amp;gt;Form has errors!&amp;lt;/span&amp;gt;`
***********************************************************/&lt;/span&gt;


&lt;span class="c1"&gt;// Property binding&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;custom-list .items=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; id="user-list"&amp;gt;&amp;lt;/custom-list&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**** Given these variables and values... *****************

const users = ['Diego', 'Ana', 'Laura', 'Piero'];
const customList = document.getElementById('user-list');
console.log(customList.items);

***** The code above will show in console *****************

 ["Diego", "Ana", "Laura", "Piero"]

***********************************************************/&lt;/span&gt;


&lt;span class="c1"&gt;// Event binding to a global handler function&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;button @click=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;Click Me!&amp;lt;/button&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 


&lt;span class="c1"&gt;// Event binding to an inline function&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;button @click=&lt;/span&gt;&lt;span class="p"&gt;${()&lt;/span&gt;&lt;span class="o"&gt;=&amp;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;clicked&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;Click Me!&amp;lt;/button&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 


&lt;span class="c1"&gt;// Event binding to an instance function&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;button @click=&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;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;Click Me!&amp;lt;/button&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="c1"&gt;// Event binding to listener object&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;button @click=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;clickHandler&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;Click Me!&amp;lt;/button&amp;gt;`&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;clickHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;handleEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;clicked!&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="p"&gt;};&lt;/span&gt;


&lt;span class="c1"&gt;// Binding to a DOM node&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;h1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Chapter 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;p&amp;gt;Once upon a time...&amp;lt;/p&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/***** The code above will render... **********************

&amp;lt;h1&amp;gt;Chapter 1&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;Once upon a time...&amp;lt;/p&amp;gt;
***********************************************************/&lt;/span&gt;


&lt;span class="c1"&gt;// Binding to a TemplateResult object&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;h1&amp;gt;Chapter 1&amp;lt;/h1&amp;gt;`&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;article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;article&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;p&amp;gt;Once upon a time...&amp;lt;/p&amp;gt;&amp;lt;/article&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/***** The code above will render... **********************

&amp;lt;article&amp;gt;
  &amp;lt;h1&amp;gt;Chapter 1&amp;lt;/h1&amp;gt;
  &amp;lt;p&amp;gt;Once upon a time...&amp;lt;/p&amp;gt;
&amp;lt;/article&amp;gt;
***********************************************************/&lt;/span&gt;


&lt;span class="c1"&gt;// Binding to arrays/iterables&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&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;listItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;li&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/li&amp;gt;`&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;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;ul&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;listItems&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/ul&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/***** The code above will render... **********************

&amp;lt;ul&amp;gt;
 &amp;lt;li&amp;gt;2&amp;lt;/li&amp;gt;
 &amp;lt;li&amp;gt;4&amp;lt;/li&amp;gt;
 &amp;lt;li&amp;gt;6&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
***********************************************************/&lt;/span&gt;


&lt;span class="c1"&gt;// Binding to a promise&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&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;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/***********************************************************
Let's say that after some seconds the fetch operation 
resolves with a the string 'some text...'

Until the promise is resolved, the code above will render
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt; 

Once the promise is resolved, it will render...
&amp;lt;p&amp;gt;some text...&amp;lt;/p&amp;gt;

***********************************************************/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Composition
&lt;/h3&gt;

&lt;p&gt;One consequence of having bindings to expressions that return &lt;code&gt;TemplateResult&lt;/code&gt; objects is that by composition we can create templates using other templates. The composition allows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a complex template using simpler templates.&lt;/li&gt;
&lt;li&gt;Refactor a complex template by diving it into simpler templates.&lt;/li&gt;
&lt;li&gt;Reuse of templates (the use of JavaScript modules makes reuse much easier, for example, a module of common templates, partial templates, etc.)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
    &amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;h1&amp;gt;
    &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtitle&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;h2&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtitle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;h2&amp;gt;`&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="s2"&gt;`&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;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;makeParagraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;`&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;composedTemplate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
    &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conditionals
&lt;/h3&gt;

&lt;p&gt;A template can have parts that are only visible if a condition is met, or it could have parts that are represented in different ways depending on one or more conditions. These behaviors can be expressed using conditional expressions such as the ternary operator &lt;code&gt;?&lt;/code&gt; or conditional structures such as the &lt;code&gt;if&lt;/code&gt; or &lt;code&gt;switch-case&lt;/code&gt; statements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// using ternary operator&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
    &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;
        &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;img src=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;&amp;lt;/img&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// using if&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&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="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;img src=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;&amp;lt;/img&amp;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;span class="c1"&gt;// using switch-case&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;screenSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;s&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;img src="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-small.png"&amp;gt;&amp;lt;/img&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;img src="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-medium.png"&amp;gt;&amp;lt;/img&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;l&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;img src="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-medium.png"&amp;gt;&amp;lt;/img&amp;gt;
                    &amp;lt;img src="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.png"&amp;gt;&amp;lt;/img&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;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;
  
  
  Iterations
&lt;/h3&gt;

&lt;p&gt;It is very common for a part of a template to be repeated with different values. Think of a list, where the part that paints each item is always the same but with different values. For these cases we have already seen that it is possible to make a binding to expressions that return iterables from &lt;code&gt;TemplateResult&lt;/code&gt; objects. This is the way we can repeat parts or blocks in a template.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;weekDays&lt;/span&gt; &lt;span class="o"&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;Monday&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;Tuesday&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;Wednesday&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;Thursday&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;Friday&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;Staurday&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;Sunday&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// loops with arrays&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;ul&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;weekDays&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;li&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/li&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/ul&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// loop statement (better if DOM node update is cheap)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;itemTemplates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="k"&gt;for &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;day&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;weekDays&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;itemTemplates&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="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;li&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/li&amp;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;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;ul&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;itemTemplates&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/ul&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/*************************************
* We'll see the use of directives 
* in a future post !!
*************************************/&lt;/span&gt;
&lt;span class="c1"&gt;// repeat directive (better if moving DOM node is cheap)&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;ul&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;weekDays&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="cm"&gt;/*id*/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;li&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/li&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/ul&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting things up
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;lit-html&lt;/code&gt; is distributed as a &lt;code&gt;npm&lt;/code&gt; package so to install it run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save&lt;/span&gt; lit-html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;lit-html&lt;/code&gt; uses JavaScript modules therefore to use the &lt;code&gt;html&lt;/code&gt; and &lt;code&gt;render&lt;/code&gt; functions we have to import them from the module.&lt;/p&gt;

&lt;p&gt;At the moment, browsers don't import ES6 modules using the short syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lit-html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We should write the full path to the module&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./node_modules/lit-html/lit-html.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if you want to use the short syntax you can use a built tool such as Webpack or you can install the Polymer command line tool that can handle the short syntax import when it serves the application. &lt;/p&gt;

&lt;p&gt;With Polymer CLI:&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;## install it&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; polymer-cli

&lt;span class="c"&gt;## use it&lt;/span&gt;
polymer serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're ready to start coding! I strongly recommend you to experiment and try your own examples. The best way to learn is by doing!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As we have seen, a template is pure JavaScript code so any expression and valid structure of the language can be used inside the template. There are so many ways to define a template that is only limited by the preferences or styles of each developer. The result is that the templates turn out to be tremendously expressive and because it is just JavaScript you don't need to learn nothing new.&lt;/p&gt;

</description>
      <category>lit</category>
      <category>litelement</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>lit-html templates from zero to hero for beginners</title>
      <dc:creator>Julio Castillo Anselmi</dc:creator>
      <pubDate>Mon, 17 Jun 2019 20:33:02 +0000</pubDate>
      <link>https://dev.to/julcasans/lit-html-templates-from-zero-to-hero-for-beginners-3eje</link>
      <guid>https://dev.to/julcasans/lit-html-templates-from-zero-to-hero-for-beginners-3eje</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;📣 &lt;strong&gt;UPDATE!&lt;/strong&gt; 📣&lt;br&gt;
&lt;em&gt;Now lit-html and LitElement are unified under &lt;a href="https://lit.dev/"&gt;Lit&lt;/a&gt;.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;I'm writing new posts about &lt;strong&gt;Lit&lt;/strong&gt;, meanwhile you can:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;read this post because the principles are the same&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;upgrade your code with this &lt;a href="https://lit.dev/docs/releases/upgrade/"&gt;guide&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;visit &lt;em&gt;Lit&lt;/em&gt; site to know what's new&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;You can also use &lt;a href="https://lit.dev/docs/libraries/standalone-templates/"&gt;lit-html standalone&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After a very smooth introduction to &lt;code&gt;lit-html&lt;/code&gt;, I will go hard and get my hands dirty. I will show you how to write templates so this will be a session full of code!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I know you are here because you want to learn &lt;code&gt;LitElement&lt;/code&gt;, so you read this title and find out that we continue with &lt;code&gt;lit-html&lt;/code&gt;. The reason why I've structured these sessions this way is because &lt;code&gt;lit-html&lt;/code&gt; is the basis for &lt;code&gt;LitElement&lt;/code&gt; and also because I want you to see the great potential and versatility of &lt;code&gt;lit-html&lt;/code&gt; by itself, probably the perfect match for a small or medium project. I assure you that everything you learn about &lt;code&gt;lit-html&lt;/code&gt; will be used in &lt;code&gt;LitElement&lt;/code&gt;. Be patient, we will arrive soon.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Setting things up
&lt;/h2&gt;

&lt;p&gt;First of all, we'll create a project where you'll be able to try each example you see here. I also suggest you make changes, experiment and create your own examples. The best way to learn is by doing.&lt;/p&gt;

&lt;p&gt;We create the project:&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;mkdir &lt;/span&gt;lit-train
&lt;span class="nb"&gt;cd &lt;/span&gt;lit-train
npm init &lt;span class="nt"&gt;--yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last command creates the &lt;code&gt;package.json&lt;/code&gt; file that we'll use to handle the dependencies.&lt;/p&gt;

&lt;p&gt;The next step is to install &lt;code&gt;lit-html&lt;/code&gt; using &lt;code&gt;npm&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;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save&lt;/span&gt; lit-html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the moment, browsers don't import ES6 modules using the short syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lit-html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We must write the full path to the module&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./node_modules/lit-html/lit-html.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, to use the short syntax we'll install &lt;code&gt;polymer-cli&lt;/code&gt;. The Polymer command line tool is able to serve our project and at the same time it handles the short syntax import. To do that just run the command &lt;code&gt;polymer serve&lt;/code&gt;. To make things easier we'll install &lt;code&gt;polymer-cli&lt;/code&gt; in our local project and in our package.json will add a script to run it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; polymer-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;package.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="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lit-train"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&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="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"polymer serve"&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="nl"&gt;"keywords"&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="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ISC"&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;Create an index.html file and write in it this code:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;index.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="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"main"&lt;/span&gt;&lt;span class="nt"&gt;&amp;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;"module"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lit-html.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// write your code here&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run the project execute this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're ready to start coding! Now you can continue reading and trying the examples in the project that you've just configured.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing templates
&lt;/h2&gt;

&lt;p&gt;☝️Remember from last post: templates are written using tagged template literals. We tag the template literal with the &lt;code&gt;html&lt;/code&gt; function provided by &lt;code&gt;lit-html&lt;/code&gt;. This function returns a &lt;code&gt;TemplateResult&lt;/code&gt; object. &lt;br&gt;
&lt;code&gt;render&lt;/code&gt; is the other function provided by &lt;code&gt;lit-html&lt;/code&gt;. &lt;code&gt;render&lt;/code&gt; receives a &lt;code&gt;TemplateResult&lt;/code&gt; object and renders it into the DOM.&lt;/p&gt;

&lt;p&gt;This is a very simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// import functions from lit-html library&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lit-html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// define the template as function that takes the data&lt;/span&gt;
&lt;span class="c1"&gt;// and returns a TemplateResult object&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
    &amp;lt;p&amp;gt;Hello &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;
  `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// node where the template will be rendered&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mainNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// render the template&lt;/span&gt;
&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Silvia&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;mainNode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// render the template again with different data&lt;/span&gt;
&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Benjamin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;mainNode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dynamic parts of a template are JavaScript expressions that are binded with values. &lt;code&gt;TemplateResult&lt;/code&gt; supports bindings of certain data types that we will see now. &lt;/p&gt;

&lt;h3&gt;
  
  
  Supported bindings
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Text&lt;/strong&gt;: An expression that is resolved as text can be used as the text content of a node. Be aware that an empty string ('') in a text binding will render an empty text node.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Text binding&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;someText&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;div&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/div&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**** Given these variables and values... ***************

let someText = 'Lorem ipsum';
let user = { name : 'JEN', firstName: 'MONROE' };  

***** The code above will render... *********************

&amp;lt;p&amp;gt;Lore ipsum&amp;lt;/p&amp;gt;
&amp;lt;div&amp;gt;Jen Monroe&amp;lt;/div&amp;gt;
*********************************************************/&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Attribute&lt;/strong&gt;: an expression that returns a text can be used as the value of an attribute.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Attribute binding&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;div class=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;Stylish text.&amp;lt;/div&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**** Given these variables and values... ****************

let classList = ['main', 'required', 'modern'].join(' ');

***** The code above will render... ***********************

&amp;lt;div class="main required modern"&amp;gt;Stylish text.&amp;lt;/div&amp;gt;
***********************************************************/&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When an attribute behaves like a boolean (it is present or not) we denote it with the name of the attribute preceded by &lt;code&gt;?&lt;/code&gt;. The value of the expression must be boolean, if it is &lt;code&gt;true&lt;/code&gt; &lt;code&gt;lit-html&lt;/code&gt; puts the attribute and if it is &lt;code&gt;false&lt;/code&gt; it removes it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Attribute binding (boolean)&lt;/span&gt;

&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;input type="submit" ?disabled=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;formWithErrors&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; value="Submit"&amp;gt;
     &amp;lt;span ?hidden=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;formWithErrors&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;Form has errors!&amp;lt;/span&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="cm"&gt;/**** Given these variables and values... *****************

let formWithErrors = true;

***** The code above will render... ***********************

&amp;lt;input type="submit" disabled value="Submit"&amp;gt;`;
&amp;lt;span&amp;gt;Form has errors!&amp;lt;/span&amp;gt;`
***********************************************************/&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Property&lt;/strong&gt;: An expression can also be binded to a JavaScript node's property. We write the property name with a &lt;code&gt;.&lt;/code&gt; at the beginning. In that case, the type of expression must match the type of the property (it could be any type even a complex object).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Property binding&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;custom-list .items=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; id="user-list"&amp;gt;&amp;lt;/custom-list&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**** Given these variables and values... ****************

const users = ['Diego', 'Ana', 'Laura', 'Piero'];
const customList = document.getElementById('user-list');
console.log(customList.items);

***** The code above will show in console *****************

 ["Diego", "Ana", "Laura", "Piero"]

***********************************************************/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Event&lt;/strong&gt;: An expression can be the handler of an event. For this we write the event name preceded by &lt;code&gt;@&lt;/code&gt; and in this case we have several alternatives for the binding.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Global handler function&lt;/em&gt;: the expression resolves to a global function that will handle the event.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Event binding to a global handler function&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;button @click=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;Click Me!&amp;lt;/button&amp;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;em&gt;Inline function&lt;/em&gt;: the expression resolves to an inline function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;button @click=&lt;/span&gt;&lt;span class="p"&gt;${()&lt;/span&gt;&lt;span class="o"&gt;=&amp;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;clicked&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;Click Me!&amp;lt;/button&amp;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;em&gt;Instance function&lt;/em&gt;: the expression resolves to a function that belongs to your object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;button @click=&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;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;Click Me!&amp;lt;/button&amp;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;em&gt;Event listener object&lt;/em&gt;: the expression returns an object that &lt;em&gt;must have&lt;/em&gt; a function named &lt;code&gt;clickHandler&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;button @click=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;clickHandler&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;Click Me!&amp;lt;/button&amp;gt;`&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;clickHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;handleEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;clicked!&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="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HTML node element&lt;/strong&gt;: the expression can return a DOM node.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;h1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Chapter 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;p&amp;gt;Once upon a time...&amp;lt;/p&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/***** The code above will render... **********************

&amp;lt;h1&amp;gt;Chapter 1&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;Once upon a time...&amp;lt;/p&amp;gt;
***********************************************************/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TemplateResult&lt;/strong&gt;: the expression can be another &lt;code&gt;TemplateResult&lt;/code&gt; object. This makes it possible to have composition of nested templates.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;h1&amp;gt;Chapter 1&amp;lt;/h1&amp;gt;`&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;article&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;article&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;p&amp;gt;Once upon a time...&amp;lt;/p&amp;gt;&amp;lt;/article&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/***** The code above will render... **********************

&amp;lt;article&amp;gt;
  &amp;lt;h1&amp;gt;Chapter 1&amp;lt;/h1&amp;gt;
  &amp;lt;p&amp;gt;Once upon a time...&amp;lt;/p&amp;gt;
&amp;lt;/article&amp;gt;
***********************************************************/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Iterable of &lt;code&gt;TemplateResult&lt;/code&gt; objects&lt;/strong&gt;: expressions that returns an array or iterables of &lt;code&gt;TemplateResult&lt;/code&gt; objects.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&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;listItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;li&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/li&amp;gt;`&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;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;ul&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;listItems&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/ul&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/***** The code above will render... **********************

&amp;lt;ul&amp;gt;
 &amp;lt;li&amp;gt;2&amp;lt;/li&amp;gt;
 &amp;lt;li&amp;gt;4&amp;lt;/li&amp;gt;
 &amp;lt;li&amp;gt;6&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
***********************************************************/&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Promise&lt;/strong&gt;: the expression can return a promise that must be resolved returning a valid binding value.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&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;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/***********************************************************
Let's say that after some seconds the fetch operation 
resolves with a the string 'some text...'

Until the promise is resolved, the code above will render
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt; 

Once the promise is resolved, it will render...
&amp;lt;p&amp;gt;some text...&amp;lt;/p&amp;gt;

***********************************************************/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Composition
&lt;/h3&gt;

&lt;p&gt;One consequence of having bindings to expressions that return &lt;code&gt;TemplateResult&lt;/code&gt; objects is that by composition we can create templates using other templates. The composition allows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a complex template using simpler templates.&lt;/li&gt;
&lt;li&gt;Refactor a complex template by diving it into simpler templates.&lt;/li&gt;
&lt;li&gt;Reuse of templates (the use of JavaScript modules makes reuse much easier, for example, a module of common templates, partial templates, etc.)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
    &amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;h1&amp;gt;
    &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtitle&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;h2&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtitle&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;h2&amp;gt;`&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="s2"&gt;`&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;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;makeParagraph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;`&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;composedTemplate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
    &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conditionals
&lt;/h3&gt;

&lt;p&gt;A template can have parts that are only visible if a condition is met, or it could have parts that are represented in different ways depending on one or more conditions. These behaviors can be expressed using conditional expressions such as the ternary operator &lt;code&gt;?&lt;/code&gt; or conditional structures such as the &lt;code&gt;if&lt;/code&gt; or &lt;code&gt;switch-case&lt;/code&gt; statements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// using ternary operator&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
    &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt;
        &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;img src=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;&amp;lt;/img&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// using if&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&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="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;img src=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;&amp;lt;/img&amp;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;span class="c1"&gt;// using switch-case&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;screenSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;s&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;img src="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-small.png"&amp;gt;&amp;lt;/img&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;m&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;img src="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-medium.png"&amp;gt;&amp;lt;/img&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;l&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;img src="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-medium.png"&amp;gt;&amp;lt;/img&amp;gt;
                    &amp;lt;img src="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.png"&amp;gt;&amp;lt;/img&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/p&amp;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;
  
  
  Iterations
&lt;/h3&gt;

&lt;p&gt;It is very common for a part of a template to be repeated with different values. Think of a list, where the part that paints each item is always the same but with different values. For these cases we have already seen that it is possible to make a binding to expressions that return iterables from &lt;code&gt;TemplateResult&lt;/code&gt; objects. This is the way we can repeat parts or blocks in a template.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;weekDays&lt;/span&gt; &lt;span class="o"&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;Monday&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;Tuesday&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;Wednesday&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;Thursday&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;Friday&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;Staurday&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;Sunday&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// loops with arrays&lt;/span&gt;
&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;ul&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;weekDays&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;li&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/li&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/ul&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// loop statement (better if DOM node update is cheap)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;itemTemplates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="k"&gt;for &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;day&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;weekDays&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;itemTemplates&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="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;li&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/li&amp;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;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;ul&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;itemTemplates&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/ul&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/*************************************
* We'll see the use of directives 
* in a future post !!
*************************************/&lt;/span&gt;
&lt;span class="c1"&gt;// repeat directive (better if moving DOM node is cheap)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;weekDays&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="cm"&gt;/*id*/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;li&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/li&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ul&amp;gt;`&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As we have seen, a template is pure JavaScript code so any expression and valid structure of the language can be used inside the template. There are so many ways to define a template that is only limited by the preferences or styles of each developer. The result is that the templates turn out to be tremendously expressive.&lt;/p&gt;

</description>
      <category>lit</category>
      <category>litelement</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>LitElement series: I need your help!</title>
      <dc:creator>Julio Castillo Anselmi</dc:creator>
      <pubDate>Mon, 17 Jun 2019 20:32:25 +0000</pubDate>
      <link>https://dev.to/julcasans/litelement-series-i-need-your-help-1lij</link>
      <guid>https://dev.to/julcasans/litelement-series-i-need-your-help-1lij</guid>
      <description>&lt;p&gt;📣Hi Dev people!&lt;/p&gt;

&lt;p&gt;This is the first time I make a series of posts and I have doubts on how to face it. Do I write detailed articles step by step explaining everything or is it better to explain briefly the basics but focusing on complex topics and things that are not obvious and aren't in the official documentation? Do I write for newbies or for those already initiated?&lt;/p&gt;

&lt;p&gt;The posts for &lt;em&gt;beginners&lt;/em&gt; are longer and can be boring for those who already have some experience, but they explain all the details and do not take anything for granted.&lt;br&gt;
On the other hand, posts with an &lt;em&gt;intermediate&lt;/em&gt; level are shorter and go straight to the point, but they can be more difficult to understand for those who are starting to develop. They would rely less on words, and more on code samples with comments. They are easy to use as a reference.&lt;/p&gt;

&lt;p&gt;As these posts have to be useful and of interest to &lt;strong&gt;you&lt;/strong&gt; I ask you: &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Girls and guys&lt;/em&gt;, what do you prefer???&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Posts for beginners developers&lt;/li&gt;
&lt;li&gt;Posts for experienced developers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this time, the second post for the &lt;code&gt;LitElement&lt;/code&gt; series goes in two flavours. Please 🙏 read them and tell me your opinion!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/julcasans/lit-html-templates-from-zero-to-hero-for-beginners-3eje"&gt;lit-html templates from zero to hero for beginners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/julcasans/lit-html-templates-from-zero-to-hero-2afm"&gt;lit-html templates from zero to hero&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thank you!&lt;/p&gt;

</description>
      <category>lit</category>
      <category>litelement</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>A gentle introduction to lit-html</title>
      <dc:creator>Julio Castillo Anselmi</dc:creator>
      <pubDate>Tue, 04 Jun 2019 18:12:48 +0000</pubDate>
      <link>https://dev.to/julcasans/a-gentle-introduction-to-lit-html-3d74</link>
      <guid>https://dev.to/julcasans/a-gentle-introduction-to-lit-html-3d74</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;📣 &lt;strong&gt;UPDATE!&lt;/strong&gt; 📣&lt;br&gt;
&lt;em&gt;Now lit-html and LitElement are unified under &lt;a href="https://lit.dev/"&gt;Lit&lt;/a&gt;.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;I'm writing new posts about &lt;strong&gt;Lit&lt;/strong&gt;, meanwhile you can:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;read this post because the principles are the same&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;upgrade your code with this &lt;a href="https://lit.dev/docs/releases/upgrade/"&gt;guide&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;visit &lt;em&gt;Lit&lt;/em&gt; site to know what's new&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;You can also use &lt;a href="https://lit.dev/docs/libraries/standalone-templates/"&gt;lit-html standalone&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hello! I start my blog with a series of &lt;code&gt;LitElement&lt;/code&gt; entries. I'll start with the most basic concepts and then I'll go deeper into the details of the use of this library. As &lt;code&gt;LitElement&lt;/code&gt; is based on &lt;code&gt;lit-html&lt;/code&gt; the first step will be the study of &lt;code&gt;lit-html&lt;/code&gt;. I hope you like it and find it useful.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lit-html&lt;/code&gt; is an HTML templating library made by the Polymer team. This library stands out for being simple, very small, extremely efficient in terms of speed and use of resources, and all this is because it is based on web standards.&lt;/p&gt;

&lt;p&gt;A very important point to note is that &lt;code&gt;lit-html&lt;/code&gt; doesn't define any component model and therefore can be used in any project with other frameworks or libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what is a template?
&lt;/h2&gt;

&lt;p&gt;Think of a payment receipt, it's a pice of paper that has written words and spaces to fill in. It has a text part that is always the same and other parts that can vary. It could be something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Date: ___/___/___
Received from ___________, the amount of $__________
for _____________________________________________
Received by: __________________
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This template can be printed and used many times filling in the blanks with the data of each payment.&lt;/p&gt;

&lt;h2&gt;
  
  
  And what is an HTML template?
&lt;/h2&gt;

&lt;p&gt;Think of a piece of HTML code that has some parts to fill in, the content of those parts can change but the rest remains always the same, so the HTML code has static parts and dynamic parts (the gaps to fill in).&lt;/p&gt;

&lt;p&gt;If the above receipt template had been written using HTML it could be:&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&amp;gt;&lt;/span&gt;Date: &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt; ______&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Received from &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt; ______ &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;, 
     the amount of &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt; $ ______ &lt;span class="nt"&gt;&amp;lt;/span&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;p&amp;gt;&lt;/span&gt; for &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt; _______ &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt; Received by: &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt; _______ &lt;span class="nt"&gt;&amp;lt;/span&amp;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;&lt;code&gt;lit-html&lt;/code&gt; lets you define an HTML template like the one above so that it can be rendered and reused with different values in the dynamic parts. This is not something new, there are other libraries like MoustacheJS or HandlebarJS that do the same, but &lt;code&gt;lit-html&lt;/code&gt; is special because it does it in a very, very efficient way. Why so efficient? Well, the usual approach is to parse the template and then render the HTML in a DOM node  with the new values in the changing parts. Every time the dynamic parts change, a parsing and rendering process is needed. The cost of re-rendering the DOM is high because it replaces the old node with the new node. &lt;code&gt;lit-html&lt;/code&gt; is efficient because it doesn't parse the template and it only renders the HTML in the DOM once, just the first time. It also remembers where the dynamic parts are so that when a value of these parts changes &lt;code&gt;lit-html&lt;/code&gt; just has to directly access that part and update the value in the DOM (normally it will be just text content, although it could also be a node).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lit-html&lt;/code&gt; is extremely efficient because it uses features of the web platform that are implemented natively in browsers. These characteristics are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tagged template literals of JavaScript.&lt;/li&gt;
&lt;li&gt;HTML template tag.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The use of these features makes the library small and fast because it doesn't need to implement the parsing of the string templates. It's done by JavaScript natively.&lt;/p&gt;

&lt;p&gt;The creation of the DOM represented by the template is also efficient, since it does so through the &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tag, cloning its content.&lt;br&gt;
Therefore, using what the platform offers, &lt;code&gt;lit-html&lt;/code&gt; doesn't have to resort to the use of ad-hoc languages like JSX that requires extra processing, nor create complex solutions like a virtual DOM.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to define a template?
&lt;/h2&gt;

&lt;p&gt;Too many words so far, let's see how a template is defined in &lt;code&gt;lit-html&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
  &amp;lt;div&amp;gt;
    &amp;lt;p&amp;gt;Date: &amp;lt;span&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;Received from &amp;lt;span&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 
    &amp;lt;/span&amp;gt;, the amount of &amp;lt;span&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/span&amp;gt; &amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt; for &amp;lt;span&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concept&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt; Received by: &amp;lt;span&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have a template literal tagged with a function called &lt;code&gt;html&lt;/code&gt;. This is one of the two functions provided by &lt;code&gt;lit-html&lt;/code&gt;.&lt;br&gt;
As I said before, &lt;code&gt;lit-html&lt;/code&gt; uses tagged template literals to define a template. These strings contain normal HTML code, there is nothing special, except for the tag function and the marks with &lt;code&gt;${}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Enclosed in &lt;code&gt;${}&lt;/code&gt; are JavaScript expressions that when interpolated are replaced by the results of evaluating them. Also, when JavaScript finds a tagged template literal it processes the string (kind of parsing task) and pass it to the tag function. As you can see, it's all pure JavaScript's work, there's no need for anything else (I mean, not like JSX).&lt;/p&gt;

&lt;p&gt;That's what a template in &lt;code&gt;lit-html&lt;/code&gt; looks like. To make it useful we can define a function that takes the data that will be applied inside the template literal and it will return a &lt;code&gt;ResultTemplate&lt;/code&gt; object (it is what the &lt;code&gt;html&lt;/code&gt; tag function produces but we don't need to go into detail now, I'll talk about it in a future post).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;receiptTemplate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
&amp;lt;div&amp;gt;
  &amp;lt;p&amp;gt;Date: &amp;lt;span&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;Received from &amp;lt;span&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;surname&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 
  &amp;lt;/span&amp;gt;, the amount of &amp;lt;span&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/span&amp;gt; &amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt; for &amp;lt;span&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concept&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt; Received by: &amp;lt;span&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have the template definition we can use it many times with different values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;receiptTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;receiptTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;otherData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What about rendering the template?
&lt;/h2&gt;

&lt;p&gt;We have seen how to define a template, now we'll see how to render it. This is the easiest part. For this we'll use the other function provided by &lt;code&gt;lit-html&lt;/code&gt;: the &lt;code&gt;render&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;render&lt;/code&gt; requires two mandatory arguments: the first is the &lt;code&gt;TemplateResult&lt;/code&gt; object to render and the second is the DOM node where the template will be placed. The third argument is optional and is an object that contains additional options (for now you do not have to know this).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;templateResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;receiptTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;templateResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mainContent&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;
  
  
  Recap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;lit-html&lt;/code&gt; is a simple, modern, safe, small and fast HTML templating library for JavaScript.&lt;/li&gt;
&lt;li&gt;It can be used in any project.&lt;/li&gt;
&lt;li&gt;It's based on web standards.&lt;/li&gt;
&lt;li&gt;It's framework agnostic.&lt;/li&gt;
&lt;li&gt;It provides two functions: &lt;code&gt;html&lt;/code&gt; and &lt;code&gt;render&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;html&lt;/code&gt; is used as a tag in front of the template literal that defines the HTML template.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;html&lt;/code&gt; returns a &lt;code&gt;TemplateResult&lt;/code&gt; object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;render&lt;/code&gt; is the function used to render the template in the DOM.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;render&lt;/code&gt; receives a &lt;code&gt;TemplateResult&lt;/code&gt; object and a node where to place the template.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is all the basic, minimum and elementary you should know to use this modern library. In the next post I will show you how to install &lt;code&gt;lit-html&lt;/code&gt; and explain in detail how to write complex templates. Until next time!&lt;/p&gt;

</description>
      <category>lit</category>
      <category>litelement</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
