Monthly Archives: November 2017

What is ReasonML?

By Dr. Axel Rauschmayer

This is how ReasonML fits into the OCaml ecosystem.

ReasonML is a new object-functional programming language created at Facebook. In essence, it is a new C-like syntax for the programming language OCaml. The new syntax is intended to make interoperation with JavaScript and adoption by JavaScript programmers easier. Additionally, it removes idiosyncrasies of OCaml’s syntax. ReasonML also supports JSX (the syntax for HTML templates inside JavaScript used by Facebook’s React framework). Due to ReasonML being based on OCaml, many people use the two names interchangeably.

Additionally, the ReasonML team aims to improve the OCaml ecosystem:

  • Better tooling (testing, documentation, editor support, etc.).
  • Better interoperation with JavaScript. The ReasonML-to-JavaScript compiler is already very fast and produces relatively readable code.
  • Better standard library (there is a fair amount of competition in this space in OCaml, without a clear winner). Here, the goal is also to use camel-cased names (StringUtilities, createResource). OCaml uses snake-casing for lowercase names (create_resource) and camel-casing for uppercase names (StringUtilities).

Benefits of OCaml:

  • It is an established language (created in 1996) that has proven itself in many projects. Facebook itself is using it in several projects (e.g. Flow).
  • Its core is a functional programming language (with a full-featured type system). But it also supports object-orientation and mutable state.
  • It can be compiled to either bytecode, fast native code or JavaScript.
  • Compilation to JavaScript is fast. Quoting the blog post “Messenger.com Now 50% Converted to Reason”:

    Full rebuild of the Reason part of the codebase is ~2s (a few hundreds of files), incremental build (the norm) is <100ms on average. The BuckleScript author estimates that the build system should scale to a few hundred thousands files in the current condition.

Conclusion #

In the end, ReasonML feels much like what you’d get if you cleaned up JavaScript and turned it into a statically typed functional programming language. I’m ambivalent about JSX in ReasonML – it has pros and cons. I’m glad that ReasonML doesn’t reinvent the wheel and is strictly based on the established OCaml.

OCaml’s pragmatism means that you don’t get some of the more fancy functional features (that, e.g., Haskell has), but it also leads to fast compilation, efficient code and decent error messages.

Source:: 2ality

Getting Started with CSS Grid Layout

By Hammad Ahmed

Grid Lines in a Tic-Tac-Toe Boards

Introduction

CSS Grid Layout allows us to construct custom grids with more flexibility and control than ever before. Grid Layout gives us the ability to divide a webpage into rows and columns with simple properties. It also allows us to position and size each element inside the grid using CSS only, without any change to the HTML.

Defining a Grid

With this module, comes a new value for the display property: grid. When you set the display property of any element to grid, it becomes the grid container and all it’s child elements become grid items.

For the sake of creating a 3×3 layout, let’s create the board of a Tic-Tac-Toe game. First, we will write some HTML:

<div class="game-board">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>

As you can see, the .game-board div is the grid container and .box divs are grid items. Now we will position them 3 in a row with Grid Layout.

.game-board 
{
    display: grid;
    grid-template-rows: 200px 200px 200px;
    grid-template-columns: 200px 200px 200px;
}

Here, I’ve used two other properties as well. The grid-template-rows property allows us to specify how many rows and of what sizes there should be in the grid. I think you can guess what the other property does.

The grid-template-columns property allows us to specify how many columns and of what sizes there should be in the grid. You can specify the size in any unit including pixels, percentages and another unit fr, which we are going to learn next.

The fr Unit (fraction)

fr is a new unit defined for Grid Layout. It helps you get rid of calculating percentages and divides the space into a fraction of the available space.

For example, if you place this rule:grid-template-rows: 2fr 3fr, in your grid element’s block, then your grid container will, firstly, be divided into 2 rows. Then the fractional parts will be added together which, here, sum up to 5.

We’ll have two rows: The first row taking up 2/5ths of the vertical space. The second row taking up 3/5ths of the vertical space.

Back to our Tic-Tac-Toe example, let’s use fr instead px. What we want is, that, there should be 3 rows and 3 columns. So, we just have to replace the 3 200px with 3 1fr like this:

.game-board 
{
    display: grid;
    grid-template-rows: 1fr 1fr 1fr;
    grid-template-columns: 1fr 1fr 1fr;
}

The repeat() Function

In some cases, we have a lot of columns and rows. Specifying each one in the grid-template properties can get tedious. Luckily there is a repeat function which like any loop repeats a certain value a given number of times. It takes two arguments. First one is the number of iterations and second is the value to be repeated. Let’s rewrite our previous example using the repeat function.

.game-board
{
    display: grid;
    grid-template-rows: repeat(3, 1fr);
    grid-template-columns: repeat(3, 1fr);
}

The above would create the same as:

