TypeScript internal module usage - module

I have a class named BMW defined in BMW.ts as follows:
///<reference path="../Thing.ts"/>
module Entities.Cars {
import e = Entities;
export class BMW extends Vehicle {
public series: string;
constructor ( model : string, series : string) {
super("BMW", model)
this.series = series;
}
drive() {
alert("driving a bimmer is a different kind of feeling");
}
toString() : string
{
return this.getName() + " " + this.series + " " + this.getType();
}
}
}
In another file Thing.ts, I have Vehicle and Thing classes defined as follows:
module Entities {
// Class
export class Thing {
private _name: string;
private _type: string;
// Constructor
constructor (public name: string, public type: string) {
this._name = name;
this._type = type;
}
getName(): string { return this._name; }
setName(name: string) { this._name = name; }
getType(): string { return this._type; }
setType(name: string) {
this._type = name;
}
toString() : string
{
return "Entities.Thing";
}
}
export class Vehicle extends Thing {
public cargoCapacity: number;
public fuelType: string;
public owner: string;
constructor (make: string, model : string) {
super(make, model)
}
drive() {
}
toString(): string {
return "Entities.Vehicle";
}
}
}
When I attempt to execute the following code after referencing Thing and BMW TypeScript files:
var car = new Entities.Cars.BMW("335i", "E90");
car.drive();
I get an exception with the following error " Microsoft JScript runtime error: Unable to get value of the property 'BMW': object is null or undefined". The generated Javascript for BMW has an error. What is wrong with my above snippet?

There is nothing wrong with your code so it seems like your import order for the generated javascript files is wrong. The specification says the following:
Initialization order of the source files that make up the global module ultimately depends on the order in which the generated JavaScript files are loaded at run-time (which, for example, may be controlled by tags that reference the generated JavaScript files).
I have generated a file app.ts as follows:
///<reference path='Things.ts'/>
///<reference path='bmw/BMW.ts'/>
var car = new Entities.Cars.BMW("335i", "E90");
car.drive();
At this point you have two options:
Let the compiler determine the correct order for executing the files by generating a single output file
tsc --out app.js app.ts
Then you only have to source app.js.
Specify the correct order manually. For me, the following is the only order that works without throwing errors.
<html>
<head>
<script src="Things.js"></script>
<script src="bmw/BMW.js"></script>
<script src="app.js"></script>
</head>
<body>
</body>
</html>

Your code is fine.
My guess is that you are not placing script tags in your head element properly(wrong order, or ommitting some).
The simplest way to solve this, and to not have to remember about proper declaration sequence is to use single .js output file from tsc compiler by setting --out option.
EDIT: Depending on which js scenario you are working on(WSH, web app or some other js environment), you need to link js source files differently.
With wsh for instance, you could use FileSystemObject to read a source file, then evaluate it.
Or you could use AMDs...

Related

Adding lit-element and lit-html to a global variabel

