Hi, I'm trying to add a child component into StackLayout in a parent component.
Tested on: iOS Simulator 9.3
The parent's code:
import {Component, ElementRef, ViewChild} from "@angular/core";
import {Router} from "@angular/router";
import {StackLayout} from "ui/layouts/stack-layout";
import {Page} from "ui/page";
import {NestedComponentChild} from "./NestedComponentChild"
import * as builder from "ui/builder";
@Component({
selector: "NestedComponentParent",
template: `
<StackLayout #contentStack>
<Label text="Text on parent"></Label>
<Button (tap)="addChild()" text="Add child"></Button>
<NestedComponentChild></NestedComponentChild> <!-- this works -->
</StackLayout>
`,
directives: [NestedComponentChild]
})
export class NestedComponentParent {
@ViewChild("contentStack") contentStackRef: ElementRef;
constructor(private _router: Router, private page: Page) {
}
counter = 0;
addChild() {
this.counter++;
let stack = <StackLayout>this.contentStackRef.nativeElement;
let childInstance = <NestedComponentChild> builder.load({
path: "Pages/NestedComponent/NestedComponentChild",
name: "NestedComponentChild",
attributes: {
counter : this.counter
}
});
stack.addChild(childInstance); //Nothing new appeared
console.log(childInstance.counter); // correct
console.log("#children in stack: " + stack.getChildrenCount()); // does increase
}
}
The children (NestedComponentChild.ts)
import {Component, Injector, Provider} from "@angular/core";
import {View} from "ui/core/view"
@Component({
selector: "NestedComponentChild",
template: `
<Label [text]='"Child #" + counter'></Label>
`
})
export class NestedComponentChild extends View {
counter: number = 0;
}
In short, if I use the selector "NestedComponentChild" in NestedComponentParent's template, the child component (with label) appears. However, if I add it by code, the number of children of stack increases, but it (the added child component) isn't shown on screen.
Hello @fleuverouge,
There are several things to consider from your code sample.
You are trying to use NativeScript core concepts with Angular-2 which won't provide the expected results. For example, you are building a childInstance with NS builder and using stackLayout.addChild() which ae both NativeScript core concepts for which basically Angular-2 does not know how to handle.
In your NestedComponentChild you are extending View which is also unnecessary.
What you need to do is to create your project the Angular-2 way and use the Angular concepts for initializing and handling components.
For example here is how to add a child component to your stack with an angular structural directive *ngFor and ViewContainerRef (Represents a container where one or more Views can be attached).
your parent page code
import {Component, ViewContainerRef} from "@angular/core";
import {Page} from "ui/page";
import {NestedComponentChild} from "./NestedComponentChild"
@Component({
selector: "NestedComponentParent",
template: `
<StackLayout #contentStack>
<Label text="Text on parent"></Label>
<Button (tap)="addChild()" text="Add child"></Button>
<NestedComponentChild *ngFor="let idx of items" [counter]="idx"></NestedComponentChild>
</StackLayout>
`,
directives: [NestedComponentChild]
})
export class NestedComponentParent {
items = [];
counter = 0;
constructor(private page: Page, vcRef:ViewContainerRef) {
}
addChild() {
this.counter++;
this.items.push(this.counter);
}
}
your nested component code (notice the usage of Input to export the variable _counter_)
import {Component, Input} from "@angular/core";
import {View} from "ui/core/view"
@Component({
selector: "NestedComponentChild",
template: `
<Label [text]='"Child #" + counter'></Label>
`
})
export class NestedComponentChild {
@Input() counter: number = 0;
}
Hi @NickIliev,
Thank you so much for your guidance!
I had to make NestedComponentChild extend View to use the ui builder.
My idea is to add different components dynamically basing on the data fetched by the parent component (ie: if data contain properties of Type1 & Type2, components Child1 & Child2 will be added, if data contain Type3, only Child3 will be added). I won't know which components/classes will be added and their order beforehand. That's the reason why I wanted to use StackLayout.addChild() instead of html template.
I'm an iOS developer with Obj-C & Swift. Nativescript & angular2 is really new to me. So thank you so much for any advice.
(Pls excuse me for my English)
Hey @fleuverouge
There are several approaches for your scenario with Angular-2 directives.
You can use ngSwitch directive and load components based on the switch case.
Or you can create your own custom directive with its own extended logic.
For better understanding, I recommend that you take a look at this sample application which we created with NativeScript + Angular-2
In this section you can find a basic example of how to use angular directives and how to create your own custom one.
Thanks, @NickIliev. I wonder why I hadn't found that repo before. I'll dig in it.
Most helpful comment
Hello @fleuverouge,
There are several things to consider from your code sample.
You are trying to use NativeScript core concepts with Angular-2 which won't provide the expected results. For example, you are building a childInstance with NS builder and using stackLayout.addChild() which ae both NativeScript core concepts for which basically Angular-2 does not know how to handle.
In your NestedComponentChild you are extending View which is also unnecessary.
What you need to do is to create your project the Angular-2 way and use the Angular concepts for initializing and handling components.
For example here is how to add a child component to your stack with an angular structural directive *ngFor and ViewContainerRef (Represents a container where one or more Views can be attached).
your parent page code
your nested component code (notice the usage of Input to export the variable _counter_)