Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending Angular 4 universal renderer

I hope someone can help with the logic on this one. I would like to modify the way angular universal injects the style for each component. Does anyone know how to extend the renderer an get the stylesheet from other place by doing an api request. I would just need an example on the renderer example and the api request I think I may figure out myself.

I am looking at this old one. https://github.com/ralfstx/angular2-renderer-example/blob/master/src/custom-renderer.ts

import {
    Injectable,
    Renderer,
    RootRenderer,
    RenderComponentType
} from '@angular/core';

export class Element {
    constructor(private nodeName: string, private parent?: Element) {

    }
    toString() {
        return '<' + this.nodeName + '>';
    }
};

@Injectable()
export class CustomRootRenderer extends RootRenderer {
    private _registeredComponents: Map<string, CustomRenderer> = new Map<string, CustomRenderer>();

    renderComponent(componentProto: RenderComponentType): Renderer {
        var renderer = this._registeredComponents.get(componentProto.id);
        if (!renderer) {
            renderer = new CustomRenderer(this);
            this._registeredComponents.set(componentProto.id, renderer);
        }
        return renderer;
    }
}

@Injectable()
export class CustomRenderer extends Renderer {

    constructor(private _rootRenderer: CustomRootRenderer) {
        super();
        console.log('CustomRenderer created');
    }

    renderComponent(componentType: RenderComponentType): Renderer {
        return this._rootRenderer.renderComponent(componentType);
    }

    selectRootElement(selector: string): Element {
        console.log('selectRootElement', selector);
        return new Element('Root');
    }

    createElement(parentElement: Element, name: string): Element {
        console.log('createElement', 'parent: ' + parentElement, 'name: ' + name);
        return new Element(name, parentElement);
    }

    createViewRoot(hostElement: Element): Element {
        console.log('createViewRoot', 'host: ' + hostElement);
        return hostElement;
    }

    createTemplateAnchor(parentElement: Element): Element {
        console.log('createTemplateAnchor', 'parent: ' + parentElement);
        return new Element('?');
    }

    createText(parentElement: Element, value: string): Element {
        console.log('createText', 'parent: ' + parentElement, 'value: ' + value);
        return new Element('text');
    }

    projectNodes(parentElement: Element, nodes: Element[]) {
        console.log('projectNodes', 'parent: ' + parentElement, 'nodes: ' + nodes.map(node => node.toString()));
    }

    attachViewAfter(node: Element, viewRootNodes: Element[]) {
        console.log('attachViewAfter', 'node: ' + node, 'viewRootNodes: ' + viewRootNodes.map(node => node.toString()));
    }

    detachView(viewRootNodes: Element[]) {
        console.log('detachView', 'viewRootNodes: ' + viewRootNodes.map(node => node.toString()));
    }

    destroyView(hostElement: Element, viewAllNodes: Element[]) {
        console.log('destroyView', 'host: ' + hostElement, 'viewAllNodes: ' + viewAllNodes.map(node => node.toString()));
    }

    setElementProperty(renderElement: Element, propertyName: string, propertyValue: any): void {
        console.log('setElementProperty', 'element: ' + renderElement, 'name: ' + propertyName, 'value: ' + propertyValue);
    }

    setElementAttribute(renderElement: Element, attributeName: string, attributeValue: string): void {
        console.log('setElementAttribute', 'element: ' + renderElement, 'name: ' + attributeName, 'value: ' + attributeValue);
        return this.setElementProperty(renderElement, attributeName, attributeValue);
    }

    listen(renderElement: Element, eventName: string, callback: Function): Function {
        console.log('listen', 'element: ' + renderElement, 'eventName: ' + eventName);
        return function () { };
    }

    listenGlobal(target: string, eventName: string, callback: Function): Function {
        console.log('listen', 'target: ' + target, 'eventName: ' + eventName);
        return function () { };
    }

    // Used only in debug mode to serialize property changes to comment nodes,
    // such as <template> placeholders.
    setBindingDebugInfo(renderElement: Element, propertyName: string, propertyValue: string): void {
        console.log('setBindingDebugInfo', 'element: ' + renderElement, 'name: ' + propertyName, 'value: ' + propertyValue);
    }

    setElementClass(renderElement: Element, className: string, isAdd: boolean): void {
        console.log('setElementClass', 'className' + className, 'isAdd: ' + isAdd);
    }

    setElementStyle(renderElement: Element, styleName: string, styleValue: string): void {
        console.log('setElementStyle', 'name: ' + styleName, 'value: ' + styleValue);
    }

    invokeElementMethod(renderElement: Element, methodName: string, args: Array<any>) {
        console.log('invokeElementMethod', 'name: ' + methodName, 'args: ' + args);
    }

    setText(renderNode: Element, text: string): void {
        console.log('setText', 'node: ' + renderNode, 'text: ' + text);
    }
}
like image 750
Chris Tarasovs Avatar asked Sep 13 '17 18:09

Chris Tarasovs


People also ask

What are the downsides of server side rendering (Angular 4 Universal)?

Although server-side rendering (angular 4 universal) brings many advantages, it does have downsides, too. Here are some of them: As the name server side rendering already suggests, a web-server is required to pre-render the pages.

What is Angular Universal and how does it work?

This guide describes Angular Universal, a technology that renders Angular applications on the server. A normal Angular application executes in the browser, rendering pages in the DOM in response to user actions.

Why Angular 4 is the new version of angular?

Because with version 4.0 of angular, angular universal got merged into the main framework. It now ships together with the core angular packages. The names of the packages are platform-server and platform-browser. Angular is now capable of running equally on most platforms. Most importantly, it can be run on a server now.

Do I need to download the Angular framework to render HTML?

But rendering that HTML now requires the full angular (core) framework to be downloaded. As we learned before, angular is also capable of running on node.js servers.


1 Answers

You can have a look at the issue for Dynamically import a stylesheet depending on the environment. So I think you can try to load dynamic style by:

  • Add dynamic component as the guide at here.
  • Or apply styles via document object as:

    export class AppComponent
    {
       title = 'Dynamic load theme';
       constructor (@Inject(DOCUMENT) private document) { }
    
       lightTheme() {
          this.document.getElementById('theme').setAttribute('href', 'light-theme.css');
       }
    
       darkTheme() {
          this.document.getElementById('theme').setAttribute('href', 'dark-theme.css');
       }
    
    }
    

Here is a simple example on Plunker.

Hope this help!

like image 180
Ha Hoang Avatar answered Oct 10 '22 19:10

Ha Hoang