Nativescript Render Component after the page has loaded - javascript

I am trying to add WikitudeArchitectView to my typescript code, I registered the element to the main.ts typescript file:
var architectView = require("nativescript-wikitudearchitectview");
registerElement("ArchitectView", () => architectView.ArchitectView);
in the XML file i have added the ArchitectView element tag:
<StackLayout>
<ArchitectView urlString="http://10.20.30.79:8888" urlLoaded='urlLoaded' urlLoadError='urlLoadError' urlInvoked='urlInvoked'>
</ArchitectView>
</StackLayout>
when i run the code on my Device i get the error
So I think i need to find a way to render the after the page has loaded (maybe using ngOnInit) i dont know how to do this

Hey you can achieve to render after the page has loaded by using ngAfterViewInit.I am also writing the code for ngOnInit.
Here is the bit of code to help you.
import { Component, ElementRef,AfterViewInit, OnInit, ViewChild } from "#angular/core";
export class DuesComponent implements OnInit AfterViewInit { }
ngAfterViewInit() {
<Write your logic inside this funtion>
}
ngOnInit() {
}

Related

Angular 5 - Loading Script After View Is Loaded

I have a legacy script that I need to include in my angular application.
The thing about this script is that it relates to a specific component, and it has to be loaded only after the view of the component is loaded.
As for today, I succeeded to include it on OnInit function but sometimes (not always for some reason) the CLI throws an error about it.
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-player-page',
templateUrl: './player-page.component.html',
styleUrls: ['./player-page.component.scss']
})
export class PlayerPageComponent implements OnInit {
public itemId: string;
constructor() {}
ngOnInit() {
//We loading the player srcript on after view is loaded
require('assets/scripts/player/player.js');
}
}
The script assumes that elements in the UI exists and it searches them by the id.
When adding it on top of the page, it doesn't work.
What is the best way to achieve the desired behavior?
There are multiple solutions to this issue.
declare the require const on top of your component
declare const require: any;
import { Component, OnInit } from '#angular/core';
#Component({})
...
use the dynamic import() function from typescript
ngAfterViewInit() {
//We loading the player script on after view is loaded
import('assets/scripts/player/player.js');
}
change the library to only start running after you call a function from the component, this way you can add it to the scripts array of your angular.json

Cannot read property of undefined #ViewChild not working Angular 5

I'm having a bit of trouble I cant seem to figure out why my #ViewChild isnt working..
Basically I want to call a function in one component from another component so in my sidebar component I have a function called sendData() and I want to be able to call that from a button click in my header component so what Ive done is..
Sidebar component
import { Component, OnInit, Input, OnChanges, SimpleChanges, AfterViewInit } from '#angular/core';
import * as _ from 'lodash';
#Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.scss']
})
export class SidebarComponent implements OnInit, OnChanges {
constructor(
private contenfulService: ContentfulService,
private userService: UserService
) { }
ngOnInit() {
}
sendData(){
...do something
}
}
header.component.ts
import { Component, OnInit, Input, ViewChild, EventEmitter } from '#angular/core';
import { UserService } from '../../../user.service';
import { SidebarComponent } from '../sidebar/sidebar.component';
#Component({
selector: 'app-program-header',
templateUrl: './program-header.component.html',
styleUrls: ['./program-header.component.scss']
})
export class ProgramHeaderComponent implements OnInit {
#ViewChild(SidebarComponent) sidebar;
constructor() { }
ngOnInit() {
}
}
header.component.html
<div (click)="sidebar.sendData()"></div>
but it isnt working Im getting this error in the console...
ERROR TypeError: Cannot read property 'sendData' of undefined
I have removed code for brevity, so please let me know if there is more information you need
Im not sure what the problem is?
EDIT
Or if anyone knows another way to call a function from a seperate component let me know
Any help would be appreciated!
Thanks!
ViewChild is expected to be used to get target element from current component's view(template) which matches the selector.
But according to your comment above, it seems there is no app-sidebar placed in your header.component.html, so ViewChild is not able to get a valid element which results in your current error.
The solution should be place app-sidebar at least once.
<app-sidebar></app-sidebar>
<div (click)="sidebar.sendData()"></div>
If header and sidebar components are siblings, you can not pass data between them directly. Take a look at ‘Output’ and ‘Input’ from angular. Alternatively, you can use a Service to pass data between components. Check out services and observables.
<parent>
<app-program-header>
</app-program-header>
<app-sidebar>
</app-sidebar>
</parent>
Just as an addition to this conversation, I have been squirreled off on a couple of occasions chasing what seemed to be the lack of a functioning #ViewChild when the cause was the #ViewChild referencing a component in a module that was not being imported. The "cannot read property of undefined" can become extremely misleading and may not be related to #ViewChild at all; be sure to check your imports first.
In my case - it was the import from "#shared" which has caused this issue. You have to pay attention, that the component you are using the #ViewChild component reference is not in the same module with same shorthand path. If it is, import the #ViewChild component from
'shared/components/sidebar/sidebar.component'
and not from '#shared'

