Using providers instead of using a custom widget registry.
See original GitHub issueHi,
Currently A2SF uses ‘WidgetRegistry’ to provide your own custom widgets. Its possible to use the provider in a much more rigorous way to allow for a more descriptive API and to allow for more flexibility in the widget types.
There’s an interesting little quirk in Angular that actually allows you to register a component as a component and a provider. This allows you to inject in the component against a token like so:
import { DashboardWidget } from './dashboard-widget.interface';
import { DemoWidgetComponent } from './demo-widget.component';
@Component({
selector: 'example-dashboard',
template: `<div #target></div>`
})
export class DashboardComponent implements OnInit {
// where we're going to store the rendered widgets.
@ViewChild('target', {read: ViewContainerRef}) private container: ViewContainerRef;
constructor(
private resolver: ComponentFactoryResolver,
// these are our widgets. we need to have them registered as providers and as components
// on the module. This allows us to gain a reference easily to them
@Inject(DashboardWidget) private widgets: DashboardWidget[]
) {}
public ngOnInit(): void {
// this is the magic! boom! they see me creating widgets, they hating!!!
this.widgets.forEach((w) => {
// this is the bit that ties it all together. usually people pass in a reference
// to the class. you can do the same thing by passing in the constructor. its all
// the same under the hood.
const classType: Type<DashboardWidget> = <Type<DashboardWidget>> w.constructor;
// then we inject it into our dom element.
const componentFactory = this.resolver.resolveComponentFactory(classType);
this.container.createComponent(componentFactory);
});
}
}
We create our token like so:
import { Component, Type } from '@angular/core';
export abstract class DashboardWidget {
public readonly name: string;
}
and our component that extends that token:
import { Component } from '@angular/core';
import { DashboardWidget } from './dashboard-widget.interface';
@Component({
template: '<div>hello is it me youre looking for?</div>'
})
export class DemoWidgetComponent extends DashboardWidget {
public name: string = 'DummyWidget';
}
And then to wire it all up together:
import { DashboardWidget } from './dashboard-widget.interface';
import { DemoWidgetComponent } from './demo-widget.component';
import { DashboardComponent } from './dashboard.component';
@NgModule({
declarations: [
DashboardComponent,
DemoWidgetComponent
],
entryComponents: [
DashboardComponent,
DemoWidgetComponent
],
providers : [
{
provide: DashboardWidget,
useClass: DemoWidgetComponent,
multi: true
},
{
provide: DashboardWidget,
useClass: DemoWidgetComponent,
multi: true
},
{
provide: DashboardWidget,
useClass: DemoWidgetComponent,
multi: true
},
{
provide: DashboardWidget,
useClass: DemoWidgetComponent,
multi: true
}
]
})
export class DashboardModule {}
In this case I use a multi binder because I don’t distinguish between widget types. In the case of the forms you can expose an abstract class that each of the widget must adhere to. This allows a developer to see exactly what is available to them to implement and what default values will be available from the schema.
It also allows you to keep providing your default widgets but they can be selectively overridden by a developer as needed.
I use schema form quite a lot at the moment and wouldn’t mind helping to make it a bit more flexible and modular. If you like the approach and would like me to work on a pull request for this then let me know.
Issue Analytics
- State:
- Created 6 years ago
- Comments:9
Top GitHub Comments
Hey @ebrehault,
Cool. 👍 It’ll probably be early next week before I can get a preliminary pull request in for handling forms like above.
It also gives you something that I only realized today. I allows you to load different components per module due to the the hierarchical injector (if you’re not using a multi-provider).
Ill give you a shout back when I get started on the core refactorings. It will probably involve modifying the core first and then recreating the original widgets. If youve any suggestions or ideas feel free to shout.
no… this was interesting