Friday, January 27, 2017

Branding Guidelines for Angular and AngularJS

Angular
In September of last year we made several big announcements. We released version 2.0.0 of Angular and that we were adopting Semantic Versioning, meaning that developers will see version number increases in a planned and careful manner. As a result of these announcements, you’ve seen us using the term Angular to refer to all versions of the framework after 2.0.0.


We’ve had a great response from Developers about this. Bloggers and authors and discussions boards can in most contexts drop the version number from discussions of Angular, because the tutorials, tips, tricks, and content that works in version 2 will work in version 4, and likely beyond. This allows those discussing Angular to talk about the framework without becoming prematurely dated each time there’s a version bump.


Here’s an example tutorial you could write:


Correct
Angular Router Guide - Learn about how to use the Router in Angular as the basis for page animations, analytics tracking, and how to fetch parameters and data reactively from the router.
Incorrect
Angular 2 Router Guide - Learn about how to use the Angular 2 Router as the basis for page animations, analytics tracking, and how to fetch parameters and data reactively from the router.

Reasoning
By not using “Angular 2” in the title, the content still feels applicable and useful after version 4, 5, 6, 7, etc have been released, as the syntax is unlikely to change.


AngularJS
Our announcements around “It’s just Angular" were the first step in bringing consistency into the naming of the platform and the ecosystem. Our recommendation last month was to use Angular 1 for all 1.x versions of the framework and Angular for all the subsequent versions (unless a version was required for clarification in a given context). We heard from the community that because AngularJS has been used for for so long, it would be too hard and confusing to "rewrite history" across the web and the physical world.


We agree with this and we have accepted the suggestions many of you have brought up to return to our roots with the name AngularJS for any 1.x release, and Angular for any 2+ release. Our goal is to bring as much consistency as possible especially going forward, while reducing the maintenance burden caused by past branding inconsistencies.


These new guidelines match what already exists in a number of ways. If you are looking for a book on version 1.x, you’ll probably find it with the name AngularJS. And as more content is written consistently using these guidelines, it should become easier to search for what you are looking for.




What about Angular Material?
Angular Material is a project led by Google to build a great reusable component library for Angular Developers. The Material project takes Google’s design principles, and boils them down into components you can add your projects. We are continuing to invest in Material as a great choice for developers working with either Angular or AngularJS. To match the name guidelines, we’re clarifying the naming of the projects to “Angular Material” and “AngularJS Material”.


Brand Guidelines
For the full guidelines, check out our Press Kit.

We've been propagating these standards across all of our projects over the last week or so, but there's more work to be done. You can help by using these names to build consistency across the ecosystem! Here are some handy regular expressions if you'd like to help us fix the branding in your projects!
s/angular (1\.\d)/AngularJS $1/ig
s/angular 1\.x/AngularJS/ig
s/angular 1/AngularJS/ig
s/angular1/AngularJS/ig
s/angular 2\.0/Angular/ig
s/angular 2/Angular/ig
s/angular 2\.x/Angular/ig
s/angular2/Angular/ig

Friday, January 13, 2017

Understanding AOT and Dynamic Components

This is a guest post from Sean Landsman at ag-Grid. Sean is the lead engineer on ag-Grid's Angular integration. -- Stephen Fluin


Motivation

ag-Grid is an enterprise datagrid that works with Angular. As ag-Grid works with many frameworks, the internals of the grid had to allow for Angular rendering inside the grid despite ag-Grid not being written in Angular itself. This was done using Angular Dynamic Components and we managed to do it while still supporting AOT. This blog details what we learnt along the way.

The Setup

