Custom render services
See original GitHub issueCustom Render Services
Custom render services are services that live on the render layer and are accessible via an interface on the app layer. We already have two of these services, RenderCompiler
and Renderer
, but users should be able to create their own.
For the WebWorker scenario, the idea so far was to create manual proxy/stubs for the RenderCompiler
and the Renderer
to be able to communicate between the processes. To allow a user to create their own render services, it would be great if Angular provided a general RPC mechanism that allows to generate client and services given an interface automatically.
This proposal supersedes custom renderers
Example
Wrapping the JQuery UI Dialog widget. Note that only the directive is specific to the ui dialog, the service can be used for wrapping any other JQuery widget:
@Directive({
properties: ['closeText'],
events: ['close'],
exportAs: 'jqDialog',
lifecycle: ['onDestroy']
})
class JQueryDialogDirective {
close:EventEmitter;
subscriptions:[];
closeText:string;
constructor(public renderer:JQueryRenderer, public element:ElementRef) {
this.renderer.create(this.element, 'dialog', {});
this.subscriptions.push(
this.renderer.listen(this.element, 'close').observer(this.close)
);
}
set closeText(value:string) {
this.renderer.setOptions(this.element, 'dialog', {'closeText': value});
}
// TODO: allow directives to continue living over hydrate/dehydrate
onDestroy() {
this.subscriptions.forEach( (subscription) => {
subscription.unsubscribe();
});
this.renderer.call(this.element, 'dialog', 'destroy');
}
open() {
this.renderer.call(this.element, 'open');
}
close() {
this.renderer.call(this.element, 'close');
}
}
class JQueryRenderer {
// will do `$(el)[widgetName](options)`
create(element:ElementRef, widgetName:string, options:StringMap):Observable {}
// will do `$(el)[widgetName]('option', options)`
setOptions(element:ElementRef, widgetName:string, options:StringMap):Observable {}
// will do `$(el).on(event)`
listen(element:ElementRef, event:string):Observable {}
// will do `$(el)[widgetName](methodName)`
call(element:ElementRef, widgetName:string, methodName:string):Observable {}
}
class DomJQueryRenderer implements JQueryRenderer {}
Other examples would be a RulerService
, CookieService
, LocationService
.
Why?
- we don’t want to have an injector per element on render side as well for perf and simplicity reasons. The consequence is that custom render logic needs to be encapsulated into singleton services
- restricting custom render logic to only use setting properties, calling actions and listening to events as means of communication with the app side is very restrictive.
- allowing custom render logic this just a generalization of our
RenderCompiler
andRenderer
, i.e. it does not add new abstractions / primitives to Angular
TODO: discuss why not use render directives
- can’t reference them from app side, but compiler should not take configuration other than the root component
Restrictions to the interface of custom render services
- a render service can’t call an app service
- every method must either be
void
, return aPromise
or anObservable
(e.g. events). - Angular should provide hooks to allow users to marshal any object
- We might have 2 interfaces, one for the app side that uses
ElementRef
and one for the render side that gets the dom element with Angular automatically unwrapping theElementRef
into a DOM element and vice versa.
Implications
- DOM elements should not be referenced in directives, only in render services
- Rename
Renderer
intoRenderViewManager
, as it is only used by theAppViewManager
and to signal that it is no so special any more, as users can write their own render services.
Potential later changes
- allow directives on the app side to implement their own hydrate/dehydrate and to survive hydration.
Non webworker scenario
- In dev mode: enforce that all parameters given to a render service are serializable
- TODO: same injector or separate injectors?
Webworker scenario
TODO: Show how to register custom render services in WebWorker scenario
To be discussed
Issue Analytics
- State:
- Created 8 years ago
- Reactions:1
- Comments:12 (11 by maintainers)
Is there any update on this?
@mhevery yes, still relevant. We need this!