This content originally appeared on Telerik Blogs and was authored by Alyssa Nicoll
Angular 15 brings two amazing features out of developer preview: Standalone APIs (Components, Pipes, Directives) and the Image Directive! Take a closer look!
Happy Fall, to those of you on the same side of the globe as me. And HAPPY ANGULAR VERSION 15 to all!
Check out the official release Angular Blog Release written by the lovely Minko and the release notes detailed in the Angular CHANGELOG or the much easier to read Breaking Changes in the docs! Some of my favorite highlights are two amazing features out of developer preview: Standalone APIs (i.e., Components, Pipes, Directives) and the Image Directive!
Updates include but are not limited to:
- Standalone API Stable
- Directive Composition API
- Image Directive Stable
- Functional Router Guards
- Router Unwraps Default Imports
- Improved Stack Traces
- Release MDC-based Components to Stable
- Other Component Upgrades
- CDK Listbox
- Experimental ESBuild Support Improvements
- Automatic Imports In Language Service and Banana in Box Fix Support
- CLI Improvements
- Provide an ability to configure default options for DatePipe
- Add preload tag for priority images during SSR
- Deprecated providedIn:'Any’ and providedIn: NgModule
- Planned Deprecation of @angular/flex-layout
- Deprecated Typescript code that relies on
keyframes
Getting Updated
First thing is first, though. We need to update in order to access the new goods! The official Angular Update Guide is always a great place to start. But the
meat of the update is this command: ng update @angular/core@15 @angular/cli@15
.
Now this girl always runs into new and exciting npm issues, so I am sure it was just a fluke. That said, if you do run into some as well for your Angular apps, remember, deleting your
node_modules
folder and yourpackage-lock.json
and re-runningnpm install
after updating dependencies can get you out of many-a-pickle.
For this latest version, you can remove the line in your tsconfig about enableIvy (since Ivy is the only rendering engine option for version 15 of Angular).
Breaking Changes
This particular breaking change did catch me: https://angular.io/guide/update-to-version-15#the-title-property-is-required-on-activatedroutesnapshot
Simply changing “text” to “title” in my routes fixed this:
src/app/app-routing.module.ts [old]
const routes: Routes = [
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: 'detail/:id', component: HeroDetailComponent },
{ path: "dashboard", component: DashboardComponent, text: "Dashboard" },
{ path: "heroes", component: HeroesComponent, text: "Heroes" },
];
src/app/app-routing.module.ts
const routes: Routes = [
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: 'detail/:id', component: HeroDetailComponent },
{ path: "dashboard", component: DashboardComponent, title: "Dashboard" },
{ path: "heroes", component: HeroesComponent, title: "Heroes" },
];
Standalone APIs
As touched on above, standalone APIs are now out of developer preview and ready for mainstream use with Angular version 15. For getting started with standalone components, you should check out Jessica Janiuk’s video here in the docs: https://angular.io/guide/standalone-components#creating-standalone-components.
There are also a couple articles and repos I recommend written by fellow GDEs:
Manfred Steyer [Articles]
- Router: https://www.angulararchitects.io/aktuelles/routing-and-lazy-loading-with-standalone-components/
- HttpClient: https://www.angulararchitects.io/aktuelles/the-refurbished-httpclient-in-angular-15-standalone-apis-and-functional-interceptors/
And the web component article is at least indirectly about Standalone APIs:
Marko Stanimirović [Article]
(This article is before the standalone NgRx and Router APIs were released.)
Dhananjay Kumar [Article]
Q Ray @tipster22 [Repo]
Netanel Basal @NetanelBasal [Repo]
Lonli-Lokli @sirlonlilokli [Repo]
Follow along with Mike Brocchi’s recent twitter chain for emerging repos with standalone APIs in use: https://twitter.com/Brocco/status/1593234105613058050
Giving Standalone a Try
All of this standalone hype has got me itching to try this feature. So, I pulled up my go-to-demo (Tour of Ponies) and decided
to give it a try. You can use the CLI to generate a standalone component: ng -g component standalone-card
--``standalone
.
I want to replace my hero-card
component with this standalone-component and see if there is any difference in practical usage. So far, in generating, the only difference (other than not being included in any module) are these two lines
in the component’s TypeScript file:
Jessica mentions it in her tutorial, but the CommonModule being imported here is what gives our standalone component access to things like ngIf, ngFor and other directives. After creating the standalone component, we still need include it in our app module so our app knows about it. Note, it goes in the imports, not the declarations.
Now I replaced hero-card with this standalone component card and even copied over the markup/logic from our hero card. These components are identical now, except one is module-less. However, when we serve up our app, you can see by not only the UI but the console errors, our standalone component doesn’t know about the Kendo UI library elements we were using in hero-card.
Similar to feature modules, you need to include your dependencies inside the component’s TypeScript file, like I did below for the Kendo UI Layout module. (This is the npm package that includes the desired kendo-card
.)
However, the hero-card also uses a custom pipe I made called ellipsis-pipe
:
<p kendoCardSubtitle *ngIf="hero.residence" title="{{ hero.residence }}">{{ hero.alias }} from {{ hero.residence | ellipsis:25 }}</p>
In order to use this pipe, we need to export it like so with its own module:
Then we can import it into our standalone card component:
import { Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Hero } from '../hero';
import { LayoutModule } from '@progress/kendo-angular-layout';
import { AppRoutingModule } from '../app-routing.module';
import { PipesModule } from '../pipes/pipes.module';
import { EllipsisPipe } from '../pipes/ellipsis.pipe';
@Component({
selector: 'standalone-card',
standalone: true,
imports: [CommonModule, LayoutModule, AppRoutingModule, PipesModule],
templateUrl: './standalone-card.component.html',
styleUrls: ['./standalone-card.component.css']
})
export class StandaloneCardComponent {
@Input() hero: Hero;
}
HOWEVER, the standalone API not only allows you to create components without modules, but directives and pipes as well. So it seems silly to create a card component without a module, only to need to create a module for our custom pipe. We’d end up module-neutral and we are trying to reduce the number of modules in our app! So let’s make our pipe standalone while still exporting it for use in our standalone component.
Making Our Angular Pipe Standalone
This was by far the easiest thing I have ever done in Angular. I added standalone: true
to the pipe declaration and then wherever I was importing the pipes module (app.module.ts
and standalone-card.component.ts
),
I instead just included the pipe itself:
standalone-card.component.ts
import { Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Hero } from '../hero';
import { LayoutModule } from '@progress/kendo-angular-layout';
import { AppRoutingModule } from '../app-routing.module';
import { EllipsisPipe } from '../pipes/ellipsis.pipe';
@Component({
selector: 'standalone-card',
standalone: true,
imports: [CommonModule, LayoutModule, AppRoutingModule, EllipsisPipe],
templateUrl: './standalone-card.component.html',
styleUrls: ['./standalone-card.component.css']
})
export class StandaloneCardComponent {
@Input() hero: Hero;
}
We have imported things like commonModule, LayoutModule and AppRoutingModule because standalone components manage their own dependencies. This might seem like an extra step, however, the explicit-ness inline is quite eye-opening to what you’re actually using per component. I think it’s nice to have it included here, versus a global app module or even feature module. It’s more verbose on the component level, but less steps overall.
And, as easy as that, all places once using my hero-card component are now using my standalone-card.
“But Alyssa,” you might say to yourself, “What was it all for? We’ve added zero new functionality.” And alas, you are correct. But the door that module-less things opens is a component-centered and exciting one. It makes the API face of our language that much simpler and attainable to beginners and that much easier for maintainers. I personally am excited to walk through it.
Directive Composition API
The next step in this module-less evolution is the directive composition API, which opens up new code reuse strategies. The composing directives with this API only works with standalone directives (as one would imagine) and was truly the missing piece in this module-less puzzle.
@Component({
selector: 'navbar-anchor',
template: 'navbar-anchor.html',
hostDirectives: [AnchorFunc],
})
export class NavbarAnchor { }
So here I am applying the AnchorFunc
directive to the host element, NavbarAnchor
. (Again, to try some of this stuff out, would highly recommend Manfred’s blogs above to help guide you along with the official docs. Manfred
is a 10/10 teacher.)
I did attempt to put our pipe inside the hostDirective, to avoid creating a module for it. However, I ended up crashing the ALS. So I don’t believe pipes are supported here. But it was worth a try! lol
So, only use the directive composition feature with directives AND use them sparingly.
While the directive composition API offers a powerful tool for reusing common behaviors, excessive use of host directives can impact your application’s memory use. If you create components or directives that use many host directives, you may inadvertently balloon the memory used by your application. — Angular Docs
Image Directive
The image directive feature is another one I am DYING to try. So let’s try it out on this rainbow image in the header!
First, we need to include the new image directive’s module in our app.module.ts. Do I find it odd that he isn’t standalone? Yes, yes I do. But perhaps it is too soon for such things?
Now we can use ngSrc
instead of src
on the rainbow img. However, this optimized image directive requires a width and height (or fill
mode) to render. There are dynamic options as well as considerations for differing
screen sizes along the way. I was really surprised with how fully thought-out the docs felt on this—check them out!
<img src="https://www.telerik.com../assets/images/retro-mlp/my-littt-ponies-rainbow.png" alt="retro my little pony rainbow">
<img ngSrc="https://www.telerik.com../assets/images/retro-mlp/my-littt-ponies-rainbow.png" width="670" height="200" alt="retro my little pony rainbow">
2022, That’s a Wrap
As always, I am super impressed with this latest release of Angular. I love this framework and was reminded just today that it is more than the features that draw me to it. It has been and will always be the people.
I am organizing a stream for The State of JS Survey when it releases early next year. I have ever been an Angular girl, so my connections on that side of JS are naturally stronger. For this year’s stream, I wanted to mix it up and add some new faces. The person I had in mind is a very big fish and fairly high profile, so no open DMs for them. I reached out on their framework’s community discord to attempt to contact the author. I, of course, did not get a hold of this person. Not a huge deal, I knew it was a long shot.
However, what I didn’t expect was the blatant ridicule I got for even daring to speak in that discord. I was even made fun of for how little I posted in that community. It was a stark reminder about how special the Angular community really is. I know this one interaction was not representative of the community as a whole; however, I have never been made to feel this way when asking dumb questions in Angular channels.
In fact, for the above demo, when I made the Angular Language Service crash, I reached out to the Angular team about it. They not only told me that it shouldn’t be happening, but had it fixed within the hour. They also informed me, super kindly, that directive compositions were not for pipes.
I only mention this because as we wrap this year and look back, perhaps we could look forward too. At the end of the day, we are all web devs just making a living on JavaScript’s back. We should be kinder to each other, no matter our background. The way you respond to someone matters—sometimes a great deal. Let’s bring kindness into our communities this next year and make it more inclusive for all. Happy Holidays everyone, and happy Angular v15!
This content originally appeared on Telerik Blogs and was authored by Alyssa Nicoll
Alyssa Nicoll | Sciencx (2022-12-05T09:44:00+00:00) Angular v15—She’s Here!. Retrieved from https://www.scien.cx/2022/12/05/angular-v15-shes-here/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.