Description
Is your feature request related to a problem? Please describe.
Currently angular components cannot be styled through XML attributes nor do they have a representation in the UI tree (e.g. <my-component backgroundColor="red" paddingTop="10">
). To overcome this and other limitations, Angular components are frequently wrapped either outside or inside in some kind view container (StackLayout
is perhaps the most common).
Describe the solution you'd like
A custom component annotation (either as a replacement or complementary to Angular's @Component
) i.e. @NativeScriptComponent
which allows the developer to provide a viewClass
property to specify which Nativescript view to use for a given component.
Describe alternatives you've considered
Alternatively to the component annotation, one can use registerElement('my-component-selector', () => StackLayout)
to manually associate the Angular component with a UI view.
Additional context
PoC for the custom component annotation and use-case:
function NativeScriptComponent(meta: Component & { viewClass: ViewClass }) {
const viewClass = meta.viewClass;
delete meta.viewClass;
const componentMeta = meta as Component;
const ngComponentDecorator = Component(componentMeta);
return function<T extends { new(...args:any[]): {} }>(constructor: T) {
ngComponentDecorator(constructor);
if (!isKnownView(componentMeta.selector)) {
registerElement(componentMeta.selector, () => viewClass);
} else {
console.warn(`Component with selector ${componentMeta.selector} is already registered`);
}
}
}
Component declaration:
@NativeScriptComponent({
moduleId: module.id,
viewClass: StackLayout,
selector: 'nativescript-component',
template: '<Label text="Hello, World"></Label>',
host: {
'class': 'm-10 p-10'
},
})
export class TestComponent implements OnInit {
constructor(private elementRef: ElementRef) {
// elementRef.nativeElement is a StackLayout
}
}
Usage:
<!-- app.component.html -->
<nativescript-component backgroundColor="red"></nativescript-component>
Additional Notes
- This way of overriding the
@Component
annotation might not be supported across all versions of Angular. This was tested with Angular 6. Host propertiesIt does.@Component({ host: { 'borderColor': 'red' }, ... })
do not seem to work.registerElement
is global while the component is scoped to the module where it is declared and, when exported, the modules that import the declaring module. This means that two components with the same name declared on different modules would clash in theregisterElement
phase.