I've got a component where I'm trying to define a function that reads through the following js file and checks if a certain string value is contained in it. How can I do it? It's path is '../../../assets/beacons.js' (from my component) and it's named beacons.js
const allBeacons = {
"RIPE": [
"84.205.64.0/24",
"84.205.65.0/24",
"84.205.67.0/24",
"84.205.68.0/24",
"84.205.69.0/24",
"84.205.70.0/24",
"84.205.71.0/24",
"84.205.74.0/24",
"84.205.75.0/24",
"84.205.76.0/24",
"84.205.77.0/24",
"84.205.78.0/24",
"84.205.79.0/24",
"84.205.73.0/24",
"84.205.82.0/24",
"93.175.149.0/24",
"93.175.151.0/24",
"93.175.153.0/24"].map(i => i.toLowerCase()),
"rfd.rg.net": [
"45.132.188.0/24",
"45.132.189.0/24",
"45.132.190.0/24",
"45.132.191.0/24",
"147.28.32.0/24",
"147.28.33.0/24",
"147.28.34.0/24",
"147.28.35.0/24",
"147.28.36.0/24",
"147.28.37.0/24",
"147.28.38.0/24",
"147.28.39.0/24",
"147.28.40.0/24",
"147.28.41.0/24",
"147.28.42.0/24",
"147.28.43.0/24",
"147.28.44.0/24",
"147.28.45.0/24",
"147.28.46.0/24",
"147.28.47.0/24"].map(i => i.toLowerCase())
}
You need to include the js file in the bundle by telling angular about it:
Open angular.json, and add the path to the "scripts" array:
"scripts": ["src/assets/beacons.js"]
In the top of your component file (before class declaration) declare the variable as global so typescript won't complain about it (the name must match to the one in the js file):
type Beacons = {/* Define type if you want */} | any
declare const allBeacons: Beacons
Now you can use it as a global variable in your app:
ngOnInit() {
console.log(allBeacons)
}
Related
I've created an angular custom element from an angular component that I want call from a normal html page.
The component requires a parameter, which works when it's called as a component from within an angular project, but I cannot figure out how to pass the parameter from the html tag to the custom element.
Current I'm trying to use:
#Input() crs: string
in the component and:
<station-info crs="btn"></station-info>
in the html tag, but the crs never makes it into the component.
What I'd like to know is the correct way to pass the parameter from the html tag to the component after it has been converted to a custom element?
I eventually worked it out, so here's my write up of how to do it:
How To Create And Use A Custom Element
Install angular elements
ng add #angular/elements
npm i --save-dev concat fs-extra
In tsconfig.json, ensure target uses es2015 or newer:
"target": "es2015",
Add the following to app.module.ts
==> Add the imports
import { Injector} from '#angular/core';
import { createCustomElement } from '#angular/elements';
==> Add the component to the bootstrap array
bootstrap: [AppComponent]
==> Change the constructor to the following:
constructor(
private injector: Injector
) {
const el = createCustomElement(AppComponent, { injector });
customElements.define('station-info', el); // <-- 'station-info' is the name of the html tag you want to use
}
ngDoBootstrap() {}
To enable parameters to be passed from the HTML tag to the custom element, do the following steps
In app.component.ts:
Accept any input parameters using #Input and change any parameters retrieved from ActivatedRoute to use the #Input variables
Note: To ensure the input variables on the HTML tag are bound to the #Input properties, you must pass the tag attribute name to the #Input method i.e. #Input('crs') (see example below)
e.g.
Delete these:
this.crs = this.activatedRouteService.snapshot.params.crs.toLowerCase();
this.stationName = this.activatedRouteService.snapshot.params.stationName.toLowerCase();
Add these (insert after export class):
#Input('crs') crs: string
#Input('stationName') stationName: string;
In ngOnInit(), navigate to the component, passing on any input parameters:
e.g.
this.router.navigateByUrl('/station-details/' + this.crs + '/' + this.stationName);
In app-routing.module.ts
Delete (so there is no automatic routing):
{ path: '', redirectTo: 'station-details', pathMatch: 'full' },
Pass any parameters on the appropriate path:
{ path: 'station-details/:crs/:stationName', component: StationDetailsComponent,
In the custom HTML tag
Add the parameters as follows:
<station-info crs="btn" station-name="Brighton" client="tl" has-template="true"></station-info>
Create a build-component.js file in the root folder with the following content
Note: dist/dev is the folder structure automatically created by the compiler
const fs = require('fs-extra');
const concat = require('concat');
build = async () =>{
const files = [
'./dist/dev/runtime.js',
'./dist/dev/polyfills.js',
'./dist/dev/scripts.js',
'./dist/dev/main.js'
];
await fs.ensureDir('station-info'); // <-- Use the same name here as in customElements.define
await concat(files, 'station-info/station-info.js'); // <-- this is where you want to save the resulting files
}
build();
Compile and concatenate the resulting files
==> Add build-component.js script to package.json
"scripts": {
"build:component": "ng build --configuration production --output-hashing none && node build-component.js",
}
==> Run the script
npm run build:component
To use the custom element, add the following to an html page
Note: You also have to ensure any external assets that the custom element requires are present e.g. images and files
If you want to pass a parameter:
You can use property binding to pass data from parent to child.
Like so,
Use property binding to bind the item property in the child to the currentItem property of the parent.
<app-item-detail [item]="currentItem"></app-item-detail>
In the parent component class, designate a value for currentItem:
export class AppComponent {
currentItem = 'Television';
}
Link to angular docs:
https://angular.io/guide/inputs-outputs
I want to share a complex typescript exported function to a simple HTML - javascript website
I tried to use npm tsc to transform the file into javascript, but generated files have "exports" functions that creates errors in the browser console.
myFunction.ts
export const getTest = (test: any) => {
// Change test object
return test;
};
generated myFunction.js
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTest = function (test) {
// Change test object
return test;
};
Browser console actually warning me "Uncaught ReferenceError: exports is not defined" when I try to include the file with a script tag in HTML file.
What am I doing wrong?
In order to use the original myFunction.ts file all you need to do is this:
Remove the typing and change the extension to .js:
export const getTest = (test) => {
// Change test object
return test;
};
And then, in your HTML file's <script> tag for that JavaScript file, make sure you set the type attibute to module like so:
<script type="module" src="myFunction.js"></script>
Finally, you'll need to import that functionality where you intend to use it.
That should do it as long as you consider browser compatibility:
ES6 Modules
To make this ultimately clear, here is a Plunkr to demonstrate what I mean.
The export keyword creates a module, which can only be used with a module system (such as webpack).
Either use a module system or drop export to create a normal file that creates global names.
I have a Typescript class class.component.ts in which I want to call methods which are defined within my Javascript class. This Javascript class is headed within: /assets/js/*initlibrary.js*. This javascript library is automatically called when the project is initialized.
My question is: how can I reach out to this javascript library and call the function in it? Is it required to import it in a way like import { Component, OnInit } from '#angular/core';? If so, how should I do this?
Thank you in advance!
If you want to use an external library inside your angular project, there are many requirements.
1. Declare your javascript library inside your angular-cli.json :
"scripts": [
"../assets/js/yourlibrary.js"
]
With this instruction, you can use your library function inside your typescript code, but it will not be able to compile (transpile).
2. Create a definition of your library
A typescript definition has an extension file ends with .d.ts. You can create it inside your project and reference it from your tsconfig.json.
Here is an example of the EXIF library definition that I've created :
/// EXIF.d.ts
declare module EXIF {
interface EXIFStatic {
getData(img, callback): boolean;
getTag(img, tag): any;
getAllTags(img): any;
pretty(img): any;
readFromBinaryFile(file): any;
}
}
declare var EXIF: EXIF.EXIFStatic;
declare module "EXIF" {
export = EXIF;
}
In my code, I use like this :
EXIF.getData(img,callback);
You can find more example here : https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types
3. Reference the definition of your library
Here is an example of my tsconfig.json file :
"typeRoots": [
"./typings" // I have create a typings folder inside my src project folder
],
"types": [
"EXIF" // Reference of your EXIF.d.ts inside your typings folder
]
The definition allows you to get autocomplete function name when you code (if you use Visual studio code), and allows angular to build your project.
I am defining models using TypeScript and I have encountered an issue when extending classes. I have two classes, each within a code file of the same name:
class kanine {
name = 'dog'
}
and
class beagle extends kanine {
constructor(name: string) {
super();
this.name = name;
}
}
Within the solution they appear as such:
When I run the application I get this error:
However, when I rename the code file which contains the kanine class from kanine.ts to 1kanine.ts, I do not get the error. Another workaround is by bundling them like this:
.Include("~/app/kanine.js")
.Include("~/app/beagle.js")
Instead of like this:
.IncludeDirectory("~/app", "*.js")
Is there a way to process the files in an explicit order without having to include them individually?
The reason why this is happening is because the base class kanine needs to be defined before the parser gets to beagle.
You can fix this one of two ways:
Continue to explicitly define the order of each individual .js file as you are currently doing in your first example.
Change your compilation settings, either with a tsconfig.json or through the project properties, so that the .ts files are combined into a single .js file, and rely on the typescript compiler to order them properly.
If you choose option 2, you'll need to use /// reference tags to help the compiler figure out which file should be output first. This is as simple as adding this to beagle.ts:
/// <reference path="kanine.ts" />
This will make sure that kanines javascript is output before beagles.
I have an existing Javascript file named app.min.js which comes with a website template. This file defines a function called pageSetUp that needs to be invoked when the DOM is loaded.
I have created a TypeScript definition file named app.d.ts which the following content:
interface App {
pageSetUp();
}
It is referenced in the TypeScript file as follows:
/// <reference path="../typings/app.d.ts"/>
However, when add the following line to the constructor of this class like this:
module ViewModel {
export class TableViewModel {
constructor() {
pageSetUp();
}
}
}
The build fails with error: "Could not find symbol 'pageSetUp'.
What am I missing?
TIA.
app.d.ts is defining a method on an interface called App, but the TableViewModel is trying to use a global function called pageSetUp, which is not defined.
Try this instead in app.d.ts:
declare function pageSetUp();
This declares a global function, but doesn't implement it, so no associated JavaScript is generated, but the function definition can be referenced from other TypeScript files.