.game-board 
{
    display: grid;
    grid-template-rows: 1fr 1fr 1fr;
    grid-template-columns: 1fr 1fr 1fr;
}

grid-template property

There is a shorthand property for specifying both the grid-template-rows and grid-template-columns, that is the grid-template property. Here is it’s syntax:

grid-template: ro ws / co lu mns;

Using this shorthand, our previous example looks pretty neat.

.game-board
{
    display: grid;
    grid-template: repeat(3, 1fr) / repeat(3, 1fr);
}

See, just using 2 lines of code you can make a 3×3 grid with Grid Layout.

With some added paint and polish, the above example looks like this:

Grid Line Number, Cell & Tracks

A grid line is a line that exists on each side of a column and a row. One set of lines divide the space vertically into columns and the other set of lines divide the space horizontally into rows. This means that in our previous example, there were four vertical lines and four horizontal lines containing the rows and columns between them.

Grid Lines become quite useful while moving grid items from one place to another in the grid.

A grid track is the space between two lines. A grid track can either be a row or a column.

A grid cell, much like a table cell, is the space between two vertical lines and two horizontal lines. It is the smallest unit of the grid.

Positioning Grid Items

I’ve taken the grid of the previous example and labeled each cell, not with a X or O, but with a number from 1 to 9. Here’s how it looks:

Numbered Grid

Let’s say I want to move the sixth box to the place of the second box. Without CSS Grids, this would have been an almost impossible task, at least for me, without changing the HTML. But with this new module, changing position of items in a grid is a breeze. To move the sixth box to the place of the second box, we must know exactly where the second box is sitting. And we can easily find this with the help of grid line numbers. The second box is sitting after line 2 and before line 3 on the vertical axis and after line 1 and before line 2 on the horizontal axis. Now we can assign these grid line numbers to the sixth box using the following properties:

  • grid-column-start
  • grid-column-end
  • grid-row-start
  • grid-row-end

The first two properties correspond to the vertical lines’ start and end. And the last two properties refer to the horizontal lines’ start and end. Let’s assign the correct line numbers to move the sixth box.

.box:nth-child(6)
{
    grid-row-start: 1;
    grid-row-end: 2;
    grid-column-start: 2;
    grid-column-end: 3;
}

There are also two shorthand properties for setting the start and end lines of row and column in one line.

.box:nth-child(6)
{
    grid-row: 1 / 2;
    grid-column: 2 / 3;
}

Additionally, there is a grid-area property which is the shorthand property of all four above mentioned properties. It takes values in the following order:

grid-area: <row-start> / <column-start> / <row-end> / <column-end>;

Now, our example looks like this:

.box:nth-child(6)
{
    grid-area: 1 / 2 / 2 / 3;
}

The above line of code can also be further reduced. As you can see that the box only takes up one row and one column, so we only need to specify the starting lines of the row and column and not the end values.

.box:nth-child(6)
{
    grid-area: 1 / 2;
}

What if we wanted the sixth box to span the area of two boxes? This can easily be done by increasing the column-end value by 1.

.box:nth-child(6)
{
    grid-area: 1 / 2 / 2 / 4;
}

Double Column Span

You can also use the span keyword with the number of tracks instead of specifying the ending line number for grid-row-end and grid-column-end. In this case, the sixth box is spanning 2 columns and 1 row.

.box:nth-child(6)
{
    grid-area: 1 / 2 / 2 / span 2;
}

Named Grid Areas

The grid-area property can also be used to name parts of a grid which we can then position with the grid-template-areas property. Let’s create a simple bread-and-butter layout with a header on top, nav, main and aside in the middle, and a footer below them. Here’s the HTML required for this:

<div class="container">
  <header></header>
  <nav></nav>
  <main></main>
  <aside></aside>
  <footer></footer>
</div>

We need to name each area using the grid-area property like this:

header
{
  grid-area: header;
  background-color: #9b59b6;
}

nav
{
  grid-area: nav;
  background-color: #3498db;
}

main
{
  grid-area: main;
  background-color: #2ecc71;
}

aside
{
  grid-area: aside;
  background-color: #f1c40f;
}

footer
{
  grid-area: footer;
  background-color: #1abc9c;
}

Now we will use the grid-template-areas property to specify which rows and columns each grid area has to span across. Here’s how we do it:

.container
{
      display: grid;
      grid-template-rows: 1fr 5fr 1fr;
      grid-template-columns: 2fr 5fr 3fr;
      grid-template-areas:
        "header  header  header"
        "nav     main    aside"
        "footer  footer  footer";
      grid-gap: .75em;
}

Notice that the header and footer words are repeated three times. This states that both the header and the footer span across the width of 3 rows. You can write all of it in one line but it’s nice and clean to write each row on a separate line. You can see that I’ve used a new property grid-gap here. All it does is simply add a gutter between two grid areas. You can also specify different gutter values for row and column using grid-row-gap and grid-column-gap.

