typescript - Angular 2 - Påverka alla komponenter på en sida (tredjeparts och dina egna) samtidigt


Jag har redan ställt en annan fråga, men jag ville förtydliga den här och se om det finns ett enklare sätt att uppnå effekten jag ville visa på bilden nedan.

Om jag har flera komponenter på en sida (några av dem kan ha barnkomponenter), vill jag lägga till en kant runt alla (möjligen med en färg som ändras slumpmässigt) och lägga till namnet på komponenten (eller namnet på dess selektor) i det övre högra hörnet av komponentens ruta. På detta sätt vill jag enkelt kunna identifiera komponenternas layout på min sida.

Jag har 2 frågor:

1. Vad är det enklaste sättet att uppnå detta om din sida har några egna och några tredjepartskomponenter.

2. Vad skulle vara det enklaste sättet att uppnå detta bara för dina egna komponenter?

Obs: Jag skulle vilja ha det minst påträngande sättet att uppnå detta och det vore önskvärt att kunna visa/dölja ramar och komponentnamn med en global variabel som skulle aktiveras för felsökningsändamål

Det här är effekten jag vill uppnå:

Uppdatering: Jag lägger till 2 skärmdumpar

Applikationskomponenter

Batarangle 2 vy av applikationen

Svar #1

Detta är vad jag kom fram till. Jag har bara lagt till en kant. Om någon har en kortare lösning, låt mig veta.

I princip skapade jag en direktiv som kommer att lägga till kantstil till vilken komponent som helst som är utökad med direktivet "componentcolor" med standardfärgen blå som kan ändras när direktivet deklareras.

Varje komponent som har några barnkomponenter måste lägga till: directives: [ComponentVisualizerDirective]

Detta är mycket påträngande, eftersom min tidigare lösning som är möjlig genom att ärva en bas komponentklass.

komponentvisualiserare.ts

import {Directive,ElementRef,OnInit} from 'angular2/core';

@Directive({
    selector:'[componentcolor]',
    properties: [
        'color: componentcolor'
    ]
})
export class ComponentVisualizerDirective implements OnInit
{
    private color: string = 'blue';
    constructor(private _el:ElementRef) {
    }

    ngOnInit():void {
        this._el.nativeElement.style.border = '1px solid ' + this.color;
        this._el.nativeElement.style.display = 'block';
    }

}

ansökan.html

<auction-navbar component></auction-navbar>

<div class="container">
    <div class="row">
        <!-- Left column contains only search form the style col-md-3 comes from
        Twitter Bootstrap grid system-->
        <div class="col-md-3">
            <auction-search component="green"></auction-search>
        </div>
    </div>
</div>

application.ts

import {Component} from 'angular2/core';
import NavbarComponent from "../navbar/navbar";
import SearchComponent from "../search/search";
import {ComponentVisualizerDirective} from "../../directives/componentvisualizer";

@Component({
    selector: 'auction-application',
    templateUrl: 'app/components/application/application.html',
    directives: [
        NavbarComponent,
        SearchComponent,
        ComponentVisualizerDirective]
})
export default class ApplicationComponent {
}

Svar #2

Ett mindre snyggt sätt att göra det skulle vara att bara söka efter element med ett attribut som börjar med _nghost.

Det är mindre elegant än direktivlösningen och om Angular2 bestämmer sig för att inte längre använda den attributet skulle det gå sönder, men det täcker fallet med komponenter som inte används direkt i din kod (tredjepartskomponenter som importerar andra tredjepartskomponenter).

Jag har skapat en tjänst som låter dig få tillgång till alla komponentelement som finns i dokumentets kropp.

import {Injectable} from 'angular2/core';

@Injectable()
export class ComponentDecorationService {

    public forAllComponents(action: (e: HTMLElement) => void) {

        this.highlight(document.body, action);
    }

    private highlight(element: HTMLElement | Element, action: (e: Element) => void) {

        if (element.attributes) {
            for (var j = 0; j < element.attributes.length; j++) {
                if (element.attributes.item(j).name.startsWith("_nghost")) {
                    action(element);
                }
            }
        }

        if (element instanceof HTMLElement && element.children) {
            for (var i = 0; i < element.children.length; i++) {
                this.highlight(element.children[i], action);
            }
        }

    }
}

Du kan använda det så här:

export class App {

  constructor(private ComponentDecorationService: ComponentDecorationService) {}

  ngAfterViewInit() {

    this.ComponentDecorationService.forAllComponents((e) => {
      e.classList.add('highlighted-component');
    })
  }

}