I have several lit-elements on my page, but I can't compile them all together so I would like to "share" the lit stuff through a global variable. Might be a bit unconventional, but right now it will save me a lot of bytes.
I'm using rollup to do the packaging.
I think I'm pretty close to achieve what I want, but there is something that I'm missing...
This is my component..
#customElement('tab-strip')
export class TabStrip extends LitElement {
Resulting in
var tabstrip = (function (exports, litElement, repeat, classMap) {
//SOME OTHER STUFF
exports.TabStrip = class TabStrip extends litElement.LitElement {...
.
.
.
${repeat.repeat(this._tabs, e => litElement.html
}({}, Globals, Globals.repeat, Globals.classMap))
I have create a Globals.ts file that looks like this..
import { customElement, html, LitElement, property } from "lit-element";
import { Template, TemplateResult } from "lit-html";
import { classMap } from "lit-html/directives/class-map";
import { repeat } from "lit-html/directives/repeat";
class Globals {
public html = html;
public LitElement = LitElement;
public customElement = customElement;
public property = property;
public repeat = repeat;
public classMap = classMap;
public Template = Template;
public TemplateResult = TemplateResult;
}
window["Globals"] = new Globals();
And at last my rollup.config
input: inputDir + name + ".ts",
output: {
file: outputDir + name + ".js",
name: name,
format: format,
sourcemap: true,
globals: {
"lit-element": "Globals",
'customElement': 'Globals.customElement',
'lit-html': "Globals.LitHtml",
'html': "Globals.html",
'property': "Globals.property",
'lit-html/directives/repeat': "Globals.repeat",
'lit-html/directives/class-map': 'Globals.classMap',
'Template': 'Globals.Template',
'TemplateResult': 'Globals.TemplateResult'
}
},
plugins: [
typescript({
experimentalDecorators: true
}),
resolve(),
// terser({"ecma":"2019"}),
],
external: ['lit-element', 'lit-html', "lit-html/directives/repeat", "lit-html/directives/class-map"]
Gut feeling is that I have misunderstood something in the external stuff of rollup..
AS you can see in the generated file it says litElement.LitElement instead of just litElement
Any help??
Does it work for you? This seems correct just taking it at face value.
Looking at what your Globals is, it's an object with the properties LitElement, property, html, and so on.
If we look at your tabstrip function, the second argument is litElement, which matches the Globals Object being passed in.
So class TabStrip extends litElement.LitElement
makes sense, since the litElement is referencing your Globals object, and that has the LitElement property.

How to access swift class in other module of objective c

How can i access that dummy class.swift in my sdksdk module and use it in ViewController.m file. any suggestion structure image
in dummy class there is a var name = "sid"
and i want to fetch that in my objective c class
dummy project link: https://drive.google.com/open?id=1PpJfdAlkT8kPhbxnFvJ2DyshvaD6K_mD
You need to have your sdkSDK module to be a framework, add it to you project. After that you can import sdkSDK in any of your Pracs classes or inject things to sdkSDK, best way I found to communicate from SDK to App is to use callbacks.
I did simple example in Swift but in your case there will be no difference if you will combine Swift and ObjC.
First - add SDK to Project.
Code inside SDK:
public class SDKDummyProvider {
public var sdkSurnameDidChanged: ((_ text: String) -> Void)?
var surname = "Siddhant" {
willSet {
// When you change surname its calls closure in `willSet`
sdkSurnameDidChanged?(newValue)
}
}
public init(name: String) {
print("Name from Pracs: \(name)")
}
}
Code inside Project:
import sdkSDK
class AppDummy {
var name = "Name"
let sdkProvider: SDKDummyProvider
init() {
// This is how you 'inject' name to SDK
sdkProvider = SDKDummyProvider(name: name)
// This is how SDK module will tell to Pracs that name has changed.
sdkProvider.sdkSurnameDidChanged = { newName in
print(newName)
}
}
}

singleton object in react native

I'm new in react native.I want store multiple small small strings to common singleton object class and want to access it from singleton object for all component. Can anyone help me singleton object implementation for react native.
Ex
Component 1 -- Login button -- >> success --> need to store userID into singleton object.
Component 2 --> get stored userID from singleton object. How can i implement it.
Here is a simple way of doing it...
export default class CommonDataManager {
static myInstance = null;
_userID = "";
/**
* #returns {CommonDataManager}
*/
static getInstance() {
if (CommonDataManager.myInstance == null) {
CommonDataManager.myInstance = new CommonDataManager();
}
return this.myInstance;
}
getUserID() {
return this._userID;
}
setUserID(id) {
this._userID = id;
}
}
And here is how to use it...
import CommonDataManager from './CommonDataManager';
// When storing data.
let commonData = CommonDataManager.getInstance();
commonData.setUserID("User1");
// When retrieving stored data.
let commonData = CommonDataManager.getInstance();
let userId = commonData.getUserID();
console.log(userId);
Hope this works out for you :)
I suggest making a static class that stores data using AsyncStorage.
You mentioned in a comment that you are already using AsyncStorage, but don't like spreading this functionality throughout your app. (i.e. try-catches all over the place, each component needing to check if a key is available, etc.) If this functionality were in a single class, it would clean up your code a lot.
Another bonus to this approach is that you could swap out the implementation pretty easily, for example, you could choose to use an in-memory object or AsyncStorage or whatever and you would only have to change this one file
NOTE: AsyncStorage is not a safe way to store sensitive information. See this question for more info on the security of AsyncStorage and alternatives.
That said, this is how I imagine a global data holder class might look:
export default class dataManager {
static storeKeyValue(key, value) {
// your choice of implementation:
// check if key is used
// wrap in try-catch
// etc.
}
static getValueForKey(key) {
// get the value out for the given key
}
// etc...
}
Then to use this class anywhere in your app, just import wherever it's needed like so:
import dataManager from 'path/to/dataManager.js';
// store value
dataManager.storeKeyValue('myKey', 'myValue');
// get value
const storedValue = dataManager.getValueForKey('myKey');
EDIT: Using Flux, Redux, or a similar technology is probably the preferred/suggested way to do this in most cases, but if you feel the Singleton pattern works best for your app then this is a good way to go. See You Might Not Need Redux
There is a workaround for this, react native packager require all the modules in the compilation phase for a generating a bundle , and after first require it generates an internal id for the module, which is from then on referenced in the whole run-time memory , so if we export an instance of a class from the file, that object will be referenced every-time whenever that file is imported .
TLDR;
Solution I :
class abc {
}
module.exports = new abc()
Solution II : I assume you want to get your strings which are static and wont change , so you can declare them as static and access them directly with class name
FYI :this works with webpack also.
I might be too late for this, but I might as well share my own implementation based on Yeshan Jay's answer.
export default class Data {
static instance = null;
_state = {};
static get inst() {
if (Data.instance == null) {
Data.instance = new Data();
}
return this.instance;
}
static get state() {
return Data.inst._state;
}
static set state(state) {
Data.inst._state = state;
}
static setState(state) {
Data.inst._state = {...Data.inst._state, ...state}
}
}
And here's how you use it. It's pretty much mimicking React Component's state behavior, so you should feel at home with little to no adjustment, without the need to frequently modify the Singleton to add new properties now and then.
import Data from './Data'
// change the whole singleton data
Data.state = { userId: "11231244", accessToken: "fa7sd87a8sdf7as" }
// change only a property
Data.setState ({ userId: "1231234" })
// get a single property directly
console.log("User Id: ", Data.state.userId)
// get a single property or more via object deconstruction
const { userId, property } = Data.state
console.log("User Id: ", userId)
TS Class Example:
export class SingletonClass
{
private static _instance: SingletonClass;
public anyMetod(_value:any):any
{
return _value;
}
public static getInstance(): SingletonClass
{
if (SingletonClass._instance == null)
{
SingletonClass._instance = new SingletonClass();
}
return this._instance;
}
constructor()
{
if(SingletonClass._instance)
{
throw new Error("Error: Instantiation failed: Use SingletonClass.getInstance() instead of new.");
}
}
}
Use:
SingletonClass.getInstance().anyMetod(1);

Aurelia DataTables Recompile

I've been exploring Aurelia and so far have loved what I've seen. I've come accross an issue that I'm not really sure how to solve. I used jquery datatables for large results in my current app with angular, using server side fetches. Datatables has a function you can call whenever a new row is added to the table (fnRowCallback - http://legacy.datatables.net/ref#fnRowCallback, or "createdRow" - https://datatables.net/examples/advanced_init/row_callback.html#) - This is really handy as you can recompile the dom after each row (costly I know).
This enables you to reference functions that exist in the current scope (or viewModel) that the datatable exists in. For example:
In my view model:
export class DataTableTest{
test(){
alert('this is a test');
}
}
In the return results from a datatable fetch:
{name:'blah',age:40,actions:"<a click.delegate='test();'>Test</a>"}
For some reason I can't seem to figure out how to recompile an element once it has been added to the dom.
Does anyone have any ideas how you could do this?
UPDATE:
These are the original options I pass to datatables:
var options = {
"fnRowCallback": function (nRow) {
$compile($(nRow).contents())(scope);
}
};
I've tried the following after injecting that compiler service:
"fnRowCallback": function (nRow) {
this.compiler.compile($(nRow).contents()).fragment.innerHTML;
},
But I always get Uncaught TypeError: Cannot read property 'compile' of undefined - I do this in the "attached" function.. If I console.log(this.compiler) outside of these options, it's available. Also, we don't need to return html back to datatables, just run the compile on the contents. Many thanks for all your help!
You can use a compiler service to compile the element:
import {inject, ViewCompiler, ViewResources, Container} from 'aurelia-framework';
/**
* Compiler service
*
* compiles an HTML element with aurelia
*/
#inject(ViewCompiler, ViewResources, Container)
export class Compiler {
viewCompiler: any;
resources: any;
container: any;
constructor(viewCompiler, resources, container) {
this.viewCompiler = viewCompiler;
this.resources = resources;
this.container = container;
}
compile(templateOrFragment, ctx = null, viewSlot = null):any {
if (typeof templateOrFragment === "string") {
var temp = document.createElement('span');
temp.innerHTML = templateOrFragment;
templateOrFragment = temp;
}
var view = this.viewCompiler.compile(templateOrFragment, this.resources).create(this.container, ctx);
return view;
}
}
I use this in Kendo in the cell template callback function (it lets you return a string that will become the cell contents)
function(dataItem) {
var cellctx = { "$item": dataItem, "$parent": ctx };
return this.compiler.compile(templateString, cellctx).fragment.innerHTML;
}
(this happens in Aurelia's bind callback so the ctx is the executionContext)
I just wrap the current data item up in a context and alias it as $item so I can work with it.
Looks something like this:
<kendo-grid>
<kendo-grid-col title="Main Office" field="IsMainOffice">
<kendo-template><img if.bind="$item.IsMainOffice" src="/content/img/accept.png" /></kendo-template>
</kendo-grid-col>
</kendo-grid>

Properties in a module

Is there a way to define a property in a TypeScript module?
None of these compile:
module My {
// doesnt work
get Value(): number { return 42; }
// doesn't work either
get function Value(): number { return 42; }
// nope
function get Value(): number { return 42; }
}
Right now I'm forced to use this:
module My {
declare var Value: number;
Object.defineProperty(My, "Value", {
get: () => 42
});
}
The second form seems messy to me and the code hinting doesn't really treat it as a read-only property but as a plain variable.
Is there any standard way of defining properties directly inside modules?
No, there's not a way to declare a property on a module in TypeScript using any documented language features.
You can do it in several slightly round-about techniques.
A module can extend an existing class or function. So, I've created a class with a static property, and then later created a module that uses the same name as the class.
class My
{
static get Value():Number {
return 42;
}
}
module My {
var works: boolean = true;
}
alert(My.Value);
It does generate one oddity in the JavaScript generated code that you wouldn't do manually (and should be removed by most optimizers anyway) ... it will redeclare the variable My when the module is created. This does not cause a run-time issue as the variable was already lifted in JavaScript and will not conflict with the first usage.
Here's another option:
module Global {
class Inner {
get Value():Number {
return 42;
}
}
export var My;
My = new Inner();
}
var My = Global.My;
alert(My.Value);
While it presents an extra namespace, you can manipulate it however you'd like and use the inner class or change it as needed. This way, the My variable is global, just like it would be as a module.
Instead of using the module keyword, consider instead using export, which will allow you to do what you want to do, treating the file itself as a module (which is how CommonJS and AMD both work).
// in My.ts
var My = {
get value() {
return 42;
}
};
export = My;
// in foo.ts
import My = require('My');
console.log(My.value);
I describe this in greater detail in a blog post, The Definitive Guide to TypeScript.
I tried the singleton
let My = {
get value() {
return 42;
}
}
export My
but ran into an issue where the emitted JS still said get value() and didn't work on older versions of Node. I tried Object.defineProperty but then lost TypeScript compatibility. Here's my bridge that fixes both cases:
interface My {
value: number
}
// type assertion fixes TypeScript usage
let my = <My>{}
// defineProperty fixes JS usage
Object.defineProperty(my, 'value', {
get: () => 42
});
export = my;
It's used like a module in typescript
import * as my from './my'
my.property // returns 42
// my.property = doesn't work
I know it's a "little" late for this but using typescript 4.8 you can do this:
export module MyModule {
export var myVariable: string = "test";
}
then use it like:
MyModule.myVariable = "something else";