Angular #Input type accepts faulty model - javascript

I am trying to make #Input to my component with a model that looks something like this
interface Car {
sail?: never
tires: number
weight: number
}
interface Boat {
tires?: never
sail: boolean
weight: number
}
export type Vehicle = Car | Boat;
Goal is to accept inputs like this: (this works and does not give me any error)
#Input() Car: Vehicle = {weight: 2500, tires: 4}
#Input() Boat: Vehicle = {weight: 2500, sail: true}
This gives me error as expected
#Input() Mixed: Vehicle = {weight: 2500, tires: 4, sail: true}
And in my html file i have this (should only be able to input tires or sail not booth, should throw error)
<component [car]="{weight: 2500, tires: 4, sail: true}"></component >
And the Input from the html file doesn't give me any error as expected from Angular. But what I am not understanding is how the Vehicle type can be populated with faulty data. What is the best way to deal with this?

In the HTML there is no type-checking, since this is specific to Typescript.
However, you can declare the Vehicle in your .ts file and use the variable within your HTML, this way you should get an error as expected.

Related

In DymanoDB/Dynamoose, how can I set a schema of a map of string keys and number values?

So I have this instructions:
Schema Defs:
Result object:
It's a map of string keys and number values
"result": { "M": { [STRING]: { "N": "401" } },
This is what I have so far
result: {
type: Object,
schema: {
// I am getting 2 errors:
// Parsing error: Unexpected token, expected "]"
// ',' expected.
[id: String]: Number
},
required: true
},
Any ideas?
[id: String] is a TypeScript thing. Not allowed in standard JavaScript.
This is not technically possible in Dynamoose. The only option here is to use the saveUnknown schema setting.
This was brought up in a conversation before, and the user who wanted to do this I told to create an issue on the GitHub repo but it doesn't look like that happened. If you'd like support for this in Dynamoose in the future, please submit a feature request on the GitHub repo.
Edit
In order to do this your schema would looks something like:
new dynamoose.Schema({
result: {
type: Object,
required: true
},
}, {
"saveUnknown": ["result.**"]
});
This will allow indefinitely nested objects within result.

Dynamically form Input, to a function in Service, from Input from Template- Angular

Let's say a service has a Subject, whose value you want to dynamically set from a component.
A.service.ts:
//ChartTools: zoom?: boolean, pan?: boolean
public ChartConfig$: BehaviorSubject<ChartTools> = new BehaviorSubject(this.defaultValues);
public changeChartConfig(config: ChartTools):void{
const currentValues = this.ptChartToolsConfig$.value;
this.ptChartToolsConfig$.next({
...currentValues,
pan: config.pan,
zoom: config.zoom
})
}
Now in component A,we want to set this subject dynamically through a function:
A.component.html:
<mat-checkbox
value="zoom"
[checked]= "ToolsConfig$.zoom"
(change) = changeChartConfig($event.value, $event.source._checked)
>
A.component.ts
ngOnInit():void{
private ToolsConfig$ = this.A_Service.ChartConfig$.subscribe();
}
//cTask['constant']= "zoom" | "pan"
changeChartConfig(component: cTask['constant'], checked: boolean):void{
this.A_Service.changeChartConfig({
component : checked
})
}
But, the input 'component' in changeChartConfig() is not even used and I get the error:
Argument of type '{ component: boolean; }' is not assignable to parameter of type 'ChartTools'.
Object literal may only specify known properties, and 'component' does not exist in type 'ChartTools'.
I understand It's saying 'component' doesn't exist in interface ChartTools, but the values of component exist in ChartTools, and I want to use them.
Can someone please help me with what can be done to resolve this?
You have a typescript issue here.
What your error is saying is that you are expecting params to be ChartTools, but you are sending in something that looks different. Check your interface to make sure everything fits in properly. Also if in interface you are lacking component property add it. If everything is fine reset your VScode
So lets say your ChartTools interface looks like this:
interface ChartTools {
property1: string;
property2: number;
component: boolean;
}
The error prevents you to send in a value that lacks property1 and property2, because it is not a ChartTool.
How to fix it:
either make property1 and property2 opitonal:
interface ChartTools {
property1?: string;
property2?: number;
component: boolean;
}
use TS Partials, or add the missing params to you component when you are sending data:
changeChartConfig(component: cTask['constant'], checked: boolean):void{
this.A_Service.changeChartConfig({
component : checked
missingProp1: 'Some value'
missingProp2: 'Another value'
})
}
EDIT
If you are trying to achieve dynamic property name do it this way:
this.A_Service.changeChartConfig({
[component] : checked
// [component] will be parsed instead of being sent in as a string
})

How to implement ngx-select-dropdown with typescript objects array not with single type of elements such strings

I wanted to implement mat select box or just html select box with live search functionality and found mat-select-search project implemented in https://stackblitz.com/github/bithost-gmbh/ngx-mat-select-search-example?file=src%2Fapp%2Fapp.component.html.
It is working perfectly fine but it requires a lot of configuration and in my project I have more than 5 mat-selects with pretty large data set, then found "ngx-select-dropdown" it has minimum configuration but I couldn't configure it for typscript objects, it is working with single type string array.
Here is code
export class AppComponent {
public items: string[] = ['Amsterdam', 'Antwerp', 'Athens','Barcelona',
'Berlin', 'Birmingham', 'Bradford', 'Bremen', 'Brussels', 'Bucharest',
'Zagreb', 'Zaragoza', 'Łódź'];
public ngxControl = new FormControl();
public inputTyped = (source: string, text: string) =>
console.log('SingleDemoComponent.inputTyped', source, text);}
html
<ngx-select [formControl]="ngxControl"
[allowClear]="true"
[defaultValue]="doNgxDefault()"
[items]="items"
placeholder="No city selected"
(typed)="inputTyped('ngx-select', $event)"
</ngx-select>
However I wanted to implement it with this type of items
interface Bank {
bank_id: number;
name: string;
code: string;
ord: number;}
private items: Bank[] = [
{bank_id: 1, name: 'Bank A (Switzerland)', code: 'ARM', ord:10},
{bank_id: 2, name: 'Bank B (Switzerland)', code: 'ARM', ord:11},
{bank_id: 3, name: 'Bank C (Switzerland)', code: 'HIO', ord:12},
{bank_id: 4, name: 'Bank D (Switzerland)', code: 'ARM', ord:13},
{bank_id: 5, name: 'Bank E (Switzerland)', code: 'ARM', ord:14},];
Is it possible use typscript objects with ngx-select for items, because I need to populate the names of each object and get the id's as value property to integrate with database. I am sure that it is possible extracting the names with loop and searching matching options with names but it is not best practice I think.
Updated Answer
Since items:[] gets array of objects property names of items should be exactly as documentation of ngx-select
interface Bank {
id: string;
text: string;
}
Yes its possible. you need see API document https://optimistex.github.io/ngx-select-ex/
optionValueField string 'id' Provide an opportunity to change the name an id property of objects in the items
optionTextField string 'text' Provide an opportunity to change the name a text property of objects in the items
<ngx-select [formControl]="ngxControl"
[allowClear]="true"
[defaultValue]="doNgxDefault()"
[items]="items"
[optionValueField]="bank_id"
[optionTextField]="name"
placeholder="No city selected"
(typed)="inputTyped('ngx-select', $event)"
</ngx-select>
<ngx-select
[(ngModel)]="Value Which You Selected"
[allowClear]="true"
[items]="Bank"
optionTextField="bank_id"
placeholder="Type your Value Here">
<ng-template ngx-select-option ngx-select-option-selected let-option let-text="text">
<span class="color-box" [style]="option.value"></span>
<span [innerHtml]="text" style="color: black"></span>
/ {{option.data.name}} / {{option.data.code}} / {{option.data.ord}}
</ng-template>
</ngx-select>
Assign your Full array in [Items]="" and use the another key values in ngx Template
{{option.data.name}}
{{option.data.code}}
{{option.data.ord}}
If you want to stay with angular material, you can also create your custom wrapper component to avoid boilerplate code, see e.g. Angular ngx-mat-select-search Custom Component.
The wrapper component behaves like a form control and you can adjust it to your needs.

Strongly typed Immutable.js Records in TypeScript

I'm unable to find a good resource for this question. Essentially I want to describe types for my data using an interface in TypeScript, but my data is Immutable.js records which appears to complicate matters, please see my example below.
interface tree extends Immutable.Map<string, any> {
readonly id: number,
readonly type: number
}
let trees = Immutable.List<tree[]>([
Map<tree>({
id: 101,
type: 1
}),
Map<tree>({
id: 201,
type: 3
})
])
Questions with the above:
Why do I have to repeat the type of each map in my list? Shouldn't the type be simply be declared by the <tree[]> when creating the list? And then any Map added to the list be type checked against this?
At present this example errors, stating that "property 'id' is incompatible with index signature. Type 'number' is not assignable to type 'tree'. Which makes sense! However, reading the documentation, I can't work out how to get it to work? Reading the docs it states I need an ID but I want an array of maps, my signature in this case is just standard array ID's if I not much mistaken?
I've been working on this for days and I simply can't get it to work, it should be this simple according to everything I've read.
Any help would be greatly appreciated.
You are creating a List of arrays of trees, which is an extended Map. This is what it should look like:
let trees = Immutable.List<tree[]>(
[ // List
[ // Array
<tree>Immutable.Map<any>({
id: 101,
type: 1
}),
<tree>Immutable.Map<any>({
id: 201,
type: 3
})
]
]
);
Answering your questions:
You are not repeating the type of each map. Actually, you are calling a method Map that builds a map from an object. I added the <tree> cast because it is an array of trees, not maps.
You are trying something like:
var singleTree: tree = Immutable.Map<tree>(
{ id: 101, type: 1 }
);
But your tree is a map of the any type. So, this is the right syntax:
let singleTree: tree = <tree>Immutable.Map<any>(
{ id: 101, type: 1 }
);
For the code above, we can simplify and force a type check if we create a tree function to wrap the Map function, so, the final solution would be:
function tree(obj: { [key: string]: any, id: number, type: number }): tree {
return <tree>Immutable.Map<any>(obj);
}
let trees = Immutable.List<tree[]>(
[ // List
[ // Array
tree({
id: 101,
type: 1
}),
tree({
id: 201,
type: 3
})
]
]
);

Hashes being pushed onto mongoose model as '[object Object]"

I am trying to push some things onto a Mongoose model. The model looks like this.
var ScheduleSchema = new mongoose.Schema({
hours: Number,
items: [{number: Number, minutes: Number, details: {description: String}, type: String}],
userId: Number
});
//later
ScheduleSchema.methods.createNew = function(hours, tasks, breathers) {
var schedule = makeSchedule(hours, tasks, breathers);
console.log(schedule);
this.items = schedule;
console.log(this.items);
}
I think that is enough code for my issue, but I can give more code if needed. Essentially, I've got a method for creating a schedule and then I want to assign the schedule to the object's 'items' property. I must admit I am still learning about mongoose so it is likely a problem there.
Anyway, I know my makeSchedule function is working, because I see this as the output from the first console message.
[{ number: 1,
minutes: 30,
details: {description: 'Task A'},
type: 'task'},
{ number: 2,
minutes: 45,
details: {description: 'Task B'},
type: 'task'},
etc...
]
However, when the console output from my second log statement, this.items, prints, I don't see the same structure. Instead, I see
["[object Object]", "[object Object]", "[object Object]", etc...]
Why am I not able to just assign the schedule variable to this.items? I believe I was even able to do it before, but I made some changes to my schedule code and now I cannot.
That would lead me to believe that the error is in my schedule code, but as you can see, it is creating the list of items just fine, based on the console output. Can anyone see a really obvious, potentially mongoose related mistake that I may have missed as a rookie?
My guess is that you recently added the type field to the embedded objects in items which is making Mongoose now think that items contains an array of strings instead of an array of objects like you have.
To fix it, use an object to define the type for type in your schema like so:
var ScheduleSchema = new mongoose.Schema({
hours: Number,
items: [{
number: Number,
minutes: Number,
details: {description: String},
type: {type: String}
}],
userId: Number
});

Categories