I wish to generate a Table of Contents ( ToC ) by parsing the HTML that is already present in the templateUrl of my component.
This is my component.ts :
#Component({
selector: 'app-presentation',
templateUrl: './presentation.component.html',
styleUrls: ['./presentation.component.css']
})
export class PresentationComponent implements OnInit {
public toc = '';
constructor() { }
ngOnInit(): void {
// parse tempalteUrl here
// set the this.toc variable
}
}
and this is my component.html :
<div class="container">
<div class="row">
<div class="col-sm-4">
{{toc}}
</div>
<div class="col-sm-8">
<h1>Title</h1>
<h2>Sub Title1</h2>
<p>some text</p>
<h2>Sub Title2</h2>
<p>more text</p>
<h1>Title2</h1>
<h2>Sub Title3</h2>
<p>random text</p>
<h2>Sub Title4</h2>
<p>extra text</p>
</div>
</div>
</div>
What I wish to do is to extract all of the and children and then use them to generate the ToC.
Only <div class="col-sm-8"> has the elements I am interested in
All <h1> are direct children of that div
All <h2> are direct children of a <h1>
The aim of what I am trying to do is have as little HTML as possible to edit at each update when I want to change the content of my website.
Couple ways I can think of are inject ElementRef if just reading whole HTML doc, Renderer2 if going to modify HTML and output in ngOnInit(); add template ref and read ViewChild in ngAfterViewInit()
<div #toc class="col-sm-8">...</div>
import { Component , ElementRef, ViewChild } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
#ViewChild('toc') toc: ElementRef;
constructor(private elRef: ElementRef) {}
ngOnInit() {
console.log(this.elRef.nativeElement.innerHTML);
}
//template ref + viewChild
ngAfterViewInit() {
console.log(this.toc.nativeElement.innerHTML);
}
}
Related
Can't figure out why the columns aren't being structured with this HTML component:
<div class="container">
<div class="row">
<div class="col-6">
<p>Some text</p>
</div>
<div class="col-6">
<p>Some text</p>
</div>
</div>
</div>
if i use col-someNumber, it does not work
columns displaying incorrectly
But if i use the class 'col', it works.
columns displaying correctly
this is my component.ts
import { Component, OnInit } from '#angular/core';
import { Product } from '../model/product.model';
import { ProductService } from './product.service.component';
#Component({
selector: 'app-products',
templateUrl: './product.component.html',
styleUrls: ['./product.component.css', '../../../node_modules/bootstrap/dist/css/bootstrap.min.css']
})
I need one columns smaller than the other, that's why i don't use '.col'.
'.col-' should do the work.
I also replaced my html with multiple bootstrap .col- examples, but none seems to work
<div class="loader-wrapper ">
<div class="loader is-loading"></div>
</div>
Loader image
I want to to increase the size of the loader without added anything in CSS!
<img src="your_image.jpg" width="500" height="600">
in component
import {
Component,
OnInit,
ViewChild,
ElementRef,
ViewEncapsulation
} from '#angular/core';
#Component({
selector: 'app-loading',
template: `
<div #loaderWrapper class="loader-wrapper ">
<div class="loader is-loading"></div>
</div>
`,
encapsulation: ViewEncapsulation.None
})
export class CustomComponent implements OnInit {
#ViewChild('loaderWrapper') loaderWrapper: ElementRef;
ngOnInit() {
this.loaderWrapper.nativeElement.style.with = 500;
this.loaderWrapper.nativeElement.style.height = 500;
}
}
app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
serverElements :[{type:"blueprint",name:"abnc",content:'Just A Test'}];
}
app.component.html
<div class="container">
<div class="row">
<div class="col-xs-12">
<app-server-element *ngFor="let serverElement of serverElements" [childElement]="serverElement">abc</app-server-element>
</div>
</div>
</div>
src-->app-->server-element
server-element.component.ts
import { Component, Input, OnInit } from '#angular/core';
#Component({
selector: 'app-server-element',
templateUrl: './server-element.component.html',
styleUrls: ['./server-element.component.css']
})
export class ServerElementComponent implements OnInit {
#Input('childElement') element:{type:string,name:string,content:string};
constructor() { }
ngOnInit(): void {
}
}
server-element.component.html
<div class="panel panel-default">
<div class="panel-heading">Hello</div>
<div class="panel-body">
<p>
<strong *ngIf="element.type ==='server' " style="color: red;"> {{ element.content }}</strong>
<em *ngIf="element.type==='blueprint'"> {{element.content}} </em>
</p>
</div>
</div>
it should iterate single serverElements by <app-server-element *ngFor> . But it isnt doing ,although the course which i am folowing(Maximilian Schwarzmuller) code works fine .. Help
you missed the assignment of serverElements. It should have some value, you just declare the type.
app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
// assign the value, you declare it as type but it was emplty
serverElements = [
{ type: "blueprint", name: "abnc", content: "Just A Test" }
];
}
I'm trying to communicate between two components, but my #Output() doesn't seem to be working when a button is clicked. Accessing the function is not the issue as I can get a response from the console.
child-comp.component.html:
<div class="container" style="text-align: center" style="padding-top: 10px">
<label>The Child text is: {{goodbye}} </label>
<p></p>
<p>The parent input is : {{state}} </p>
<button class="primary" (click)='sendToParent()'>Send to Parent</button>
</div>
parent-comp.component.html:
<div class="container" style="text-align: center" style="padding-top:
10px">
<label>The Parent text is: {{hello}}</label>
<p></p>
<p>The Child input is : {{goodbye}} </p>
</div>
<hr>
<app-child-comp [state]="hello" (event)="setDataFromChild()"></app-child-
comp>
child-comp.component.html:
<div class="container" style="text-align: center" style="padding-top:
10px">
<label>The Child text is: {{goodbye}} </label>
<p></p>
<p>The parent input is : {{state}} </p>
<button class="primary" (click)='sendToParent()'>Send to Parent</button>
</div>
child-comp.component.ts:
import { Component, OnInit, Input, Output, EventEmitter} from
'#angular/core';
#Component({
selector: 'app-child-comp',
templateUrl: './child-comp.component.html',
styleUrls: ['./child-comp.component.css'],
})
export class ChildCompComponent implements OnInit {
#Input() public state: string;
#Output() event: EventEmitter<string> = new EventEmitter();
public goodbye = 'goodbye';
constructor() { }
ngOnInit() {
}
sendToParent() {
this.event.emit(this.goodbye);
}
}
parent-comp.component.ts:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-parent-comp',
templateUrl: './parent-comp.component.html',
styleUrls: ['./parent-comp.component.css']
})
export class ParentCompComponent implements OnInit {
public hello = 'hello';
public goodbye: string;
constructor() { }
ngOnInit() {
}
public setDataFromChild(data) {
this.goodbye = data;
console.log('event emitted');
}
}
You dont take data comming from EventEmitter:
Change this:
(event)="setDataFromChild()"
To:
(event)="setDataFromChild($event)"
I have 3 components in angular 2 application.The class="container-fluid content" is css class in app.component.html. This class="container-fluid content" is default css for other components. Now I want to set background-color:blue in the detail component. I tried to set in detail.component.ts like this styles:['.container-fluid content{background-color: blue;}'] It did not work. If I set in app.component.html like this <div class="container-fluid content" style="background-color: blue;"> It applies to both the components. How to override this class="container-fluid content" in detail component?
//my project structure
app
- app.component.html
-app.component.ts
- welcome
-welcome.component.html
-welcome.component.ts
- detail
-detail.component.html
-detail.component.ts
//app.component.html
<div class="container-fluid content">
<router-outlet></router-outlet>
</div>
<app-footer></app-footer>
</div>
//welcome.component.html
<h1>welcome page heading</h1>
<div fxLayout="row" fxLayoutWrap style="padding-bottom: 25px;
padding-top: 25px; margin: auto;justify-content: center" >
<md-card>
<md-card-content>
<h1></h1>
<h2></h2>
<h2>
</h2>
</md-card-content>
</md-card>
</div>
//detail.component.html
<h1>Details page heading</h1>
<div fxLayout="row" fxLayoutWrap style="padding-bottom: 25px;
padding-top: 25px; margin: auto;justify-content: center" >
<md-card>
<md-card-content>
<h1></h1>
<h2></h2>
<h2>
</h2>
</md-card-content>
</md-card>
</div>
//detail.component.ts
import { OnInit, Component } from '#angular/core';
import { DetailService } from '../detail/detail.service';
import { HostBinding} from '#angular/core';
#Component({
providers: [DetailService ]
templateUrl: './detail.component.html',
styles: ['h3 {margin:5px}']
})
export class DetailComponent implements OnInit {
#HostBinding('class.blueClass') blue: boolean = false;
constructor( private _detailService: DetailService ) { }
ngOnInit() {
this.blue = true;
}
}
In child component, you can add this param to #Component.
// child-component.component.ts
#Component({
selector: 'child-component',
templateUrl: 'child-component.component.html',
styleUrls: ['child-component.component.css']
encapsulation: ViewEncapsulation.None
})
// child-component.component.css
.container-fluid content{background-color: blue;}
You can ref this side for more infomartion :
https://blog.thoughtram.io/angular/2015/06/29/shadow-dom-strategies-in-angular2.html
Have you tried with the hostbinding and adding a new class there?
#HostBinding('class.blueClass') blue: boolean = false;
And in the second component just switch that on onInit?
ngOnInit() {
this.blue = true;
}
The other way could be in the component definition, you can add the following line :
host: {'class': 'blueClass'}
and you do the rest of the css work in css instead.