Here’s the CodePen for this example:

Browser Support

At the time of this writing, there is good browser support for CSS Grid Layout. According to caniuse.com, all major browsers support CSS Grid Layout except Internet Explorer 11 which has partial support with -ms- prefix and Opera Mini having no support at all.

Conclusion

CSS Grid Layout allows us to make layouts faster and with more control and ease. In this tutorial, we learned how to define layouts with CSS Grids, the fr unit, the repeat function and some grid-specific glossary. We also learned how to position grid items inside a grid container using grid-lines and grid-named-areas. But that’s just the start. In the next tutorial, we will dive deep into CSS Grids.

Til then, Happy Coding!

Source:: scotch.io

Automate Tasks by Creating Custom Artisan command in Laravel

By Olususi Kayode Oluyemi

Out of the box, Laravel comes installed with a lot of helpful commands available to use in an application. But as your application grows, you might find it time wasting, performing some tasks like populating database with user’s data or products.

At this point, automating those tasks will go a long way to help you get data into your database seamlessly and facilitate the rapid completion of your web application.

Some of the default Artisan commands for Laravel include php artisan serve, php artisan make:controller, php artisan make:model and so on.

In this article, we will be creating an artisan command to populate database with product’s data. This tutorial will not only show you how to create a custom artisan command, but moreso to read data from a CSV file, parse and store it in our database using the command we are going to create.

Install Laravel

To get started with the custom artisan command, I want to assume that you already have Laravel installed, if not quickly do that with the following commands. As at the time of writing this tutorial, Laravel 5.5 is being used.

composer create-project --prefer-dist laravel/laravel command

The command above will create a Laravel project called command in your local directory. Feel free to change as preferred, if you wish too.

Generating Commands

Now that you have installed Laravel, let’s proceed to build our own custom commands as stated earlier.
To create a custom command, use the command below:

php artisan make:command productData

The intention is to create a custom command to populate the products table, hence the reason for the name productData. After successfully running this command, a new class will be created in the app/Console/Commands directory within your project.

Open app/Console/Commands/productData, you should have a similar content like the file below :

<?php
namespace AppConsoleCommands;
use IlluminateConsoleCommand;
class productData extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:name';
    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';
    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }
    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        //
    }
}

Command Structure

Now proceed to creating the actual command by editing the file we just created

<?php

namespace AppConsoleCommands;

use AppProduct;
use IlluminateConsoleCommand;

class productData extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'add:product';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Add products data to the database';

    public function __construct()
    {
        ...
    }

    public function handle()
    {
       //
    }
}

Here, we have changed the name and signature of the command and also added the command description. This will be used when displaying the command on the list screen.

Register Command

We are close, but unfortunately our newly created command will have no effect yet; as it does not exist, as far as Laravel is concerned. To change this, we will need to register the command by navigating to app/Console/kernel.php file and place the Command class we just created in the protected $commands array.

<?php

namespace AppConsole;

use IlluminateConsoleSchedulingSchedule;
use IlluminateFoundationConsoleKernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        CommandsproductData::class,
    ];

    protected function schedule(Schedule $schedule)
    {
       ...
    }

    protected function commands()
    {
       ...
    }
}

To check if the command has been registered, run the artisan command :

php artisan list

And that’s it, our command signature and description have been successfully registered as indicated above.

Congratulations!!! You just created your first custom Artisan command!

Migrating and Creating Table

In order to give our command life, we are going to create a model and migration file for Product, and then complete a function that will execute the console command we created.

Generate a model and migration file with this command:

php artisan make:model Product -m

This will generate two separate files app/Product and database/migrations/create_products_table. Add the contents below respectively:

## app/Product.php
...
class Product extends Model
{

    protected $table = "products";
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
      'name', 'description', 'quantity'
    ];
}

and

<?php
...
class CreateProductsTable extends Migration
{

    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('description');
            $table->string('quantity');
            $table->timestamps();
        });
    }

    public function down()
    {
        ...
    }
}

Database Set up

Open the .env file and add your database details

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=Your-database-name
DB_USERNAME=Your-database-username
DB_PASSWORD=Your-database-password

Now run to create tables

php artisan migrate

Execute Command

Once you execute the newly created command, the handle method within productData class will be called. So let’s edit that and place the required command logic in this method.

<?php
...
class productData extends Command
{

    protected $signature = 'add:product';

    protected $description = 'Add products data to the database';

    public function __construct()
    {
        ...
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $CSVFile = public_path('products.csv');
        if(!file_exists($CSVFile) || !is_readable($CSVFile))
            return false;

        $header = null;
        $data = array();

        if (($handle = fopen($CSVFile,'r')) !== false){
            while (($row = fgetcsv($handle, 1000, ',')) !==false){
                if (!$header)
                    $header = $row;
                else
                    $data[] = array_combine($header, $row);
            }
            fclose($handle);
        }

        $dataCount = count($data);
        for ($i = 0; $i < $dataCount; $i ++){
            Product::firstOrCreate($data[$i]);
        }
        echo "Products data added successfully"."n";
    }
}

