I'm trying to build a dynamic component, I need to create an ng-content for each language :
<div *ngFor="let locale of locales" [hidden]="selected!=locale.code" class="filed-content">
<ng-content #select="{{'[locale-'+locale.code+']'}}"></ng-content>
</div>
But they are created within a div:
Stackblitz
Related
I am trying to display two seperate d3 pie charts on my webpage in two seperate mat-cards, but they display in the svg tag of the first d3 chart in my code.
My code:
<section class="three">
<!-- Card 1 -->
<div fxLayout="row" fxLayoutGap="10px">
<mat-card class="child-card">
<mat-card-content class="card-grid">
<app-d3-donut class="card-grid-graph"></app-d3-donut>
</mat-card-content>
</mat-card>
<!-- Card 2 -->
<mat-card class="child-card">
<mat-card-content class="card-grid">
<app-apex [type]="'type1'" class="card-grid-graph"></app-apex>
</mat-card-content>
</mat-card>
<!-- Card 3 -->
<mat-card class="child-card">
<mat-card-content class="card-grid">
<app-d3-donut class="card-grid-graph"></app-d3-donut>
</mat-card-content>
</mat-card>
</div>
</section>
Both my d3 charts as I have configured in my app-d3 component display in the first card like this;
Is this because I have configured my d3 chart wrong or some other reason?
The problem is definitely that you use d3.select('svg') or d3.select('app-d3-donut') in your custom component. d3.select is a wrapper around document.querySelector, which matches the first element it finds.
You need to make sure that this is not the first SVG element as seen from the document, but the first element as seen from the custom component. That is - you need to make sure that each Angular component can only look at and modify its own inner HTML.
From the source, d3.select also accepts HTML elements. So you should use Angular's ViewChild to get a the reference to the SVG element, and then pass that reference to d3.
#Component({
selector: 'app-d3-donut',
template: `
<svg #chartEl></svg>
`
})
class AppD3DonutComponent {
#ViewChild('chartEl') svgElement: ElementRef;
ngAfterViewInit() {
d3.select(this.svgElement.nativeElement).append('g') // etc
}
}
The following code is a component that i need to inject in other components:
<div class="row">
<div class="col-12 [...]" *ngFor="let course of courses">
<div class="card">
[...]
</div>
</div>
</div>
The problem is that in one of the components it is injected in, I need to apply a | slice:0:4 in the ngFor to display less data. For this reason, I modified the child component and made it so the data from the parent components is sent to the child component. So I removed the .row and .col-12 divs and put it into the parent components, this way I can use the slice only in the parent component I need to.
<div class="row">
<div class="col-12 [...]" *ngFor="let course of courses | slice:0:4">
<app-child-component [course]="course"></app-child-component>
</div>
</div>
Child component now is like this:
<div class="card">
[...]
</div>
The problem now is that I need to apply CSS classes to the child component's .row that must be visible everywhere but this way I have to modify every single parent component's .row, so more useless code. I also assume this way I'm not using Angular's components concept the way it is meant to.
Is there a way to use | slice and kind of "send it" from a single parent component to the child component like i'm doing now with [corso]="corso" in <app-component [corso]="corso"></app-component>?
Hoping I explained this well. Thank you.
//Child component ts
#Input() sliceStart = 0; //default to `0` if not passed
#Input() sliceEnd = 4; //default to `4` if not passed
courses = ['HTML', 'CSS', 'Javascript', 'Angular'];
<!-- Child component html -->
<div *ngFor="let course of courses | slice: sliceStart:sliceEnd">
{{course}}
</div>
<!-- Parent component html -->
<app-child-component [sliceEnd]="2"></app-child-component>
Stacblitz example
I've got a child component (that I cannot edit) where each row in an object is rendered inside a div with a specific slot, and I'd need to pass data from the parent for each of those elements. I'm trying to iterate through every element of the object in the parent component, generate a slot and pass the desired code to the child, but unfortunately I can't manage to and I can't find any material to support me.
The child component:
<div class="slotchildren" v-for="(child, childindex) in row.elementChildren" :key="childindex">
<span>element nr. {{child.id}}</span>
<slot :name="`element-child-${row[idlabel]}-${childindex}`" :row="child">
...
</slot>
</div>
The parent component (not working):
<template v-for="row in rows"> -->
<template v-slot:`element-row-${row.id}`="{row}">
//--> [vue/valid-v-slot] 'v-slot' directive doesn't support any modifier
//--> [vue/valid-v-slot] 'v-slot' directive must be owned by a custom element, but 'template' is not.
<span>{{row.name}}</span>
</template>
</template>
Is something like this feasible and how? If it's not, what could be a viable workaround, consideind that I can't edit the child component?
Thanks in advance.
I solved it with the following synthax:
<template v-for="row in rows" v-slot:[`element-row-${row.id}`]>
..
</template>
I have two angular components whose respective templates are called home.component.html and information-icon.html.
I am using custom HTML elements, so when I define my custom elements together only in one template, for example in home.component.html, the template shows correctly elements defined:
<!-- home.component.html-->
<sh-access-bar label="Access bar">
<sh-button icon="example.png"></sh-button>
</sh-access-bar>
Nevertheless, I need two separate components to my purpose, so If I defined both templates like this, the component doesn't render correctly:
First component:
<!-- home.component.html-->
<sh-access-bar label="Access bar">
<app-information-icon></app-information-icon> <!--Component selector-->
</sh-access-bar>
Second component:
<!--information-icon.component.html-->
<sh-button icon="example.png"></sh-button>
Are there any way in Angular to render both components correctly?
Are there any properly way to create custom tags dynamically as a component?
I will appreciate any kind of help.
let's say I've got the following basic component with two slots:
// my-component.component.ts
#Component({
selector: 'my-component',
template: `
<div class="my-component">
<div>
Title:
<ng-content select="my-component-title"></ng-content>
</div>
<div>
Content:
<ng-content select="my-component-content"></ng-content>
</div>
</div>`
})
And into the second slot ('my-component-content') I want to insert regular Angular 2 component...
<div class="app">
<my-component>
<div class="my-component">
<div>
Title:
<my-component-title>
This is the Component title!
</my-component-title>
</div>
<div>
Content:
<my-component-content>
<some-regular-angular2-component></some-regular-angular2-component>
</my-component-content>
</div>
</div>
</my-component>
</div>
Where 'some-regular-angular2-component' is a selector of some Angular 2 component...
#Component({
selector:'some-regular-angular2-component'
})'
Problem is that 'some-regular-angular2-component' is never transcluded into ng-content second slot...Only regular HTML works for me...Of cource I tried to set 'some-regular-angular2-component' into [directives] of parent component, but Angular 2 component is not recognized inside of the ng-content...Or does this work for you?
You need to add <ng-content></ng-content> to the view (template) of <my-component-content> If <my-component-content> doesn't support transclusion, its children won't be shown. The <ng-content> tags in your code apply only to elements that match directly, but not their children.
Just to answer my question, yes, angular 2 transclusion supports inserting of Angular 2 components. I had stupid typo in the code.
Yes it does. It is now called content projection. See this example of a modal dialog with multiple slots.