To explain we present a simple sample application that isolates what we are trying to do. In our example below we are going to develop two main Modules - one will be a Library (in our case this was ag-Grid) that will display an array of dynamically created Components (similar to how ag-Grid displays Angular components inside the grid's cells), and the other will be our actual Application.
The end result will be look like this:




You can find all the code for this example over at GitHub, and the live example over at GitHub.io
One further note - when we return to "user" below, we are referring to a user (or client) of the Library we're writing.

The Library

Our Library is going to be a simple one - all it does is display an array of dynamically created Angular Components. The main component looks like this:

@Component({
    selector: 'grid-component',
    template: `
        <div class="row" *ngFor="let cellComponentType of cellComponentTypes">
            <div class="col-lg-12">
                <grid-cell [componentType]="cellComponentType"></grid-cell>
            </div>
        </div>
    `
})
export class Grid {
    @Input() componentTypes: any;

    cellComponentTypes: any[] = [];

    addDynamicCellComponent(selectedComponentType:any) {
        this.cellComponentTypes.push(selectedComponentType);
    }
}

As you can see it's a pretty simple component - all it does is display the current cellComponentTypes. These are the user supplied components, and they can be any Angular Component.

The interesting part of the Library is in the Cell Component:

@Component({
    selector: 'grid-cell',
    template: ''
})
export class Cell implements OnInit {
    @Input() componentType: any;

    constructor(private viewContainerRef: ViewContainerRef,
                private cfr: ComponentFactoryResolver) {
    }

    ngOnInit() {
        let compFactory = this.cfr.resolveComponentFactory(this.componentType);
        this.viewContainerRef.createComponent(compFactory);
    }
}

You'll notice that we don't have a template here - that's deliberate as the Cell doesn't have any
    content of its own - all it does is serve up the user supplied Component. The important part of this Component are
    these two lines:

let compFactory = this.cfr.resolveComponentFactory(this.componentType);

This line asks the ComponentFactoryResolver to find the ComponentFactory for the provided
    Component. We'll use this factory next to create the actual component:

this.viewContainerRef.createComponent(compFactory);

And that's all there is to it from the Library Component side of things - we find the factory for the Component, and
    then create a new instance of the Component. Easy!

For this to work we need to tell Angular's AOT Compiler to create factories for the user provided Components, or ComponentFactoryResolver won't find them. We can make use of NgModule.entryComponents for this - this will ensure that the AOT compiler creates the necessary factories, but for you purposes there is an easier way, especially from a users perspective:

@NgModule({
    imports: [
        BrowserModule,
        FormsModule
    ],
    declarations: [
        Grid,
        Cell
    ],
    exports: [
        Grid
    ]
})
export class GridModule {
    static withComponents(components: any[]) {
        return {
            ngModule: GridModule,
            providers: [
                {provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: components, multi: true}
            ]
        }
    }
}

By making use of ANALYZE_FOR_ENTRY_COMPONENTS here, we are able to add multiple components to the NgModule.entryComponents
    entry dynamically, in a user friendly way.

The Application

From the application side of things, the first thing we need to do is create the components we want to use in the Library - these can be any valid Angular Component. In our case we have three similar Components:

@Component({
    selector: 'dynamic-component',
    template: '<div class="img-rounded" style="background-color: lightskyblue;margin: 5px"> Blue Dynamic Component! </div>',
})
export class BlueDynamicComponent {
}

All these components do is display a little styled text.
To register these in both our Application, and in the Library, we need to switch to the Application Module:

@NgModule({
    imports: [
        BrowserModule,
        FormsModule,
        GridModule.withComponents([
            BlueDynamicComponent,
            GreenDynamicComponent,
            RedDynamicComponent
        ])
    ],
    declarations: [
        AppComponent,
        BlueDynamicComponent,
        GreenDynamicComponent,
        RedDynamicComponent
    ],
    bootstrap: [AppComponent]
})
export class AppModule {
}


We declare our Components in the usual way, but we additionally need to register them with the Library (remember,
    this is the part where they'll be added to the
    Library's NgModule.entryComponent entry). We do this in this part of the module:

GridModule.withComponents([
    BlueDynamicComponent,
    GreenDynamicComponent,
    RedDynamicComponent
])


Finally, we can take a look at the main Application Component:

@Component({
    selector: 'my-app',
    template: `
        <div class="container-fluid">
            <div class="page-header">
                <h1>Creating AOT Friendly Dynamic Components with Angular
</div>
            <div class="row">
                <div class="col-lg-12">
                    <div class="panel panel-default">
                        <div class="panel-heading">Application Code</div>
                        <div class="panel-body">
                            <div class="input-group">
                                <span class="input-group-btn">
                                    <button type="button" class="btn btn-primary" (click)="grid.addDynamicCellComponent(selectedComponentType)">Add Dynamic Grid component
    </span>

                                <select class="form-control" [(ngModel)]="selectedComponentType">
                                    <option *ngFor="let cellComponentType of componentTypes" [ngValue]="cellComponentType">{{cellComponentType.name}}
    </select>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-12">
                    <div class="panel panel-default">
                        <div class="panel-heading">Library Code</div>
                        <div class="panel-body">
                            <grid-component #grid></grid-component>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    `
})
export class AppComponent implements OnInit {
    @Input() componentTypes: any[] = [BlueDynamicComponent, GreenDynamicComponent, RedDynamicComponent];
    @Input() selectedComponentType: any;

    ngOnInit(): void {
        // default to the first available option
        this.selectedComponentType = this.componentTypes ? this.componentTypes[0] : null;
    }
}

It may look like theres a lot going on here, but the bulk of the template is to make it look pretty. The key parts of this Component are:

<button type="button" class="btn btn-primary" (click)="grid.addDynamicCellComponent(selectedComponentType)">Add Dynamic Grid component

This will ask the Library to add a create a new instance of the supplied Component, and in turn render it.

<grid-component #grid></grid-component>


And this line is our Library Component.

That's it - easy to write and use (from both an Application and Library perspective), and AOT (and JIT!) friendly.

Benefits of using AOT

The speed and size of the resulting application when using AOT can be significant. In our ag-grid-ng2-example project, we estimate the size of the resulting application went from 3.9Mb down to 2.4Mb - a reduction of just under 40%, without optimising for size or being particularly aggressive with rollup.

Speed-wise, the loading time when using AOT is significantly more responsive on startup - this makes sense given that Angular doesn't have to compile all the code once again. Take a look at the examples project and try both the JIT and AOT versions out for yourself!

There's so much more you can do if you decide to combine Angular Components with ag-Grid - powerful functionality, fast grid and easy configuration. What are you waiting for?!