Creating directives is a big part of taking full advantage of all that the Angular framework has to offer, and the best way to take advantage of Angular is with Dart. If you've ever created a directive, it was probably an attribute directive, and if you've used Angular 2+ at all, you've definitely created the specialized form of directive known as a component. In this tutorial, you'll build a somewhat more advanced type, called a structural directive.
If you're unfamiliar with Dart or Angular, you may want to visit a more comprehensive tutorial like Build a Real-Time Chat Web App with AngularDart and Firebase, or any of the many other beginner-oriented articles on Dart Academy. Or if you're really new, try the Quickstart. For this article, we're going to concentrate entirely on the specific subject of structural directives.
Code tested with Dart SDK 1.24.2 and AngularDart 4.0.0.
What's a Structural Directive?
A structural directive is meant to change the DOM layout by adding and removing elements. Sounds simple, right? This is best illustrated with an example from Angular's built-in directives: NgIf.
Hi! Isn't AngularDart just fantastic?
Typically, you would include a more interesting condition in place of If that condition is What's with the asterisk in that example? If you haven't wondered this at some point, you are not paying attention to your lessons well enough. That thing is shorthand (syntactic sugar) for using the HTML 5 You can totally write your code this way if you want to, but most of us prefer the shorthand. However, it's important to understand how it all unfolds when you start writing your own structural directives. Now I'll show you how you can create your own structural directive. This directive will add a template to the DOM only when its data's In your parent component, add some code like this list of users. Note that we're using Maps here for simplicity, but since this is Dart, you should really use classes, interfaces, and so on for a real app. The idea here is that you want to throw all these into a list, but you only want the active ones to show up. lib/src/directives/display_active_dir.dart The first thing to note here is how much nicer and cleaner this code is compared to that other Angular language, especially when it comes to imports, the constructor, and accessing member variables. At the top of your directive file, you import Angular, which gives you access to everything you need to create a structural directive. You use the To mess with DOM structure, you need access to a few of Angular's structural references, namely Lastly, you create an @Input() setter with the same name as the attribute from If the setter finds that the incoming Map has a To use the new directive, there are just a few steps. You need to import your new directive into any component that will make use of it, and that will look something like this: lib/app_component.dart In the parent component's lib/app_component.dart To use DisplayActiveDirective, apply the correct attribute to any element, like so: lib/app_component.html {{user['name']}} Yes, stars! Preceding {{user['name']}} If you forget to include the asterisk in the concise example, you'll see a terrifying error message: If you've done everything correctly, your output should be: The other users are inactive, so they don't make the cut. If you enjoyed this brief exploration into the world of structural directives in AngularDart, you'll really enjoy using these technologies to build amazing things in record time. It's up to you to get Dart out there, doing the good it was designed to do. Get the latest posts delivered right to your inboxtrue here, but you probably already know what will happen with this code. Because the condition you passed to NgIf resolves to true, the false, the display: none; it's not in the DOM at all. Use the DOM inspector to see for yourself if you don't believe me. If you discover that I'm right, be sure to treat that as a representative precedent and trust me from now on.
Another Way To Put It
tag, like so:
Create Your Own
active field is true.First, Some Data for Context
ListNext, the Directive
import 'package:angular/angular.dart';
@Directive(selector: '[displayActive]')
class DisplayActiveDirective {
TemplateRef _templateRef;
ViewContainerRef _viewContainer;
DisplayActiveDirective(this._templateRef, this._viewContainer);
@Input()
set displayActive(Map data) {
if (data != null && data['active']) {
_viewContainer.createEmbeddedView(_templateRef);
} else {
_viewContainer.clear();
}
}
}
Import
Decorator
@Directive() decorator to tell Angular that your class, DisplayActiveDirective, will be a directive. You don't need to tell it anything special to make it a structural directive. The selector uses the CSS attribute syntax with the square brackets, meaning that any element with displayActive as an attribute will have this directive applied, just like with the more common attribute directives.Injections
TemplateRef and ViewContainerRef. In the class's constructor, Dart's shorthand syntax for field initialization is used to make _templateRef a reference to your directive's tag, which Angular will automatically add for you via the * syntax when you make use of displayActive. The _viewContainer property gives you access to the DOM renderer.Need Some Input
@Directive()'s selector parameter. The directive's consumer will pass a Dart Map into the directive like this: *displayActive="myMap". There's that asterisk again! Be sure you don't forget it.true active field, it uses the _viewContainer to render the contents of _templateRef to the DOM. Those contents are whatever is within the invisible tag that Angular provides when you use the asterisk syntax. If the data fails to pass muster, the renderer is used to clear the deck.Try It
Import It
import 'src/directives/display_active_dir.dart';
Include It
@Component() decorator, there is a directives parameter. Your new directive's class name should appear in that list, something like this:@Component(selector: 'my-app',
templateUrl: 'app_component.html',
directives: const [DisplayActiveDirective]
)
Use It

displayActive with an asterisk causes Angular to expand the code to look like this:
No provider for TemplateRef! If you see that, you need more stars.The Output
General Dartman
Private JavaScript
Sergeant Go
Conclusion
Subscribe to Dart Academy