You can find the sample CSV file used above here.

Its time to see our custom command at work.

Run

php artisan add:product

You should get a response stating Product data added successfully after running that command.

A quick look at what we now have in the database.

Conclusion

There is a lot more you can effortlessly achieve by creating a custom Artisan command. You can build on this and create more awesome commands to make development very easy for you when using Laravel.

As shown in this tutorial, you can also read data from a CSV file and store into your database with just a single command line. I hope this tutorial has been very helpful. If you have any question or thoughts that require clarifications, kindly drop a comment.

Source:: scotch.io

Custom Overlays with Angular's CDK - Part 2

overlay preview

In a previous post we have layed the foundation for our custom overlay. To recap, we wanted to build a Google Drive-like custom overlay that looks and feels much like the one built for MachineLabs. Let’s have a look at a preview:

In the first part of this series we learned how to use Angular’s CDK to create our very first custom overlay. On top of that we made it configurable, implemented a “handle” to control (e.g. close) an opened overlay and made it possible to share data with the overlay component.

In this post, we’ll pick up from where we left off and implement a few additional features that will take our overlay to the next level. More specifically, we’ll implement keyboard support, image preloading and add animations in order to make our overlay more engaging and provide better feedback. In the end, we’ll complete this post by adding a toolbar component to fully match Google Drive’s look and feel.

Let’s dive right into it!

Adding keyboard support

Adding keyboard support is easy. All we need to do is to use the @HostListener() decorator. This decorator is a function decorator that accepts an event name as an argument. Let’s use it inside our FilePreviewOverlayComponent to listen to keydown events on the HTML Document, so that we can close the overlay whenever the escape button was pressed.

Closing the dialog from within the overlay component is only possible because the FilePreviewOverlayRef is now available via the DI system. Remember that we created our own custom injector and defined custom injection tokens for the remote control and the data that we want to share with the component.

Let’s have a look at the code:

import { ..., HostListener } from '@angular/core';

// Keycode for ESCAPE
const ESCAPE = 27;

@Component({...})
export class FilePreviewOverlayComponent {
...
// Listen on keydown events on a document level
@HostListener('document:keydown', ['$event']) private handleKeydown(event: KeyboardEvent) {
  if (event.keyCode === ESCAPE) {
    this.dialogRef.close();
  }
}

constructor(public dialogRef: FilePreviewOverlayRef, ...) { }

Using the host listener we decorate a class method that is called on every keydown event. The function itself gets the KeyboardEvent that we can use to check whether it’s the escape key and only then call close() on the dialogRef.

That’s it already for adding keyboard support. Go ahead and try it out. Open a file preview and then press the escape button.

Preloading images

Instant app response is without any doubt the best, but there are cases when our apps won’t be able to deliver the content immediately, e.g. slow internet connection or even latency issues. In those cases it’s extremely important to provide users with feedback and indicate that progress is being made. It’s crucial to let the user know what is happening in contrast to keep them guessing. One of the most common forms of such feedback is a progress indicator. It reduces the user’s uncertainty, perception of time and offers a reason to wait.

Looking at our overlay, we are facing the exact same problems. When we click to preview an image, depending on the internet connection, the image is fetched by the browser and progressively rendered onto the screen. If the connection is really bad it may take a while. Also, it doesn’t really look that nice if we display image data as it is received, resulting in a top-down filling in of the image.

To solve this, we can use a progress indicator. The good thing is we don’t need to write one from scratch because Angular Material already provides a nice set of loading indicators, one of which is the . In order to use it, we need to add the MatProgressSpinnerModule from @angular/material to the imports of our application:

import { ..., MatProgressSpinnerModule } from '@angular/material';

@NgModule({
  imports: [
    ...,
    MatProgressSpinnerModule
  ],
  ...
})
export class AppModule { }

Note that the component is an alias for . As we can see, the progress-spinner supports different modes, determinate and indeterminate.

The difference is that determinate progress indicators are used to indicate how long an operation will take, whereas indeterminate indicators request that the user needs to wait while something finishes. The latter is used when it’s not necessary to indicate how long it will take or to convey a discrete progress. This is perfect for preloading images because we have no idea how long it may take to fetch the image.

Ok, now that we have added the respective module to our imports we can go ahead and update the template of the FilePreviewOverlayComponent as well as the component class:

@Component({
  template: `
    <div class="overlay-content">
      <div class="spinner-wrapper" *ngIf="loading">
        <mat-spinner></mat-spinner>
      </div>

      <img (load)="onLoad($event)" [style.opacity]="loading ? 0 : 1" [src]="image.url">
    </div>
  `,
  ...
})
export class FilePreviewOverlayComponent {

