Omar Essam Omar Essam - 2 months ago 17
TypeScript Question

Nativescript Custom Components

I was following this guide to create a a nativescript custom component http://moduscreate.com/custom-components-in-nativescript/ but it's not working for me

I have a folder pages with a folder inside it called main.
main has a couple of files

main.html

<StackLayout
xmlns="http://schemas.nativescript.org/tns.xsd"
xmlns:hello="pages/helllo"
loaded="pageLoaded" >
<hello:hello/>
</StackLayout>


main.component.ts

import { Component, ElementRef, OnInit, ViewChild} from "@angular/core";
import { Page } from "ui/page";
import colorModule = require("color");
var Color = colorModule.Color;
@Component({
selector: "my-app",
templateUrl: "pages/main/main.html",
styleUrls: ["pages/main/main-common.css"]
})
export class MainComponent implements OnInit{
constructor(private page: Page) {
}

ngOnInit() {
this.page.actionBarHidden = true;
}
}


and I also have main-common.css but that's not important to show. I then have another folder inside pages called hello with just one file inside of it

hello.html

<StackLayout width="100%" height="100%" backgroundColorr="red">
<Label class ="h1" text="h1 hello world" color="black"></Label>
<Label class ="h1" text="h1 hello world" color="black"></Label>
<Label class ="h1" text="h1 hello world" color="black"></Label>
<Label class ="h1" text="h1 hello world" color="black"></Label>
<Label class ="h1" text="h1 hello world" color="black"></Label>
<Label class ="h1" text="h1 hello world" color="black"></Label>
<Label class ="h1" text="h1 hello world" color="black"></Label>
<Label class ="h1" text="h1 hello world" color="black"></Label>
<Label class ="h1" text="h1 hello world" color="black"></Label>
<Label class ="h1" text="h1 hello world" color="black"></Label>
<Label class ="h1" text="h1 hello world" color="black"></Label>
</StackLayout>


however the hello component is not showing no matter what i do i am only getting an empty screen. I also tried changing this line
xmlns:hello="pages/helllo"
in hello.html file to this
xmlns:hello="../helllo"
but i didn't get anything not even an error. can someone point out what i am doing wrong?

Answer

What you are referring as valid in NativeScript Core but won't work in NativeScript + Angular-2.

What you need instead is to create custom component the Angular-2 way. TO demonstrate you can refer to this sample where a custom item component is created. The example is also described in the documentation and it will also show you how to bind data with @Input directive for this component.

Let me guide you through the process.

1.) Create your custom component

using-item-template.component.ts

import { Component, ChangeDetectionStrategy, Input }  from "@angular/core";

@Component({
    selector: 'item-component',
    styleUrls: ["listview/using-item-template/using-item-template.component.css"],
    template: `
        <StackLayout *ngFor="let element of data.list" class="model">
            <Label [text]="element.model" class="name"></Label>
            <Label [text]="element.speed +'mph'" class="speed"></Label>
        </StackLayout>
    `
})
export class ItemComponent {
    @Input() data: any; // this way we "pass data" to our item-component
}

@Component({
    selector: 'using-item-template',
    styleUrls: ["listview/using-item-template/using-item-template.component.css"],
    templateUrl: "listview/using-item-template/using-item-template.component.html",
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class UsingItemTemplateComponent {
    public manufacturers: Array<any>;

    constructor() {
        var bugatti = [{ "model": "Bugatti Chiron", "speed": "261" }, { "model": "Bugatti Veyron Super Sport", "speed": "268" }];
        var mclaren = [{ "model": "McLaren P1", "speed": "211" }, { "model": "McLaren F1", "speed": "242" }];
        var jaguar = [{ "model": "Jaguar XJ220", "speed": 217 }];
        this.manufacturers = [{ "list": bugatti }, { "list": mclaren }, { "list": jaguar }];
    }
}

using-item-template.component.html

<StackLayout exampleTitle toggleNavButton>
    <GridLayout rows="50, *" class="example-container">
        <Label text="Top Cars" row="0" class="title" textWrap="true" horizontalAlignment="center"></Label>
        <ListView [items]="manufacturers" row="1">
            <template let-item="item">
                <item-component [data]="item" ></item-component>
            </template>
        </ListView>
    </GridLayout>
</StackLayout>

The last but also crucial part is not to forget to declare your ItemComponent in the NgModule!

main.ts

import { ItemComponent } from "./listview/using-item-template/using-item-template.component";

@NgModule({
    declarations: [
        ItemComponent, // declare the item component
        // the other components in your app
    ],
    bootstrap: [AppComponent],
    imports: [
        .....
    ],
})
class AppComponentModule { }