I want to attached an Angular2 Component to a newly added DOM

I want to bind an Angular2 Component to a newly added dom.
What happen is: <my-app> tag is not updated with <h1>My First Angular App</h1>. With the code below, having a small DOM, my-app tag contains <h1>My First Angular App</h1>, but with huge DOM, it didn't, I only see my-app tag.
Here is my code:
Component.TS
import { Component } from "#angular/core";
#Component({
selector: "my-app",
template: "<h1>My First Angular App</h1>"
})
export class AppComponent { }
Main.TS
import { platformBrowserDynamic } from "#angular/platform-browser-dynamic";
//APPModule not included on this post, same as the quickstart
import { AppModule } from "./app.module";
interface MyWindow extends Window {
displayApp(): void;
}
declare var window: MyWindow;
window.displayApp = function displayApp() {
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);
}
Some Javascript Code
//adding the selection component dom.
document.getElementById('main-content').appendChild(document.createElement('my-app'));
//do ajax call then on success
window.displayApp();
Having a full angular approach is not an option here because there are existing ui component based on other technology, and we are exploring angular on other components.

How to load script file from component html?

Basically I wanted to load component html specific script file, so that script I'm going to put script file reference inside component html itself, I'm seeing that inner script file has been ignored while rendering component html on page.
Component
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: 'test.html'
})
export class AppComponent { }
test.html
<div>
<h1>My First Angular 2 App</h1>
</div>
<script src="test.js"></script>
Above is my code what I tried & I already have test.js there in place.
Plunkr Here
Is there any way to load component specific javascript file with component OR with its html?
Working Plunker
Security
It looks like Angular takes out script tags from Html templates.
From the Angular Docs:
It removes the <script> tag but keeps safe content, such as the text content of the <script> tag
Angular provides methods to bypass security, but for your use case it looks like a service would be helpful.
Services
The preferred way to include your own custom script in your component from a separate dedicated file would be to create a service.
I took the code from your Plunker's script.js file and put it into a service like this:
// File: app/test.service.ts
import { Injectable } from '#angular/core';
#Injectable()
export class TestService {
testFunction() {
console.log('Test');
}
}
Then I imported the service and called the custom code like this:
// File: app/app.component.ts
import { Component, OnInit } from '#angular/core';
import { TestService } from './test.service';
#Component({
selector: 'my-app',
templateUrl: 'test.html',
providers: [TestService]
})
export class AppComponent implements OnInit {
constructor(private testService: TestService) {}
ngOnInit() {
this.testService.testFunction();
}
}
Lifecycle hooks
If you want to call your service's custom code at a specific point you can take advantage of lifecycle hooks. For example you can call your code using the ngAfterViewInit() instead of ngOnInit() if you want to wait until the view has loaded.

In NativeScript with Angular, how can I get an interface element the id?

I'm trying to avoid unexpected behavior in a NativeScript application.
When I walk into any screen that has a search field (SearchBar) system puts the focus on the search field automatically.
Then I got help with a friend who gave me a function to solve this problem. But the problem I'm facing right now is that I can not get the interface element. I have the following code:
import {Component} from "#angular/core";
import {Page} from "ui/page";
import frame = require("ui/frame");
#Component({
selector: "clientes",
templateUrl: "pages/clientes/clientes.html",
styleUrls: ["pages/clientes/clientes.common.css",
"pages/clientes/clientes.css"]
})
export class ClientesPage {
page;
constructor(private _router: Router) {
this.page = <Page>frame.topmost().currentPage;
this.removeSearchFocus();
}
removeSearchFocus() {
var parent = this.page.getViewById('box-lista');
var searchBar = this.page.getViewById('barra-busca');
console.log(JSON.stringify(parent)); // UNDEFINED
console.log(JSON.stringify(searchBar)); // UNDEFINED
if (parent.android) {
parent.android.setFocusableInTouchMode(true);
parent.android.setFocusable(true);
searchBar.android.clearFocus();
}
}
}
And then I have the template:
<Page.actionBar>
<ActionBar title="Clientes"></ActionBar>
</Page.actionBar>
<StackLayout orientation="vertical" id="box-lista">
<SearchBar hint="Buscar" cssClass="mh mv" id="barra-busca"></SearchBar>
</StackLayout>
My goal is to get the auto focus of the search field, but I can not get the interface element.
to expand on Nikolay's answer above this to use #ViewChild add #foo to your stack layout so it looks like:
<StackLayout #foo ....
then:
#ViewChild('foo') stackLayout: ElementRef;
ngAfterViewInit() {
let yourStackLayoutInstance = this.stackLayout.nativeElement;
}
it won't get the element by ID but this is the more ng2 way of interacting with elements and keeps your code more loosely coupled to the DOM.
To get element in your project you should use #ViewChild decorator, which will help you to create new property that point at the SearchBar. In regard to that you could review my project here and also to review this article: Building Apps with NativeScript and Angular 2

Categories