  loading = false;

  ...

  onLoad(event: Event) {
    this.loading = false;
  }
}

First off, we introduce a new property loading and initialize it with a meaningful value, e.g. false. This will show our spinner until the image is loaded. Also note that we are using a property binding to set the opacity of the element to 0 when it’s loading and 1 when it’s finished. If we didn’t do this, we’d still see the image being rendered or filled in from top to bottom. This is just a temporary solution that we will replace with a proper solution using Angular’s Animation DSL in just a moment. Last but not least, we define a success callback as a method on our class that is called when the image is loaded. The callback is hooked up in the template via an event binding. In this particular case we are listening for the load event and when fired, we call the onLoad() method.

One more thing to mention is that we needed to wrap the spinner in another element. The reason for this is that we want the spinner to be vertically and horizontally centered. To achieve this we would leverage the CSS transform property to apply a transformation to the spinner element. The problem is that the component is animated with CSS transforms meaning every transformation we set on the element is overridden. Therefore we use a container that wraps the spinner, so that we can savely apply transformation and center it on the screen.

Here’s the image preloading in action. To better demonstrate the loading, you can throttle your connection in the “Network” tab of Chrome’s DevTools.

Animating the overlay

With animations we aim to guide users between views so they feel comfortable using the site, draw focused-attention to some parts of our application, increase spacial awareness, indicate if data is being loaded, and probably the most important point – smoothly transition users between states.

The problem with our overlay is that it still pops right into our faces. The backdrop is already animated for us, but having an animation only for the backdrop is not enough. We also want to add a little bit of motion to the overlay component, so that it’s less surprising for the user.

If you are completely new to animations in Angular, please check out our post on the Foundation Concepts or have a look at our Web Animations Deep Dive with Angular.

Let’s start off by importing the BrowserAnimationsModule into our application’s NgModule like this:

import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
  imports: [
    ...,
    BrowserAnimationsModule
  ],
  ...
})
export class AppModule { }

With this in place, we can go ahead and define our animations with Angular’s Animation DSL and add it to the component via the animations metadata property in the @Component() decorator:

// Reusable animation timings
const ANIMATION_TIMINGS = '400ms cubic-bezier(0.25, 0.8, 0.25, 1)';

@Component({
  ...
  animations: [
    trigger('fade', [
      state('fadeOut', style({ opacity: 0 })),
      state('fadeIn', style({ opacity: 1 })),
      transition('* => fadeIn', animate(ANIMATION_TIMINGS))
    ]),
    trigger('slideContent', [
      state('void', style({ transform: 'translate3d(0, 25%, 0) scale(0.9)', opacity: 0 })),
      state('enter', style({ transform: 'none', opacity: 1 })),
      state('leave', style({ transform: 'translate3d(0, 25%, 0)', opacity: 0 })),
      transition('* => *', animate(ANIMATION_TIMINGS)),
    ])
  ]
})
export class FilePreviewOverlayComponent {
  ...
}

As you can see we created two animations, one for fading in the image (fade) and the other one to slide up the content (slideContent). The fade animation will mostly be visible in combination with a spinner. Remember how we used the property binding to temporarily make the image invisible while loading? With the fade animation we can now replace our temporary solution with proper one that leverages the animation DSL.

Next, we define an animationState property that represents the current animation state, e.g. void, enter or leave. By default it’s set to enter that will cause the content of the file preview to always slide up when it’s opened.

@Component({...})
export class FilePreviewOverlayComponent {
  ...
  animationState: 'void' | 'enter' | 'leave' = 'enter';
}

Now we can connect the pieces and set it up in the template:

@Component({
  template: `
    <div class="overlay-content" [@slideContent]="animationState">
      <div class="spinner-wrapper" *ngIf="loading">
        <mat-spinner></mat-spinner>
      </div>

      <img [@fade]="loading ? 'fadeOut' : 'fadeIn'" (load)="onLoad($event)" [src]="image.url">
    </div>
  `,
  ...
})
export class FilePreviewOverlayComponent {
  ...
}

We can see that the entire content, including the spinner as well as the image, is wrapped in a container div. That’s because we only want the content to slide up. Later we’ll introduce a toolbar component which comes with its own set of animations. This also implies that it wouldn’t make any sense to use a @HostBinding() and apply the animation to the host element.

Done! Here’s a live demo with all the code above:

Animations guide our users and the overlay smoothly animates in. This is already much more engaging compared to what we had before but we can do even better. What about closing it? That’s right, we also want it to animate out.

At the moment we simply call this.overlayRef.dispose() which will detach the portal from the host, eventually removing it from the DOM. With this straightforward approach there’s no way we can execute animations before it is disposed.

What we can do instead is to leverage animation callbacks and introduce event streams that we can subscribe to. Angular provides animation callbacks that are fired when an animation is started and also when it is done.

