I have this small gridComponent:
@Component({
selector: 'moving-grid',
templateUrl: './grid.component.html',
styleUrls: ['./grid.component.css']
})
export class GridComponent {
@Input('widgets') extComponents: Array<Component>;
}
And a second testComponent
@Component({
selector: 'test',
template: `
<div #content>I say hello<li>i</li><li>u</li><button (click)="test()">click me</button> world</div>
`
})
export class TestComponent {
@ViewChild('content') content: HTMLElement;
getContent() {
return this.content;
}
test() {
console.log("test");
}
}
Now I'm trying to pass multiple instances of testComponent to the gridComponent. Therefore I have a third Component which looks like this one:
template: `
<moving-grid [widgets]="[z1,z2]">
<test class="grid-item-content-001" #z1></test>
<test class="grid-item-content-002" #z2></test>
</moving-grid>
`
Until this point, everything works like expected. But how can I render the Components from @Input in the gridComponent? My first approach was to declare a @ViewChild in the testComponent and return it with a getContent()-function. But it won't work. Can I use the ng-content directive in some way or is there a better solution?
The GridComponent looks like this. I want to display the templates of a @Input-Component inside one of the black boxes. Is it possible?
Thanks for any kind of help
The first step to passing data into an Angular component is to create a custom property to bind to. This is done via “input” binding to pass data from one component to another (typically parent to child). This custom input binding is created via the @Input() decorator!
For passing the data from the child component to the parent component, we have to create a callback function in the parent component and then pass the callback function to the child component as a prop. This callback function will retrieve the data from the child component.
This is most frequently used way of sharing data between components. It uses @Input() decorator. You can also use @Output() decorator to event pass to the parent. @ViewChild decorator allows a one component to be injected into another, giving the parent access to its properties and methods.
You should not use an @Input
to pass in the components. You can use @ContentChildren
for that and an abstract WidgetComponent
:
@Component({
selector: 'moving-grid',
template: `
<div class="widget-wrapper">
<ng-container *ngFor="let widget of widgets">
<!-- use a ngSwitchCase here for different types-->
<grid-test-widget [widget]="widget" *ngIf="widget.active && widget.type === 'test'"></grid-widget>
</ng-container>
</div>
`,
styleUrls: ['./grid.component.css']
})
export class GridComponent implements AfterContentInit {
@ContentChildren('widget')
widgets: QueryList<WidgetComponent>;
ngAfterContentInit() {
//your components will be available here
}
}
The template of your third component will stay the same, but without the [widgets]
and an added #widget
name:
<moving-grid>
<test-widget class="grid-item-content-001" #widget [active]="false"></test>
<test-widget class="grid-item-content-002" #widget></test>
</moving-grid>
Your TestWidgetComponent
which will extend an abstract WidgetComponent :
@Component({
selector: 'test-widget',
// ...
})
export class TestWidgetComponent extends WidgetComponent {
public type: string = 'test';
}
And your WidgetComponent
:
@Directive()
export abstract class WidgetComponent {
@Input()
public active: boolean;
public type: string;
}
And you'll have several grid widgets based on the type of the widget:
@Component({
selector: 'grid-test-widget',
template: `<div #content>I say hello<li>i</li><li>u</li><button (click)="test()">click me</button> world</div>`
})
export class GridTestWidgetComponent{}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With