-
Notifications
You must be signed in to change notification settings - Fork 771
Style Builders
Reduced to a simplistic form, the Angular Layout library is composed of two things:
- Directives that inject styles [FlexBox CSS or CSSGrid] inline onto DOM elements.
- Responsive MediaQuery features that trigger updates to injected styles based on current viewport size (eg breakpoint).
Traditionally developers customize Angular Layout with either:
- Build-time Custom Directives
- Run-time configuration overrides (eg Startup Configuration )
import {FlexLayoutModule} from '@angular/flex-layout';
FlexLayoutModule.withConfig({
addFlexToParent : true,
disableVendorPrefixes : true
},
breakpoints
);
Obviously the Runtime overrides are limited... and also prevent the developer from customizing the actual styles that will be injected inline.
With the release of v7.0.0-beta.20, however, Angular Layout has introduced the StyleBuilder to allow for greater flexibility for developers.
NOTE: This feature is best suited for advanced users; that is, those who want to dig deeper into the library. Understanding style builders is not a requirement for using the library
Prior to StyleBuilders, the style generation was hard-coded and non-performant... using a simple trigger 'n generate algorithm.
- Each directive instance would get an event to rebuild the styles, and then
- Each directive would generate css styles... every time
Not only is this approach inefficient, it presents a problem if a user disagrees with the default style-generation algorithm. And subsequent changes to the algorithm, of course, would then affect all users.
The StyleBuilder API resolves these issues & provides the greatest flexibility and performance without compromising existing usability.
export abstract class StyleBuilder {
shouldCache = true;
abstract buildStyles(input: string, parent?: Object): StyleDefinition;
sideEffect(_input: string, _styles: StyleDefinition, _parent?: Object) {
// This should be a no-op unless an algorithm is provided in a subclass
}
}
-
buildStyles()
: All style computation that is destined for the host directive happens here, and is returned in the output. Not only that, but the output from this computation is cached, so if there is no need to regenerate styles for the same input, you don't have to! -
shouldCache
: a flag that tells the base directive whether or not to store the computed value frombuildStyles
in the cache (and also whether to retrieve it from the cache before generation) -
sideEffect
: this is meant as a salve in the event that extra computation is needed that doesn't occur on the main directive, and happens regardless of the caching mechanism. This fires each and every time an input event reaches theStyleBuilder
Finally, a note on the parent
parameter. Some directives may requires information from its parent that can't be retrieved from dependency injection alone. To resolve this, we pass in a parent object for certain directives that contain vital information.
- Full control over the style generation process on an ad-hoc basis, i.e. you don't need to override all directives if you don't want to, you can just override one or two
- The ability to handle custom inputs on an organizational/localization level, i.e. different languages for directions in
fxLayoutAlign
, or different keywords, i.e.cc === center center
infxLayoutAlign
- Better performance using the new internal memoization [caching mechanism]
To override injected styles, developers implement a custom StyleBuilder
and use Angular DI to inject an instance of the custom builder instead of the default builder.
For instance, to override the StyleBuilder for fxFlexAlign
:
import { Injectable, NgModule } from '@angular/core';
import {
StyleBuilder,
StyleDefinition,
FlexAlignStyleBuilder,
} from '@angular/flex-layout';
@Injectable()
export class CustomAlignStyleBuilder extends StyleBuilder {
buildStyles(input: string): StyleDefinition {
return { /** CUSTOM_CSS */ };
}
}
@NgModule({
...,
providers: [
{
provide : FlexAlignStyleBuilder, // when default is requested
useClass: CustomAlignStyleBuilder // provide instead custom builder
}
]
})
export class MyAppModule {}
It's now very simple to provide a new default value for directives. Simply create a style builder that calls the original, but with the new default.
@Injectable()
export class CustomAlignStyleBuilder extends FlexAlignStyleBuilder { // <--- notice we extend the real style builder, not the abstract class
buildStyles(input: string): StyleDefinition {
input = input || NEW_DEFAULT; // <--- set this here or in a const variable
return super.buildStyles(input); // now send this off to the main style builder for processing
}
}
This feature provides developers with complete control to intercept and override or enhance injected styles.
-
Quick Links
-
Documentation
-
Demos
-
StackBlitz Templates
-
Learning FlexBox
-
History
-
Developer Guides
-
Contributing