Let’s start with the animation callbacks and hook them in the template of our FilePreviewOverlayComponent:

@Component({
  template: `
    <div class="overlay-content"
      [@slideContent]="animationState"
      (@slideContent.start)="onAnimationStart($event)"
      (@slideContent.done)="onAnimationDone($event)">
      ...
    </div>
  `,
  ...
})
export class FilePreviewOverlayComponent {
  ...
}

The animation callbacks alone are not very useful, at least not for animating the overlay out. What’s missing is an event bus that we can use to broadcast animation events. That’s needed because when we close an overlay, we have to wait until the leaving animation is done before we can dispose the overlay. We’ll see in just a second how to use this but first let’s define a new EventEmitter inside the overlay component class:

import { ..., EventEmitter } from '@angular/core';
...
@Component({...})
export class FilePreviewOverlayComponent {
  ...
  animationStateChanged = new EventEmitter<AnimationEvent>();
}

The EventEmitter is an abstraction around a the Subject type from RxJS.

Cool, now let’s wire up the animation callbacks. To do this, we’ll define the two missing methods onAnimationStart() and onAnimationDone(). Every time one of the animation callbacks is fired, we broadcast the animation event using animationStateChanged. Moreover, we need a way to start the leave animation once we close an overlay. Therefore we’ll also add a method called startExitAnimation() that sets the animationState to leave. This will then trigger the corresponding animation.

@Component({...})
export class FilePreviewOverlayComponent {
  ...
  onAnimationStart(event: AnimationEvent) {
    this.animationStateChanged.emit(event);
  }

  onAnimationDone(event: AnimationEvent) {
    this.animationStateChanged.emit(event);
  }

  startExitAnimation() {
    this.animationState = 'leave';
  }
}

We know that we programatically close an overlay using the remote control aka FilePreviewOverlayRef. So far we have no access to the overlay component from within the FilePreviewOverlayRef. To fix this we define a property componentInstance on the remote control.

export class FilePreviewOverlayRef {
  ...
  componentInstance: FilePreviewOverlayComponent;
  ...
}

We simply set the componentInstance when an overlay is opened.

@Injectable()
export class FilePreviewOverlayService {
  ...
  open(config: FilePreviewDialogConfig = {}) {
    ...
    // Instantiate remote control
    const dialogRef = new FilePreviewOverlayRef(overlayRef);

    const overlayComponent = this.attachDialogContainer(overlayRef, dialogConfig, dialogRef);

    // Pass the instance of the overlay component to the remote control
    dialogRef.componentInstance = overlayComponent;
    ...
  }
}

Now we can go ahead and introduce two event streams on the FilePreviewOverlayRef. The first one emits values before the overlay is closed and the other one after is was closed. For the streams we’ll use the Subject type from RxJS and also expose public methods for each of the event streams.

export class FilePreviewOverlayRef {

  private _beforeClose = new Subject<void>();
  private _afterClosed = new Subject<void>();

  ...

  afterClosed(): Observable<void> {
    return this._afterClosed.asObservable();
  }

  beforeClose(): Observable<void> {
    return this._beforeClose.asObservable();
  }
}

From there we can use the component instance and subscribe to the animation events and act accordingly. This means that when an animation was started we detach the backdrop and call next() on _beforeClose. When an animation is finished we broadcast on _afterClosed. This also means we can dispose the overlay and remove it from the DOM.

import { filter, take } from 'rxjs/operators';
...
export class FilePreviewOverlayRef {
  ...
  close(): void {
    // Listen for animation 'start' events
    this.componentInstance.animationStateChanged.pipe(
      filter(event => event.phaseName === 'start'),
      take(1)
    ).subscribe(() => {
      this._beforeClose.next();
      this._beforeClose.complete();
      this.overlayRef.detachBackdrop();
    });

    // Listen for animation 'done' events
    this.componentInstance.animationStateChanged.pipe(
      filter(event => event.phaseName === 'done' && event.toState === 'leave'),
      take(1)
    ).subscribe(() => {
      this.overlayRef.dispose();
      this._afterClosed.next();
      this._afterClosed.complete();

      // Make sure to also clear the reference to the
      // component instance to avoid memory leaks
      this.componentInstance = null!;
    });

    // Start exit animation
    this.componentInstance.startExitAnimation();
  }
}

That’s it. Here’s a live demo:

Adding a toolbar component

To finish this up we will create a toolbar component, add animations and also make use of the events streams exposed by the remote control to animate the toolbar out before the overlay is closed.

