Jamie Birch
Jamie Birch

Reputation: 6112

How do I initialise a NativeScript app fully programmatically (without XML)?

Here's what I have so far. The background goes green (the colour of the Page), but I'd expect a purple ContentView with some text inside to fill the page, too.

Is there anything further I'm missing?

import { on, run, launchEvent } from "tns-core-modules/application";
import { Frame } from "tns-core-modules/ui/frame/frame";
import { ContentView } from "tns-core-modules/ui/content-view/content-view";
import { TextBase } from "tns-core-modules/ui/text-base/text-base";
import { Page } from "tns-core-modules/ui/page/page";

on(launchEvent, (data) => {
    const frame = new Frame();
    const page = new Page();
    page.backgroundColor = "green";

    const contentView = new ContentView();
    const textBase = new TextBase();
    contentView.height = 100;
    contentView.width = 100;
    contentView.backgroundColor = "purple";
    textBase.text = "Hello, world!";
    contentView._addView(textBase);
    page.bindingContext = contentView;

    frame.navigate({ create: () => page });

    data.root = page; // Incidentally, should this be the frame or the page?
});

run();

Upvotes: 3

Views: 313

Answers (3)

ych
ych

Reputation: 2075

It seems to me that you try to overcomplicate. You can replace XML with code just by implementing createPage method - Create a page via code.

I just modified default NS + TypeScript Playground template to operate without XML - NS + TypeScript template without XML.

Upvotes: 1

Manoj
Manoj

Reputation: 21908

You are almost on track, you just need slight modification on your code.

import { on, run, launchEvent } from 'tns-core-modules/application';
import { Frame } from 'tns-core-modules/ui/frame/frame';
import { ContentView } from 'tns-core-modules/ui/content-view/content-view';
import { TextField } from 'tns-core-modules/ui/text-field';
import { Page } from 'tns-core-modules/ui/page/page';

run({
    create: () => {
        const frame = new Frame();
        frame.navigate({
            create: () => {
                const page = new Page();
                page.backgroundColor = "green";

                const contentView = new ContentView();

                const textField = new TextField();
                contentView.height = 100;
                contentView.width = 100;
                contentView.backgroundColor = "purple";
                textField.text = "Hello, world!";

                contentView.content = textField;
                page.content = contentView;

                return page;
            }
        });
        return frame;
    }
});
  1. You don't have to wait for launch event, you could set the root frame in run method itself.
  2. In your code, you were creating the frame but never adding it to root UI element or mark the frame itself as root element
  3. It's recommended to use .content to add child for a ContentView / Page as they are originally designed to hold one child element only.
  4. Use TextField / TextView for input text, TextBase is just a base class.

Upvotes: 4

Narendra
Narendra

Reputation: 4574

I think you can't leave run as empty as it is expecting an entry to start the app. From {NS} website,

You can use this file to perform app-level initializations, but the primary purpose of the file is to pass control to the app's root module. To do this, you need to call the application.run() method and pass a NavigationEntry with the desired moduleName as the path to the root module relative to your /app folder.

if you look for run code in "tns-core-modules/application"

function run(entry) {
    createRootFrame.value = false;
    start(entry);
}
exports.run = run;

and

function start(entry) {
    if (started) {
        throw new Error("Application is already started.");
    }
    started = true;
    mainEntry = typeof entry === "string" ? { moduleName: entry } : entry;
    if (!androidApp.nativeApp) {
        var nativeApp = getNativeApplication();
        androidApp.init(nativeApp);
    }
}

Upvotes: 0

Related Questions