Angular4/TypeScript Class Usability - javascript

Is that possible to access two different Typescript classes like controller to store a value...here is my use case....
i'm getting values from the front end lets say i have ID="100",Name="Angular4". Now how can i pass those values to these class using the methods get getFieldValue(fieldName: string) and setFieldValue(fieldValue: string, value: string). Also i have tried to instantiate the classes to get or set the value but i got failed,can anybody please tell how can i acheive the desired output completely using typescript?
my classes are:
main class:
import {Record} from './record';
import {Field} from './field';
export class BusinessObject {
public boName: string = null;
public focusedRecordsList = new Set();
// public activeRecord: Record = new Record();
public fetchSize: number = 100;
// public activeParentRecord: Record = new Record();
public hasMoreRows: boolean;
public isPageQuery: boolean;
public startIndex: number;
public createNewRecord(boName: string, parentId: string, fromRecord: string) {
return JSON.stringify({'boName': boName, 'parentId': parentId, 'fromRecord': fromRecord});
}
getFieldValue(fieldName: string): any {
}
setFieldValue(fieldValue: string, value: string): void {
}
}
and another class, that contains my field types:
import {BusinessObject} from './business-object';
export class Field extends BusinessObject{
// Specifies different information on the field
public name: string = null;
public id: string = null;
public type: string = null;
public boId: string = null;
public colName: string = null;
constructor(name: string) {
}
}

Related

Creating named parameter to base class in typescript and javascript

I have created a base model class with is a model for the incoming data, I will be modeling the data inside of a class for some external reasons. Although I ran into a problem with is defining the incoming data into this model class.
This is my class
export class EntityBasic {
constructor(
public id: string,
public title: string,
public urn?: string,
public risk_level?: string,
public be_aware?: string,
public body?: string,
public published_at?: string,
public created_at?: string,
public updated_at?: string,
public description?: string,
public notes?: string,
) {}}
}
How I define the content inside of it in another page:
public getEntity(setEntity) {
return new EntityBasic(
setEntity.id,
setEntity.title,
setEntity?.urn,
setEntity?.risk_level,
setEntity?.be_aware,
setEntity?.body,
setEntity?.published_at,
setEntity?.created_at,
setEntity?.updated_at,
setEntity?.report?.summary || '',
setEntity?.report?.metadata?.source_notes,
setEntity?.report?.metadata?.notes,
);
}
But defining the data like so, gave me problems, since some times there won't be a urn, or a risk_level for example, and the data will be messed up inside the class.
I would like a way to define like so (This didnt work):
public getEntity(setEntity) {
return new EntityBasic(
id = setEntity.id,
title = setEntity.title,
urn = setEntity?.urn,
risk_level = setEntity?.risk_level,
)
}
I believe wrap all parameters into one object is the best solution.
Wrap them as interface
interface EntityBasicParameters {
id: string;
title: string;
urn?: string;
risk_level?: string;
be_aware?: string;
body?: string;
published_at?: string;
created_at?: string;
updated_at?: string;
description?: string;
notes?: string;
}
Accept only this object as constructor parameter
export class EntityBasic {
constructor(params: EntityBasicParameters) {}}
}
Now you can pass existent data only
public getEntity(setEntity) {
return new EntityBasic({
id: setEntity.id,
title: setEntity.title,
urn: setEntity?.urn,
risk_level: setEntity?.risk_level,
})
}
or just
public getEntity(setEntity) {
return new EntityBasic(setEntity)
}

ReferenceError: Cannot access <Class> before initialization

I Have simple autoloader method that initializes and returns Instance of class using require()
Above simple require is some logic requesting info from database and checking if class exists in filesystem.
let elementClass = require('./elements/' + element.name).default;
Node and ts-node compiles without problem, but when creating instance by require i get
ReferenceError: Cannot access 'Object' before initialization
Object is main abstract class being extended by Element which is then extended by element type.
Required is last in chain class elementType
Class is initialized without problem if there is no Object class being extended, but Object class was tested without any modifications and blank constructor. And all logic transfered to Element class
Object.ts
export default class Object
{
public id: number;
public name: string;
public type: string;
public parent: number;
public owner: number;
public permission: string;
public data: {[name: string]: any};
protected dataSchema: {[name: string]: any} = {};
constructor(id: number, name: string, type: string, parent: number, owner: number, permission: string, data: {[name: string]: any})
{
if(new Validator().validate(data, this.dataSchema))
throw new Error('Invalid input data');
this.id = id;
this.name = name;
this.type = type;
this.parent = parent;
this.owner = owner;
this.permission = permission;
this.data = data;
}
}
Element.ts
import Object from "./object";
export default class Element extends Object
{
/**
* simple logic no constructor
*/
}
ElementType.ts
import Element from '../element';
export default class ElementType extends Element
{
/**
* Simple logic without constructor
*/
}
Even without any simple methods inside classes it doesn't work, it only works when Main Parent class is not used (Object)
Is there some problem requiring class that is twice extended?
Object is reserved word, I just had to rename class to something else.