@Component({
  selector: 'tm-file-preview-overlay-toolbar',
  templateUrl: './file-preview-overlay-toolbar.component.html',
  styleUrls: ['./file-preview-overlay-toolbar.component.scss'],
  animations: [
    trigger('slideDown', [
      state('void', style({ transform: 'translateY(-100%)' })),
      state('enter', style({ transform: 'translateY(0)' })),
      state('leave', style({ transform: 'translateY(-100%)' })),
      transition('* => *', animate('400ms cubic-bezier(0.25, 0.8, 0.25, 1)'))
    ])
  ]
})
export class FilePreviewOverlayToolbarComponent implements OnInit {

  // Apply animation to the host element
  @HostBinding('@slideDown') slideDown = 'enter';

  // Inject remote control
  constructor(private dialogRef: FilePreviewOverlayRef) { }

  ngOnInit() {
    // Animate toolbar out before overlay is closed
    this.dialogRef.beforeClose().subscribe(() => this.slideDown = 'leave');
  }
}

The template is very straightforward and leverages content projection to project content into the template of the toolbar component.

<!-- file-preview-overlay-toolbar.component.html -->
<div class="toolbar-wrapper">
  <ng-content></ng-content>
</div>

Finally we have to use the toolbar inside the template of the overlay component:

@Component({
  template: `
    <tm-file-preview-overlay-toolbar>
      <mat-icon>description</mat-icon>
      {{ image.name }}
    </tm-file-preview-overlay-toolbar>

    <div class="overlay-content"
      ...
    </div>
  `,
  ...
})
export class FilePreviewOverlayComponent {
  ...
}

That’s pretty much! Let’s have a look at our final solution:

Source:: Thoughtram

Vue.js with TypeScript

By John Papa

I spent a few days on and off learning parts of Vue to write a small app. I wrote the same app with Angular. I’m sharing my experience of working through Vue for the first time to help others that may be curious about the JavaScript framework landscape.

