I'm new to Angular and have hit a wall in my project which i'm hoping some of you more experienced devs can help me smash through!
I have a JSON file which is called by a service. This data is then injected into the component via my interface where I am using a custom Dictionary class for the 'lists' (list1, list2 etc) i'm looking to let the user edit.
Everything was all good until I had to start trying to use the 'nested' lists from my JSON file. I cannot find a way to use this in my component so that the user can edit the strings.
My JSON looks like this:
[
{
"id": 1,
"insurer": "My Insurer",
"product": "Healthier Solutions",
"heading1": "Insurance",
"heading2": "Insurance Product Information Document",
"heading3": "What is the type of insurance?",
"heading4": "What is insured?",
"heading5": "What is NOT insured?",
"heading6": "Are there restrictions on my cover?",
"heading7": "Where am I covered?",
"heading8": "What are my obligations?",
"heading9": "When and how do I pay?",
"heading10": "When does my cover start and end?",
"heading11": "How do I cancel my contract?",
"subHeading1": "Insurance Company",
"subHeading2": "Healthier Solutions",
"textBox1": "Private Medical Insurance",
"textBox2": "You will have access to Aviva’s Key Hospital list in the UK.",
"textBox3": "Monthly by direct debit. The first payment will be collected within 14 days of setting up the policy. The following payments will be collected monthly thereafter.",
"textBox4": "The policy will start on your chosen start date and will end exactly 12 months later.",
"textBox5": "Please contact...",
"list1": {
"item1": "In and day patient hospital charges",
"item2": "In and day patient diagnostic tests",
"item3": "In and day patient diagnostic scans",
"item4": "In and day patient specialist fees",
"item5": "In and day patient radiotherapy",
"item6": "In and day patient chemotherapy",
"item7": "Outpatient specialist consultations",
"item8": "Outpatient diagnostic tests",
"item9": "Outpatient diagnostic scans",
"item10": "Outpatient radiotherapy",
"item11": "Outpatient chemotherapy"
},
"list2": {
"item1": "Routine monitoring of conditions",
"item2": "Pre-existing conditions",
"item3": "GP consultations and treatment",
"item4": "Emergency treatment",
"item5": "Chronic conditions (e.g. the management of incurable conditions such as asthma, diabetes, arthritis)",
"item6": "Self-inflicted conditions"
},
"list3": {
"item1": "Outpatient psychiatric treatment limited to £2,000 a year",
"item2": "Fees and charges by specialists are limited to Aviva’s fee guidelines"
},
"list4": {
"item1": "You must be a UK resident.",
"item2": "You must pay your monthly premiums in full and on time.",
"item3": "You must be registered with a UK GP at the point of making a claim.",
"item4": "You must ensure that all information that you provide is accurate and true to the best of your knowledge and belief."
}
}
]
My interface looks like this:
import {
IDictionary
} from "../models/IDictionary";
export interface IProducts {
id: number;
insurer: string;
product: string;
heading1: string;
heading2: string;
heading3: string;
heading4: string;
heading5: string;
heading6: string;
heading7: string;
heading8: string;
heading9: string;
heading10: string;
heading11: string;
subHeading1: string;
subHeading2: string;
textBox1: string;
textBox2: string;
textBox3: string;
textBox4: string;
textBox5: string;
list1: IDictionary;
list2: IDictionary;
list3: IDictionary;
list4: IDictionary;
}
Here is my custom dictionary class:
export interface IDictionary {
add(key: string, value: any): void;
remove(key: string): void;
containsKey(key: string): boolean;
keys(): string[];
values(): any[];
item1: string;
item2: string;
item3: string;
item4: string;
item5: string;
item6: string;
item7: string;
item8: string;
item9: string;
item10: string;
item11: string;
}
Here is what my component uses to enable the user to edit the data via a HTML input by importing my interface and using my 'edit' model:
editProduct(k:any) {
this.edit.heading1 = this.products[k].heading1;
this.edit.heading2 = this.products[k].heading2;
this.edit.heading3 = this.products[k].heading3;
this.edit.heading4 = this.products[k].heading4;
this.edit.heading5 = this.products[k].heading5;
this.edit.heading6 = this.products[k].heading6;
this.edit.heading7 = this.products[k].heading7;
this.edit.heading8 = this.products[k].heading8;
this.edit.heading9 = this.products[k].heading9;
this.edit.heading10 = this.products[k].heading10;
this.edit.heading11 = this.products[k].heading11;
this.edit.subHeading1 = this.products[k].subHeading1;
this.edit.subHeading2 = this.products[k].subHeading2;
this.edit.textBox1 = this.products[k].textBox1;
this.edit.textBox2 = this.products[k].textBox2;
this.edit.textBox3 = this.products[k].textBox3;
this.edit.textBox4 = this.products[k].textBox4;
this.edit.textBox5 = this.products[k].textBox5;
this.edit.list1item1 = this.products[k].list1.item1;
this.myValue = k;
}
updateProduct() {
let k = this.myValue;
for (let i = 0; i < this.products.length; i++) {
if (i === k) {
this.products[i] = this.edit;
this.edit = {};
}
}
this.showSuccessAlertMessage = "This product has been successfully updated.";
}
I'm looking to do something like the above - 'this.edit.list1item1 = this.products[k].list1.item1;', but that is not working.
Really hope that makes sense please do let me know if it doesn't and i'll do my best to explain it clearer.
Thanks.
Related
I have an interface for an element:
export interface iElm {
name?: string;
appearance?: string;
atomic_mass?: number;
boil?: number;
category?: string;
density?: number;
discovered_by?: string;
melt?: number;
molar_heat?: number;
named_by?: string;
number?: number;
period?: number;
phase?: string;
source?: string;
spectral_img?: string;
summary?: string;
symbol?: string;
xpos?: number;
ypos?: number;
shells?: number[];
electron_configuration?: string;
electron_configuration_semantic?: string;
electron_affinity?: number;
electronegativity_pauling?: number;
ionization_energies?: number[];
cpk_hex?: string;
}
I got this by using a utility similar to the one in this question (json to ts): How to convert a json to a typescript interface?
The json that I'm using is an object of element object that are all a bit different but one looks like this:
"helium": {
"name": "Helium",
"appearance": "colorless gas, exhibiting a red-orange glow when placed in a high-voltage electric field",
"atomic_mass": 4.0026022,
"boil": 4.222,
"category": "noble gas",
"density": 0.1786,
"discovered_by": "Pierre Janssen",
"melt": 0.95,
"molar_heat": null,
"named_by": null,
"number": 2,
"period": 1,
"phase": "Gas",
"source": "https://en.wikipedia.org/wiki/Helium",
"spectral_img": "https://en.wikipedia.org/wiki/File:Helium_spectrum.jpg",
"summary": "Helium is a chemical element with symbol He and atomic number 2. It is a colorless, odorless, tasteless, non-toxic, inert, monatomic gas that heads the noble gas group in the periodic table. Its boiling and melting points are the lowest among all the elements.",
"symbol": "He",
"xpos": 18,
"ypos": 1,
"shells": [2],
"electron_configuration": "1s2",
"electron_configuration_semantic": "1s2",
"electron_affinity": -48,
"electronegativity_pauling": null,
"ionization_energies": [2372.3, 5250.5],
"cpk_hex": "d9ffff"
}
As you can see everything lines up with the iElm interface (properties are optional because there are some weird corner case elements)
Now here's my problem: I have a React function component that takes in an iElm:
const Element: FC<iElm> = (props) => {
// some jsx stuff with the data
}
I can pass properties of the json to Element like so:
<Element name={table.boron.name}/>
But is there some workaround so that I don't have to go through every property one by one and copy it over?
You can simply use the spread operator to pass the entire object in:
<Element {...table.boron} />
I am trying to create an array of objects for my project, but during the build, I face this issue:
TS1110: Type expected
TS1109: Expression expected
My array looks like this:
export let COUNTRIES: Array<{ name: string, segments: number[] }> = Array({
"name":"Afghanistan",
"segments":[
4687,
4787,
4790,
4795,
4880
]},{
"name":"Albania",
"segments":[
4136,
4248
]})
I tried this solution from Stack Overflow but to no results.
Tried with an interface, having another issue:
I think you might mean this?
interface Country {
name: string;
segments: number[];
}
export let COUNTRIES: Country[] = [
{
"name":"Afghanistan",
"segments":[
4687,
4787,
4790,
4795,
4880
]},{
"name":"Albania",
"segments":[
4136,
4248
]
}]
If someone interested here is the final solution:
export class Country {
name: string
segments: number[]
}
export let COUNTRIES: Country[] = [
{
"name":"Afghanistan",
"segments":[
4687,
4787,
4790,
4795,
4880
]},{
"name":"Albania",
"segments":[
4136,
4248
]
}]
iam new to typescript and don't understand the following behaviour. I have an interface like this:
import { Titles } from "../enumerations/titles";
/**
* Representing a Person
*/
export interface Person{
id: number;
title: Titles
firstName: string;
lastName: string;
getName(): string;
}
And now I want to create an Const Array for mocking some Employees. Therefore I got this class:
import { Person } from "../interfaces/person";
import { Titles } from "../enumerations/titles";
/**
* Represents an Employee
*/
export class Employee implements Person{
id: number;
title: Titles
firstName: string;
lastName: string;
getName(): string {
if (this.title === Titles.Nothing){
return this.firstName + " " + this.lastName;
}
return this.title + " " + this.firstName + " " + this.lastName;
}
}
And the Constant:
import { Titles } from "../enumerations/titles";
import { Person } from "../interfaces/person";
export const PROJECTMANAGER: Employee[] = [
{ id: 1, title: Titles.Nothing, firstName: "Max", lastName: "Mustermann" },
{ id: 2, title: Titles.Nothing, firstName: "Willy", lastName: "Brandt" },
{ id: 3, title: Titles.Dr, firstName: "Walter", lastName: "Steinmeier" }
];
The precompiler told me that this can't work, because Property getName isn't declared in my example values. But this is a Method I just want to initilize some Persons to fill the array.
The Type "({ id: number; title: Titles.Nothing; firstName: string; lastName: string; } | { id: number; titl..." cannot be assigned to "Employee[]".
The Property "getName" is missed in Type "{ id: number; title: Titles.Nothing; firstName: string; lastName: string; }".
Someone can help? I'm sure it's stupid but I'm stucking.
The problem is that object literals are not instances of the class Employee. In order to create an instance of Employee you need to use the new operator ( new Employee() ).
Since typescript uses structural compatibility to determine type compatibility, you can assign an object literal if you provide ALL the members of the class. But the object literal will still not be an instance of the class:
let emp: Employee = {
id: 1, title: Titles.Nothing, firstName: "Max", lastName: "Mustermann",
getName : Employee.prototype.getName
} // This is ok, we have the getName member
console.log(emp instanceof Employee) /// Still false, not an instance since we did not create it using new Employee
A better option would be to provide a constructor that accepts the object literal as a parameter an use that:
export class Employee implements Person{
constructor (data: Partial<Employee>) {
Object.assign(this, data);
}
/// ....
}
let emp: Employee = new Employee({
id: 1, title: Titles.Nothing, firstName: "Max", lastName: "Mustermann",
});
console.log(emp instanceof Employee) /// True now
Since Employee is a class, not a simple object, you need to create new Employees with new, not with a simple object declaration.
Define a constructor that takes id, title, firstName, and lastName as arguments, then do something like this:
export const PROJECTMANAGER: Employee[] = [
new Employee(1, Titles.Nothing, "Max", "Mustermann"),
new Employee(2, Titles.Nothing, "Willy", "Brandt"),
new Employee(3, Titles.Dr, "Walter", "Steinmeier")
];
I'm new to Typescript and I want to write a function that returns the object it receives but with less info.
Let's say I have a Type like that:
type movie = {id: number, title:string, url:string, rating:number}
so I need a function that will receive an array of movies and return it only with id and title.
so if the input is:
[{id:1, title:Wonder Woman, url: www, rating:5},{id:2, title: Super
Man, url:www2, rating:7}]
I need the output to be like that:
[{id:1, title:Wonder Woman},{id:2, title: Super Man}]
Is there an easy way to do that?
You can signal to TS that you're working with part of a type (called a Partial) by using Partial<...>
type Movie = { id: string | number, name: string, url: string }
const movies: Movie[] = [
{ id: 1, name: "Movie A", url: "http://www.google.com" },
{ id: 2, name: "Movie B", url: "http://www.google.com" }
]
function stripUrl ({ id, name }: Movie): Partial<Movie> {
return { id, name }
}
const mMovies = movies.map(stripUrl)
I am not able to map the nested json array which is response from Web to my model array in Angular2. Suppose I have json array response as below:
[{
"base_url": "http://mysearch.net:8080/",
"date": "2016-11-09",
"lname": "MY PROJ",
"name": "HELLO",
"description": "The Test Project",
"id": 10886789,
"creationDate": null,
"version": "2.9",
"metrics": [{
"val": 11926.0,
"frmt_val": "11,926",
"key": "lines"
},
{
"val": 7893.0,
"frmt_val": "7,893",
"key": "ncloc"
}],
"key": "FFDFGDGDG"
}]
I was trying to manually map the fields referring the link Angular 2 observable doesn't 'map' to model to my model and was able to display those in my HTML by iterating through ngFor.....but I want to also display ncloc and lines value also in the HTML but I am not sure how to map those values to my Model array like mentioned in the above link.
Can you please help me with this?
Thanks.
EDIT
Mode class
export class DeiInstance {
base_url: string;
date: string;
lname : string;
name : string;
id : number;
key:string;
constructor(obj: DeiInstance) {
this.sonar_url = obj['base_url'];
this.lname = obj['lname'];
this.name = obj['name'];
this.id = obj['id'];
this.key = obj['key'];
this.date = obj['date'];
}
// New static method.
static fromJSONArray(array: Array<DeiInstance>): DeiInstance[] {
return array.map(obj => new DeiInstance(obj));
}
}
You can simplify your model and your mapping a lot.
You don't need to map your API response manually. JavaScript/TypeScript can do this for you.
First you need multiple interfaces.
export interface DeiInstance {
base_url: string;
date: string;
lname: string;
name: string;
description: string;
id: number;
creationDate: string; //probably date
version: string
metrics: Metric[];
key: string;
}
export interface Metric {
val: decimal;
frmt_val: decimal;
key: string;
}
You can then use the as-"operator" of TypeScript to cast your API response to the DeiInstance Type.
sealSearch(term: string): Observable<DeiInstance[]> {
return this.http.get(this.sealUrl + term)
.map(response => response.json() as DeiInstance[])
.catch(this.handleError);
}
If you use interfaces instead of classes you have also the advantage that you have less production code which will be sended to the client browser.
The interface is only there for pre-compile-time or however you want to call it.
Hope my code works and it solves your problem.