Array of class and creating objects in typescript

I have a class like this and need to create a collection of properties .in c# i can use a list or any collection type but how to do it in typescript .
class Movies implements Imovies{
public Id : string;
public get fid(): string {
return this.Id;
}
public set fid(theid:string) {
this.Id=theid;
}
public dailyrentalRate : number;
public get fdailyrentalRate(): number {
return this.dailyrentalRate;
}
public set fdailyrentalRate(theid:number) {
this.dailyrentalRate=theid;
}
public numberinstock : number;
public get fnumberinstock(): number {
return this.numberinstock;
}
public set fnumberinstock(theid:number) {
this.numberinstock=theid;
}
public publishDate : string;
public get fpublishDate(): string {
return this.publishDate;
}
public set fpublishDate(theid:string) {
this.publishDate=theid;
}
public title : string;
public get ftitle(): string {
return this.title;
}
public set ftitle(theid:string) {
this.title=theid;
}
}
I tried to insert values to array as follows
let mov=new Array<Movies>();
mov[0].fid="asdasd";
mov[0].fdailyrentalRate=2;
mov[0].fnumberinstock=5;
mov[0].fpublishDate="2018-05-23";
mov[0].ftitle="name";
mov[1].fid="asdasda";
mov[1].fdailyrentalRate=32;
mov[1].fnumberinstock=35;
mov[1].fpublishDate="2018-06-23";
mov[1].ftitle="name2";
but is showing an error
TypeError: Cannot set property 'fid' of undefined
you can also implement the class Movie using a constructor, and then create an array of Movie, like this:
const movies: Movie[] = [];
after you could push movie objects in the movies array:
const movie = new Movie();
movie.fid="test1";
movie.dailyrentalRate=2;
movie.numberinstock=5;
movie.publishDate="2018-05-23";
movie.title="name";
movies.push(movie);
you can see a working example here: https://stackblitz.com/edit/typescript-array-movies

Passing objects between Components/Pages

