Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I inject a custom component from js in nativescript?

Tags:

nativescript

Suppose I create a small component that takes an input and sets a label to show it.

app/components/testComponent/testComponent.xml:

<Label id="someLabel" loaded="onLoad"/>

app/components/testComponent/testComponent.js:

exports.onLoad = args => {
    const obj = args.object;

    const label = obj.getViewById('someLabel');
    label.text = obj.someString || 'no string given';
};

Now I can use this component in any of my pages

<Page xmlns="http://schemas.nativescript.org/tns.xsd"
      xmlns:testComponent="components/testComponent">
    <StackLayout>
        <testComponent:testComponent someString="hello {N}"/>
    </StackLayout>
</Page>

This seems to be the official way to do it and it works. But is there a way to inject this component in the page using javascript only?

like image 672
Akash Avatar asked Apr 26 '16 18:04

Akash


1 Answers

Yes, the Declarative UI (i.e. xml) is actually a building system that parses the xml and generates the JS so you don't have to.

So if you wanted to manually do this you would leave your component code alone and you would change your main screen code to be like this:

<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="onLoad">
    <StackLayout id='sl'>

    </StackLayout>
</Page>

The first thing you will notice is we gave the Page a loaded event, you have to have somewhere to actually run your code to attach your component to the visual tree. The second thing we did was add to StackLayout an id; this technically isn't actually needed -- you can navigate the NS tree and find the proper StackLayout; but for simplicity adding a ID makes it a lot easier.


So the JS code in your page would be:

var builder = require('ui/builder');
var fs = require('file-system');

exports.onLoad = function(args) {
  // Get our current Page that is being loaded
  var page = args.object;

  // Find our StackLayout
  var stackLayout = page.getViewById('sl');

  // Load our JS for the component
  var path = fs.knownFolders.currentApp().path;
  var componentJS = require(path + '/components/testComponent/testComponent.js');

  // Actually have the builder build the Component using the XML & JS.
  var component = builder.load(path + '/components/testComponent/testComponent.xml', componentJS);

  // And add our component to the visual tree
  stackLayout.addChild(component);
};

I believe that because you are adding the child in the loaded event that your page loaded event in the child component will be ran, but don't hold me to that one. If it isn't then you can manually run it a the same time you are adding it...

like image 186
Nathanael Avatar answered Oct 16 '22 14:10

Nathanael