This post explores how I refactored the Vue app to use TypeScript. The two places I found the most help were in this (Microsoft resource](https://github.com/microsoft/typescript-vue-starter) and the Vue docs. Neither was exactly what I needed, but together they were helpful in gaining success. Read on to learn more.

Disclaimer: This was my first attempt at using TypeScript in Vue. My intent is to share the journey, not to claim this is the “best” way to use TypeScript. I know TypeScript well, but I am learning Vue and leaning on the experts from the Vue document and TypeScript team’s resources on Vue for much of what I accomplished. I give credit to both of these teams for making these resources available and helping the community.

Why TypeScript?

Hold on a second … Why? I mean, why use TypeScript at all? JavaScript is awesome, why do we need TypeScript? Well, we don’t need* it. But I want it. But again … why? Why do I want TypeScript? This is a question we should always ask when someone tells us we should use something. Far too often we find ourselves reading how to do something … but the **why is often far more important.

Simply put TypeScript allows me to code faster and to catch and rectify more problems at development time than without it. Intellisense, auto-complete, and great tooling are enabled when editors can use the TypeScript features. Need some examples? OK … We can tell what the return type of an asynchronous function is an array of Hero models. Or we can find that we use a heroes array in one place as an array and in another as an ES promise. When the editor is smarter, I can adapt quickly and fix problems before I deploy.

If you are interested in how I got started with Vue, here are some other posts that may interest you:

Setup

I had to start somewhere, so I started by branching off of my connect2017 branch in this repo. This gave me a functional Vue app out of the box that I could begin refactoring to use with TypeScript.

I started by adding in the files that tell TypeScript how to do its job.

tsconfig.json

The first new file is tsconfig.json. I started with the file that the Vue documentation recommends here. Then I enhanced it a bit. I found the changes to be super helpful.

The following file tells TypeScript to put the compiled JavaScript in the ./built folder, to generate source maps for debugging and use TypeScript decorators (among other settings). I also added in lib support for some core ES2016 features.

webpack.config.js

I knew I needed to change how the build process worked. For this, I opened the webpack.config.js and immediately started to Google for some help. I find WebPack configuration to be painful … hey, it’s an awesome tool, but I admit that it’s not easy for me to figure out what I need to modify in there. Luckily I found this guide by the TypeScript team that showed how to modify the file.

These are the git changes I made to my file.

We can see that the entry file is now the main.ts instead of main.js. That makes sense. Then there are settings for a ts-loader, which helps load the TypeScript with Vue. Finally, I added some extensions to the resolve section.

Do I expect this is all perfect? Nope. It works … and this is the kind of thing that once the Vue CLI adds a TypeScript template to its tooling, we won’t have to mess with it at all. So let’s proceed.

npm packages

I’m adding TypeScript to the project so it makes sense that I had to add some packages to support this. (The Vue CLI should handle this once it adds the new TypeScript template, too.)

First I ran npm run typescript ts-loader --save-dev to add them as a development dependency. This came from the helpful Microsoft doc here. I deviated from that helped doc because I already had some of the others and I like to code dangerously.

Next, I ran npm install vue-property-decorator vue-class-component --save to install support for the TypeScript decorators. The decorators will help define classes as Vue components and define props.

Note: I only ended up using one of these directly. The @Component() decorator is in vue-class-component but it is imported and re-exported from vue-property-decorator.

vue.shims.d.ts

We can define files that help TypeScript and the tooling know how to handle some specific types. The helpful Microsoft doc here suggested adding the following code to a new file named vue.shims.d.ts. It basically makes it easier for the tooling to know how to handle *.vue files, also known as Single File Components (SFC).

Refactoring the Code Files

A great way to look at the changes required during my refactor is to use a file by file comparison. Let’s begin.

main.js –> main.ts

I renamed the main.js file to main.ts. Yep, no code changes in this one. Move along.

App.vue

The App component is the root component in the Vue app. Here is its original file using Babel with JavaScript.

The next image shows the TypeScript. Take a glance, then read on to learn how I refactored the code to get here.

First, I added a hint to the tag to let it know I will be using TypeScript. Notice the tag is now in the image below.

I added the @Component() decorator to both tell Vue that the class following the decorator is indeed a Vue component and that this component will reference a child component named HeroList. This components property in the decorator was lifted right from the components property in the JavaScript example.

I refactored the default export to become a named class App that extends Vue. This makes sense as the name of our component is App. We extend Vue as a way of preparing our class to be a component. See an example in the Vue docs here.

I refactored the data properties to become public class properties. Then I initialized the title property in the constructor. I could also have done this in a lifecycle event, which probably makes more sense.

Notice I added a few import statements to the top of the file. This helped the tooling and TypeScript know where to get the Vue and Component symbols.

HeroList.vue

The HeroList.vue file contains the logic for getting and displaying the heroes. The JavaScript version is shown below for reference. Notice I collapsed the components and methods to make it easier to follow. Full source code can be found at the end of this post.

Here follows the TypeScript version of the file, after my refactoring effort. Take a moment to see the differences and how they map to each other.

Just as with the App.vue file, the components moved up to the decorator and the data properties became public class properties. There are some subtle differences here though as we look closer. Notice that I added explicit types to selectedHero and heroes. I did not need to do this, but it helped clarify things.

The selectedHero was initialized to null so the details wouldn’t appear until a selection had been mad. But now that I have a Hero type
(we’ll explore that in the next section), I wanted to be clear to the compiler of my intentions that the selectedHero should be allowed to be null or of type Hero.

But perhaps far more interesting is how I went from initializing the heroes array right in the data function in the JavaScript example to initializing it in the created life cycle event in the TypeScript example. This is one place I found a bug in the JavaScript example. I was setting the heroes to the return value from the getHeroes function … which was not an array of heroes, but instead a promise of an array of heroes. This did not bite me in the running code because I was, but it could have. It worked only because the getHeroes function sets the heroes array … so it immediately ran and filled the array anyway. But this just hid the bug. When I refactored it to use TypeScript the editor alerted me that I had a type mismatch. Then I moved the call to getHeroes to the created lifecycle event. Ladies and gentlemen, that’s a real bug … not something I staged. Oops! But thankfully the editor caught my mistake and I was able to correct it during the refactor.

We also have some new imports up top in the TypeScript file and I added some more explicit typings in a few places, so I could make sure I had no more hidden bugs. That’s the value of setting noImplicityAny: true in the tsconfig.json file.

Hero Model

Now that I have types, I added a hero.ts file to define a Hero class. This helped make sure the components that deal with heroes are using the right types and properties.

HeroDetail.vue

The HeroDetail component had many of the same changes as the HeroList component. Some imports up top, the @Component() decorator, moving the data properties to public class properties, and defining some explicit types.

Check out the JavaScript version here.

Now take a glance at the TypeScript version, after the refactoring effort.

What’s new here is that I am using the @Props() and @Watch() decorators in the TypeScript version. Notice the hero that I was watching in the JavaScript version is now a public class property decorated with @Prop(). This was a simple refactoring.

Then I defined a named function onHeroChanged and decorated it with the @Watch() decorator. This went from a function named hero in the JavaScript version to a named function with a @Watch() decorator in the TypeScript version.

I access the $refs to grab the elements to set focus on them. I made a public class property named $refs and typed it with the names of the two references I had in the Vue template. Both are of type HTMLElement.

Hero Service

The hero service refactor was quite simple. The TypeScript version became an instance of a class that I could import into the components and use as needed. Nothing out of the ordinary here. This could have simply been a set of exported functions, too. There are lots of ways to handle services in JavaScript/TypeScript.

Summary

The best question to ask is “was it worth it?”. Only you can decide. I think it was worth it. It caught a bug I had in the JavaScript version and now I get a lot more help from my tools, like VS Code, when writing the app.

I’m looking forward to the official TypeScript template for the Vue CLI. But in the meantime, there are a few ways to use TypeScript with Vue projects.

Source Code

You can find the source code for these apps here:

Source:: johnpapa