Button doesn't work only on chrome

I have a button that doesn't work on chrome , but if I run same command on console , it works. In firefox is ok. What should be the problem ?

I have a button that doesn't work on chrome , but if I run same command on console , it works. In firefox is ok. What should be the problem ?



Render HTML with Vanilla JavaScript and lit-html

Render HTML with Vanilla JavaScript and lit-html

Sometimes you need to render HTML elements on a web page. And like Goldilocks' search for "just right", you have to try a few techniques before you find the right one. Using a framework may be too hard. Using pure HTML and the DOM API may be too soft. What you need is something in the middle that is just right. Is lit-html "just right"? Let's find out.

Sometimes you need to render HTML elements on a web page. And like Goldilocks' search for "just right", you have to try a few techniques before you find the right one. Using a framework may be too hard. Using pure HTML and the DOM API may be too soft. What you need is something in the middle that is just right. Is lit-html "just right"? Let's find out.

First, I'll show how this all works. Then at the end of this article, I'll explain everything you need to get started with lit-html to try this for yourself.

When you're done, you can push your HTML app with lit-html to the cloud to see it in all of its glory! I included a link to a free Azure trial, so you can try it yourself.

Resources:

The Sample App

Here is the app I'll demonstrate in this article. It fetches a list of heroes and renders them when you click the button. It also renders a progress indicator while it is fetching.

What's the Value of lit-html

When you focus on rendering content, and nothing else, lit-html is a good fit. It works closely with the DOM to render content, and refresh it in an optimal manner. The docs can provide you with more details, but the basic code for lit-html looks like this.

// Credit: As seen in official docs https://lit-html.polymer-project.org/guide/getting-started

// Import lit-html
import { html, render } from 'lit-html';

// Define a template
const myTemplate = name =>
  html`
    <p>Hello ${name}</p>
  `;

// Render the template to the document
render(myTemplate('World'), document.body);

You import lit-html, define a template, then render it to the DOM. That's it!

Rendering HTML

A progress bar is fairly basic. There is some HTML, and we show it when needed and hide it when it is not required. While we could use a template, or innerHTML, or the DOM API for this, let's see what this would look like with lit-html.

First, we get a reference to the element in the DOM where the progress bar will appear.