Hello Im passing objects between two pages.
I have two pages in Ionic App. The first page has Defect object and sends it to the second page. The second Page receives the object and calls it's methods. Passing objects is done with usage of NavParams, an Ionic core class. Below you can see the receiving of the object. The Defect object.
export class Defect {
public priority: DefectPriority;
public state: DefectState;
public note: string;
public _id: string;
public posX: number;
public posY: number;
public createdAt: number;
public drawingId: string;
public images: DefectImage[];
constructor();
constructor(posY?: number, posX?: number, note?: string, defectId?: string, drawingId?: string) {
if (defectId === undefined || defectId === "") {
throw new Error("incorrect defect id");
}
if (posX === undefined || posY === undefined) {
throw new Error("incorrect coordinates");
}
if (drawingId === undefined || drawingId === "") {
throw new Error("incorrect drawingId");
}
if (drawingId === undefined || drawingId === "") {
throw new Error("incorrect drawingId");
}
this.priority = DefectPriority.NORMAL;
this.createdAt = new Date().getTime();
this.state = DefectState.REPORTED;
this._id = defectId;
this.note = note;
this.posX = posX;
this.posY = posY;
this.drawingId = drawingId;
this.images = [];
}
public getPriority() {
return this.priority;
}
setPriority(value: DefectPriority) {
if (!Object.values(DefectPriority).includes(value.toString())) {
throw new Error("incorrect priority")
}
this.priority = value;
}
public changeState(value: DefectState) {
this.state = value;
}
public setNote(note: string) {
this.note = note;
}
generateImageUrl(creatorName: string): DefectImage {
const newUrl = ObjectId.generate() + '-' + this._id + '.jpg';
const defectImage = new DefectImage(newUrl, creatorName, new Date().getMilliseconds());
this.addImage(defectImage);
return defectImage;
}
addImage(defectImage: DefectImage) {
if (!this.images) {
this.images = [];
}
this.images.push(defectImage);
}
Here is the receiving class:
defect: Defect;
constructor(private viewCtrl: ViewController,
private nav: NavParams,
private navCtrl: NavController,
private photo: PhotoProvider) {
this.defect = this.nav.get('defect');
}
Defect class apart from some properties has also methods like: generateImageUrl
Now when I change view to the component where the defect is beeing fetched from params internally it is just JS object without information about Defect class methods: Which means I cannot call methods defined in defect class after I send it to the another Page.
Notice no custom methods like generateImageUrl. Is there a way that I could not lose informations about this object? Or should I just recreate this object from data in the new component ?? my goal on screen below:
the way Im passing data:
const defectModal = this.modalCtrl.create(DefectDetailModal, {
defect: this.defect
});
I'm assuming that Defect is an entity in your App. Angular's Style Guide recommends using interfaces for data models instead of classes.
Consider using an interface for data models.
That being said, you should have created a DefectService, where you would have set some property for the current defect that you're dealing with.
You could have then injected the service in the components that you wanted to share data between. Then from one component, you could have set the defect and then you could get the defect in the other component using setters and getters.

How to create an Angular Domain Model correctly

I want to create a domain model correctly.
My attempt below creates the properties outside the constructor.
Should I be creating and setting the properties of the TestModel class inside the constructor only? this way their would be less lines of code
I have the below attempt that I think is correct:
export class TestModel1 {
public currentPage: number = 0;
public hasNext: boolean = false;
public hasPrev: boolean = false;
public pageSize: number = 0;
public totalItems: number = 0;
constructor(data: any) {
this.currentPage = data.currentPage;
this.hasNext = data.hasNext;
this.hasPrev = data.hasPrev;
this.pageSize = data.pageSize;
this.totalItems = data.totalItems;
}
}
It just seems a little big, too many lines of code.
Currently I need to pass in a data object and then map.
Is their a clever way for me to implement this better using the constructor function?
If we speak about the model class, the declaration of that should be like in example below:
export class Account {
constructor(
public activated: boolean,
public authorities: string[],
public email: string,
public firstName: string,
public langKey: string,
public lastName: string,
public login: string,
public imageUrl: string
) {}
}
Certainly you should not to define values outside of constructor. You may do declare the model class members as you have in your example, but without the definition of values:
export class TestModel1 {
public currentPage: number;
public hasNext: boolean;
public hasPrev: boolean;
public pageSize: number;
public totalItems: number;
constructor(data: any = null) {
if(data !== null) {
this.currentPage = data.currentPage;
this.hasNext = data.hasNext;
this.hasPrev = data.hasPrev;
this.pageSize = data.pageSize;
this.totalItems = data.totalItems;
}
}
}
And if you want to declare default values, my advice is to do this inside the constructor for clean and good code.
Update:
export class TestModel1 {
public currentPage: number;
public hasNext: boolean;
public hasPrev: boolean;
public pageSize: number;
public totalItems: number;
constructor(data: any = null) {
if(data !== null) {
this.currentPage = data.currentPage;
this.hasNext = data.hasNext;
this.hasPrev = data.hasPrev;
this.pageSize = data.pageSize;
this.totalItems = data.totalItems;
}
else {
this.currentPage = 0;
this.hasNext = false;
this.hasPrev = false;
this.pageSize = 0;
this.totalItems = 0;
}
}
}
That's would be better, if you want to have defaults
The main issue I see in the question is that of duplication. All of the properties are duplicated in the constructor, which violates the DRY principle of clean code.
If you want to populate a new instance of your domain object in a more concise way, you can do the following:
export class TestModel1 {
public currentPage: number;
public hasNext: boolean;
public hasPrev: boolean;
public pageSize: number;
public totalItems: number;
constructor(data: any) {
Object.keys(data).forEach(key => {
this[key] = data[key]
});
}
}
You have to ensure that the input data object will have the correct properties only, which may or may not be easy, based on the source of data.

Categories

Resources