Then we define the template. This code looks and feels like JSX (or TSX). The advantage here is that you can write the HTML. You wrap the HTML in a template string (notice the back-tick character is used and not a single quote). Template strings allow you to span lines and insert variables where needed (we'll see this soon). The magic that makes this work is the html tag that precedes the template string. The html tag is what tells lit-html that you are about to define a template.

Next, we compile the template and pass those results to lit-html's render function, which places the results in the DOM. Finally, we hide or show the progress bar as needed.

function showProgress(show = true) {
  const container = document.getElementById('progress-placeholder');

  const template: () => TemplateResult = () => html`
    <progress class="progress is-medium is-info" max="100"></progress>
  `;
  const result = template();
  render(result, container);

  container.style.display = show ? 'block' : 'none';
}

Now you can run this showProgress function any time you want to show the progress bar.

Note that when a template is re-rendered, the only part that is updated is the data that changed. If no data changed, nothing is updated.

Rendering HTML with Dynamic Values

The progress bar does not change each time it is rendered. You will have situations where you want your HTML to change. For example, you may have a message area on your web app that shows a styled message box with a title and a message. The title and message will change every time you show the message area. Now you have dynamic values.

The HTML is defined with a template string, so it is trivial to add a variable into it. Notice the code below adds a title and text into the template, using the ${data.title} and ${data.text} syntax, respectively.

Then the template is compiled and rendered were needed.

When this template is re-rendered, the only part that is updated is the data that changed. In this case, that's the title and text.

function showMessage(text: string, title = 'Info') {
  const template: (data: any) => TemplateResult = (data: Message) => html`
    <div id="message-box" class="message is-info">
      <h3 class="message-header">${data.title}</h3>
      <p class="message-body">${data.text}</p>
    </div>
  `;

  const el = document.getElementById('message-placeholder');
  const result = template({ title, text });
  render(result, el);

  el.style.visibility = !!text ? 'visible' : 'hidden';
}

Rendering a List

Things get a little more real when we render a list. Let's think about that for a moment. A list requires that we have a plan if there is data and a backup plan if there is no data. A list requires that we render the same thing for each row, and we don't know how many rows we have. A list requires that we pass different values for each row, too. Then we have to take the rows and wrap them in a container such as a <ul> or a <table>.

So there is a little more logic here, regardless of whether we use lit-html or any other technique. Let's explore how the replaceHeroList function renders the rows using lit-html.

function replaceHeroList(heroes?: Hero[]) {
 const heroPlaceholder = document.querySelector('.hero-list');

 // Define the template
 let template: () => TemplateResult;

 if (heroes && heroes.length) {
   // Create the template for every hero row
   template = createList();
 } else {
   // Create the template with a simple "not found" message
   template = () =>
     html`
       <p>heroes not found</p>
     `;
 }

 // Compile the template
 const result = template();

 // Render the template
 render(result, heroPlaceholder);

Notice that when there are heroes, we call the createList function. This function begins by creating an array of TemplateResult. So for every hero in the heroes array, we define a template that represents the <li> containing the HTML that displays that respective hero.

Then we create another template that contains the <ul> and embeds the array of hero templates. It's pretty cool that we can embed templates like this! Finally, we return it all and let the logic compile the templates and render them.

function createList() {
  // Create an array of the templates for each hero
  const templates: TemplateResult[] = heroes.map(hero => {
    return html`
      <li>
        <div class="card">
          <div class="card-content">
            <div class="content">
              <div class="name">${hero.name}</div>
              <div class="description">${hero.description}</div>
            </div>
          </div>
        </div>
      </li>
    `;
  });

  // Create a template that includes the hero templates
  const ulTemplate: () => TemplateResult = () =>
    html`
      <ul>
        ${templates}
      </ul>
    `;
  return ulTemplate;
}

Summary

When you want to render HTML, lit-html is a fast and light-weight option. Is it better than using templates and the DOM API? You'll have to decide what is best for you. But the real story here is that you have another great option to consider when determining the right tool for your job.

Prologue

You can also get editor help with your lit-html templates. Notice the image below shows the syntax highlighting for the HTML template!

Setup

You can install the lit-html package with npm.

npm install lit-html

Alternately you can load it directly from the unpkg.com CDN

import { html, render } from 'https://unpkg.com/lit-html?module';

You have a choice here. npm is my preference, but feel 100% free to use the CDN if that suits you.

TypeScript and lit-html

You only need to include the library for lit-html and you're done. But I like to use TypeScript, and I absolutely recommend enabling your tooling to work great with typeScript and lit-html.

Let me be very clear here - you do not need TypeScript. I choose to use it because it helps identify mistakes while I write code. If you don't want TypeScript, you can opt to use plain JavaScript.

Here are the steps to make TypeScript and lit-html light up together:

  1. Install TypeScript support for lit-html
  2. Configure your tsconfig.json file
  3. Install the VS Code extension for lit-html

Run this command to install the plugin and typescript, as development dependencies to your project.

npm install --save-dev typescript-lit-html-plugin typescript

Edit your tsconfig.json by adding the following to your compilerOptions section.

"compilerOptions": {
  "plugins": [
    {
      "name": "typescript-lit-html-plugin"
    }
  ]
}

Finally, install the VS Code extension for lit-html.

Now you get syntax highlighting for all of your lit-html templates!

Introduction Boolean in JavaScript and TypeScript

Introduction Boolean in JavaScript and TypeScript

Boolean values are supported by both JavaScript and TypeScript and stored as true/false values .This is because, while JavaScript coerces an object to its primitive type, the TypeScript type system does not. TypeScript treats it like an object type.

Boolean in JavaScript

boolean can take the values of true and false. Values from other types can be truthy or falsy, like undefined or null.

let b = true
if(b) console.log('logged')

b = false
if(b) console.log('not logged')

b = undefined
if(b) console.log('not logged')

b = null
if(b) console.log('not logged')

Values other than undefined, null or false considered falsy are "" (empty string), -0 and 0, as well as NaN.

To get the boolean value of any value, you can use the Boolean function:

Boolean(false) // false
Boolean(true) // true
Boolean("false") // true ❗️
Boolean("Hey folks") // true
Boolean({}) // true
Boolean([]) // true
Boolean(123.4) // true
Boolean(Symbol()) // true
Boolean(function() {}) // true
Boolean(undefined) // false
Boolean(null) // false
Boolean(NaN) // false
Boolean(0) // false
Boolean("") // false

Rule of thumb: All empty values evaluate to false. Empty object {} and empty array [] (which is an object itself) do have value as they are containers for other values.

The Boolean function is really good to filter empty values from collections:

const collection = [
  { name: 'Stefan Baumgartner', age: 37 },
  undefined,
  { name: 'D.', age: 36 },
  false
  { name: 'C.', age: 2},
  false
]

collection.filter(Boolean) // handy!

Together with Number – which converts all values into their number counterpart or NaN, this is a really cool way of getting to actual values quickly:

const x = ["1.23", 2137123, "wut", false, "lol", undefined, null]
  .map(Number)
  .filter(Boolean) // [1.23, 2137123] πŸ‘

Boolean exists as a constructor and has the same conversion rules as the Boolean function. However, with new Boolean(...) you create a wrapping object, making value comparisions truthy, but reference comparisions falsy:

const value = Boolean("Stefan") // true
const reference = new Boolean("Stefan") // [Boolean: true]

value == reference // true
value === reference // false

You get to the value via .valueOf():

value === reference.valueOf() // true

I have a REPL for you to check. The use of Boolean as a function is obviously great, but new Boolean has very limited use. If you know a practical use case, please let me know.

Boolean in TypeScript

boolean in TypeScript is a primitive type. Be sure to use the lower case version and don’t refer to
object instances from Boolean

const boolLiteral: boolean = false // πŸ‘
const boolObject: Boolean = false // πŸ‘Ž

It works, but it’s bad practice as we really rarely need new Boolean objects.

You can assign true, false and undefined and null to boolean in TypeScript without strict null checks.

const boolTrue: boolean = true // πŸ‘
const boolFalse: boolean = false // πŸ‘
const boolUndefined: boolean = undefined // πŸ‘
const boolNull: boolean = null // πŸ‘

With that, boolean is the only one we can express fully through union types:

type MyBoolean = true | false | null | undefined // same as boolean

const mybool: MyBoolean = true
const yourbool: boolean = false

When we enable the strictNullChecks compiler flag, the set of values reduces to true and false.

const boolTrue: boolean = true // πŸ‘
const boolFalse: boolean = false // πŸ‘
const boolUndefined: boolean = undefined // πŸ’₯
const boolNull: boolean = null // πŸ’₯

So our set reduces to two values in total.

type MyStrictBoolean = true | false

We can also get rid of null values with the NonNullable helper type:

type NonNullable<T> = T extends null | undefined
  ? never
  : T;

type MyStrictBoolean = NonNullable<MyBoolean> // true | false

The fact that boolean consists of a limited set of values only used in conditions, allows for interesting conditional types.

Think of an mutation in a datastore through a function. You set a flag in a function that updates e.g. the user id. You have to provide the user ID then:

type CheckUserId<Properties, AddUserId> = 
    AddUserId extends true 
    ? Properties & { userId: string }
    : Properties & { userId?: string }

Depending on the value of our generic AddUserId, we expect the property userId to be set or to be optional.

We can make this type more explicit by extending our generics from the types we expect

- type CheckUserId<Properties, AddUserId> = 
+ type CheckuserId<
+  Properties extends {},
+  AddUserId extends boolean
+ >
     AddUserId extends true 
     ? Properties & { userId: string }
     : Properties & { userId?: string }

In use, it might declare a function like this:

declare function mutate<P, A extends boolean = false>
  (props: CheckUserId<P, A>, addUserId?: A): void

Note that I even set a default value for A to make sure CheckUserId gives the correct info depending on addUserId to be set or not.

The function in action:

mutate({}) // πŸ‘
mutate({ data: 'Hello folks' }) // πŸ‘
mutate({ name: 'Stefan' }, false) // πŸ‘
mutate({ name: 'Stefan' }, true) // πŸ’₯ userId is missing
mutate({ name: 'Stefan', userId: 'asdf' }, true) // πŸ‘ userId is here

Handy if your code relies a lot on truthy and falsy values. As always, there’s playground for you.

Originally published at fettblog.eu on 10 September 2019

Understanding void in JavaScript and TypeScript

Understanding void in JavaScript and TypeScript

void exists in both JavaScript as an operator and in TypeScript as a primitive type. And in both worlds void works a little bit different than most people are used to.

If you come from traditional, strongly typed languages you might be familiar with the concept of void: A type telling you that functions and methods return nothing when called.

void in JavaScript

void in JavaScript is an operator which evaluates the expression next to it. No matter which expression is evaluated, void always returns undefined.

let i = void 2; // i === undefined

Why would we need something like this? First, in earlier times, people were able to override undefined and giving it an actual value. void always returned the real undefined.

Second, it’s a nice way to call immediately invoked functions:

void function() {
  console.log('What')
}()

All without polluting the global namespace:

void function aRecursion(i) {
  if(i > 0) {
    console.log(i--)
    aRecursion(i)
  }
}(3)

console.log(typeof aRecursion) // undefined

Since void always returns undefined, and void always evaluates the expression next to it, you have a very terse way of returning from a function without returning a value, but still calling a callback for example:

// returning something else than undefined would crash the app
function middleware(nextCallback) {
  if(conditionApplies()) {
    return void nextCallback();
  }
}

Which brings me to the most important use case of void: It’s a security gate for your app. When your function is always supposed to return undefined, you can make sure that this is always the case.

button.onclick = () => void doSomething();

void in TypeScript

void in TypeScript is a subtype of undefined. Functions in JavaScript always return something. Either it’s a value, or undefined

function iHaveNoReturnValue(i) {
  console.log(i)
} // returns undefined

Since functions without a return value always return undefined, and void always returns undefined in JavaScript, void in TypeScript is a proper type for telling developers that this function returns undefined:

declare function iHaveNoReturnValue(i: number): void

void as type can also be used for parameters and all other declarations. The only value that can be passed is undefined:

declare function iTakeNoParameters(x: void): void

iTakeNoParameters() // πŸ‘
iTakeNoParameters(undefined) // πŸ‘
iTakeNoParameters(void 2) // πŸ‘

So void and undefined are pretty much the same. There’s one little difference though, and this difference is significant: void as a return type can be substituted with different types, to allow for advanced callback patterns:

function doSomething(callback: () => void) {
  let c = callback() // at this position, callback always returns undefined
  //c is also of type undefiend
}

// this function returns a number
function aNumberCallback(): number {
  return 2;
}

// works πŸ‘ type safety is ensured in doSometing
doSomething(aNumberCallback) 

This is desired behaviour and often used in JavaScript applications. Read more on this pattern called substitutability in my other articles.

If you want to make sure to pass functions who only return undefined (as in β€œnothing”), be sure to adapt your callback method signature:

- function doSomething(callback: () => void) {
+ function doSomething(callback: () => undefined) { /* ... */ }

function aNumberCallback(): number { return 2; }

// πŸ’₯ types don't match
doSomething(aNumberCallback)

You’ll propably be good with void most of the time.

Originally published at fettblog.eu on 06 September 2019