Cannot find module '#angular/core - javascript

I want to implement chart in my angular app. So I used ChartJs. I implemented method to show chart but problem in its gives an error when compiling.
My base-chart.directive.d.ts file as follows.
import { OnDestroy, OnChanges, OnInit, EventEmitter, ElementRef, SimpleChanges, DoCheck } from '#angular/core';
import * as chartJs from 'chart.js';
import { Color } from './color';
import { ThemeService } from './theme.service';
export declare type SingleDataSet = (number[] | chartJs.ChartPoint[]);
export declare type MultiDataSet = (number[] | chartJs.ChartPoint[])[];
export declare type SingleOrMultiDataSet = SingleDataSet | MultiDataSet;
export declare type PluginServiceGlobalRegistrationAndOptions = chartJs.PluginServiceGlobalRegistration & chartJs.PluginServiceRegistrationOptions;
export declare type SingleLineLabel = string;
export declare type MultiLineLabel = string[];
export declare type Label = SingleLineLabel | MultiLineLabel;
export declare class BaseChartDirective implements OnDestroy, OnChanges, OnInit, OnDestroy, DoCheck {
private element;
private themeService;
data: SingleOrMultiDataSet;
datasets: chartJs.ChartDataSets[];
labels: Label[];
options: chartJs.ChartOptions;
chartType: chartJs.ChartType;
colors: Color[];
legend: boolean;
plugins: PluginServiceGlobalRegistrationAndOptions[];
chartClick: EventEmitter<{
event?: MouseEvent;
active?: {}[];
}>;
chartHover: EventEmitter<{
event: MouseEvent;
active: {}[];
}>;
ctx: string;
chart: Chart;
private old;
private subs;
/**
* Register a plugin.
*/
static registerPlugin(plugin: PluginServiceGlobalRegistrationAndOptions): void;
static unregisterPlugin(plugin: PluginServiceGlobalRegistrationAndOptions): void;
constructor(element: ElementRef, themeService: ThemeService);
ngOnInit(): void;
private themeChanged;
ngDoCheck(): void;
copyLabel(a: Label): Label;
labelsEqual(a: Label, b: Label): boolean;
copyColor(a: Color): Color;
colorsEqual(a: Color, b: Color): boolean;
updateColors(): void;
ngOnChanges(changes: SimpleChanges): void;
ngOnDestroy(): void;
update(duration?: any, lazy?: any): {};
hideDataset(index: number, hidden: boolean): void;
isDatasetHidden(index: number): boolean;
toBase64Image(): string;
getChartConfiguration(): chartJs.ChartConfiguration;
getChartBuilder(ctx: string): Chart;
smartMerge(options: any, overrides: any, level?: number): any;
private isMultiLineLabel;
private joinLabel;
private propagateDatasetsToData;
private propagateDataToDatasets;
private isMultiDataSet;
private getDatasets;
private refresh;
}
I have already followed instruction which mentioned here
But my problem as it is. Please help. My ChartJs version is:ng2-charts#2.2.3 and angular version 8.

Try npm cache clean --force and then run npm install ng2-charts#2.3.2 --save to re install ng chart.

Related

Display an array of data from function in Angular

My goal is to display a cross or a check according to the vote.result data from the polls.
I had to use Angular only few times and I feel pretty lost honestly.
TS file (angular) :
#Component({
selector: 'app-deck-card',
templateUrl: './deck-card.component.html',
styleUrls: ['./deck-card.component.scss'],
})
export class DeckCardComponent implements OnInit {
#Input() isAnim: boolean;
#Input() inGame: boolean;
#Input() editMode: boolean;
#Input() readOnly: boolean;
#Input() deckIsBase: boolean;
#Input() card: CardDto;
#Input() polls: PollDto[];
#Input() isSearch: boolean;
#Input() isImport: boolean;
#Input() idDeck: number;
#Input() editRight: boolean;
#Output() changeVote = new EventEmitter<number>();
#Output() deleteEvent = new EventEmitter<number>();
#Output() duplicateEvent = new EventEmitter<CardDto>();
#Output() importEvent = new EventEmitter<CardDto>();
#Output() sharedToCommunityEvent = new EventEmitter<CardDto>();
safeIcon: SafeUrl | string;
votes: VoteDto[];
constructor(private readonly authState: AuthState,
private sanitizer: DomSanitizer) {
}
ngOnInit(): void {
this.safeIcon = this.sanitizer.bypassSecurityTrustUrl(this.card?.theme?.icon);
this.votes = this.polls?.find(p => p.card.id === this.card?.id)?.votes;
}
/**
* Emit the card ID to delete the card
* #return void
*/
deleteCard(): void {
this.deleteEvent.emit(this.card.id);
}
showTheResult(): string {
console.log(this.polls);
console.log(this.votes);
this.polls?.forEach(vote => {
if (vote.voted && vote.result == false) {
// display a mat-icon cross
console.log(vote)
return '<mat-icon>clear</mat-icon>'
} else if (vote.voted && vote.result == true) {
// display a mat-icon check
console.log(vote)
return '<mat-icon>done</mat-icon>'
}
});
return '';
}
}
My 2 console.log in showTheResult() are always undefined.
So, obviously, the console log in the if condition are never reached.
HTML file :
<div class="card-body" [class.card-body-readOnly]="readOnly">
<p class="main-text" [class.readOnly]="readOnly" [class.short]="inGame && isAnim"
[class.long]="!editMode && !isAnim">{{card?.text}}</p>
<p>{{showTheResult()}}</p>
<p>DISPLAY HERE THE MAT-ICON</p>
<span *ngIf="isAnim || editMode" class="sub-text">#{{card?.id}}</span>
</div>
can someone show me the way ?
The DTOs look like this:
export interface PollDto {
id: number;
result: boolean;
voted: boolean;
priority: number;
card: CardDto;
votes: VoteDto[];
}
export interface VoteDto {
participantId: number;
participantName?: string;
pollId: number;
result: boolean;
}
since your this.polls is an #Input(), you don't know if this variable is actually loaded when you reach ngOnInit lifecycle.
When working with #Input data, if you want to catch the moment data is loaded, you should watch the changes :
https://ultimatecourses.com/blog/detect-input-property-changes-ngonchanges-setters
ngOnChanges(changes: SimpleChanges) {
console.log(changes);
}
This way, you will see if ever your data are loaded, if not, that means the problem is in the parent container component.
Also, a quick note : I don't think you should return HTML in your
method, you probably want to handle this another way, with a directive
or something, this would not be a good practice.
Cheers ! :)

Typescript: es6 import type definition (.d.ts) from node_modules subfolder

I have a npm package that has the following type definitions (simplified):
./node_modules/ag-grid-react/main.d.ts
export declare class AgGridReact extends Component<AgGridReactProps, {}> {}
./node_modules/ag-grid-react/lib/agGridReact.d.ts
export declare class AgGridReact extends Component<AgGridReactProps, {}> {
gridOptions: GridOptions;
api: GridApi | null;
columnApi: ColumnApi;
}
I am using the component in my react component like this:
import { AgGridReact } from 'ag-grid-react'
const HelpRequests= () => {
const grid = useRef<AgGridReact>(null)
if (grid.current) console.log(grid.current.columnApi)
return (<AgGridReact ref={grid}/>)
}
The Problem:
Typescript does complain that there is no columnApi. It seems it sadly picks the wrong type from the main.d.ts
I found that I can import the type from the agGridReact.d.ts directly and use it like this:
import {AgGridReact as AgGridReactType} from 'ag-grid-react/lib/agGridReact'
...
const grid = useRef<AgGridReactType>(null)
Question:
Is this the correct way to address this issue? Will typescript be smart enough not to import the ./node_modules/ag-grid-react/lib/agGridReact.ts file which could cause my bundle size to go up?
I've searched a lot but could not find anything about importing types only from node_modules subfolders.
I will try to answer this:
Let's assume there is an xyz library and it has these files:
xyz/lib/main.ts:
export const test = 1000
and
xyz/main.ts:
export * from './lib/main.ts'
export const test = 'foo bar'
And I would like to use xyz in my app.ts, and I am aware of only its main.ts file as I think it is the main file which exports everything from library. So I am most likely to do:
app.ts:
import { test } from './xyz/main'
console.debug(test) // it will print 'foo bar'
Now, somebody goes and comment this line in the library:
xyz/main.ts:
export * from './lib/main.ts'
// export const test = 'foo bar'
Now, what will be printed by my app.ts? It will print 1000.
The same thing is happening there with ag-grid-react. It (ag-grid-react/main.d.ts) is overriding the apparently correct (better) class declaration present in ag-grid-react/lib/agGridReact.d.ts. And it is perfectly fine to import from inner path.
main.d.ts:
export * from './lib/agGridReact'; // it is exporting from innner path too
export declare class AgGridColumn extends Component<AgGridColumnProps | AgGridColumnGroupProps, {}> { // and overriding here at the same time
}
agGridReact.d.ts:
export declare class AgGridReact extends Component<AgGridReactProps, {}> {
props: any;
state: any;
static propTypes: any;
gridOptions: GridOptions;
changeDetectionService: ChangeDetectionService;
api: GridApi | null;
columnApi: ColumnApi;
portals: ReactPortal[];
hasPendingPortalUpdate: boolean;
destroyed: boolean;
protected eGridDiv: HTMLElement;
private static MAX_COMPONENT_CREATION_TIME;
constructor(props: any, state: any);
render(): React.ReactElement<any, string | ((props: any) => React.ReactElement<any, string | any | (new (props: any) => React.Component<any, any, any>)>) | (new (props: any) => React.Component<any, any, any>)>;
createStyleForDiv(): any;
componentDidMount(): void;
waitForInstance(reactComponent: ReactComponent, resolve: (value: any) => void, runningTime?: number): void;
mountReactPortal(portal: ReactPortal, reactComponent: ReactComponent, resolve: (value: any) => void): void;
batchUpdate(callback?: any): any;
destroyPortal(portal: ReactPortal): void;
private getStrategyTypeForProp;
shouldComponentUpdate(nextProps: any): boolean;
componentDidUpdate(prevProps: any): void;
processPropsChanges(prevProps: any, nextProps: any): void;
private extractDeclarativeColDefChanges;
private extractGridPropertyChanges;
componentWillUnmount(): void;
isDisableStaticMarkup(): boolean;
}
I can't exactly say why ag-grid did this. I found this looking at the typing files. I may be incorrect too.

MediaStreamRecorder is not a constructor

I'm new to Angular6 and I'm trying to use MediaStreamRecorder. I'm definitely doing something wrong when defining MediaStreamRecorder because I keep getting the error TypeError: msr__WEBPACK_IMPORTED_MODULE_4__.MediaStreamRecorder is not a constructor. Not sure how or where should I declare and define MediaStreamRecorder. Can you help me with this, please?
I have installed msr module, and my code looks like this:
import { Component,ViewChild, OnInit, Inject } from '#angular/core';
import { LinksService } from 'demo/_services/links.service';
import { Http,Response,Headers } from '#angular/http';
import { MediaStreamRecorder} from 'msr';
import { RecordRTC } from 'recordrtc';
#Component({
selector: 'demo-ceva',
templateUrl: './ceva.component.html',
styleUrls: ['./ceva.component.css'],
providers: [
{
provide: SpeechRecognitionLang,
useValue: 'en-US',
},
SpeechRecognitionService,
],
})
export class CevaComponent {
public navigator: any;
public MediaStreamRecorder: any;
constructor( private http: Http, private service: SpeechRecognitionService, private links: LinksService ) {
this.record = () => {
var browser = <any>navigator;
var obj = { audio: true, video:false };
browser.getUserMedia = (browser.getUserMedia || browser.webkitGetUserMedia || browser.mozGetUserMedia || browser.msGetUserMedia);
browser.mediaDevices.getUserMedia(obj).then(stream => {
var source = window.URL.createObjectURL(stream);
var config= { ... }
var recorder = new MediaStreamRecorder(stream, config);
recorder.record();
recorder.stop(function(blob) {
var blob = recorder.blob;
console.log(blob);
});
});
});
As the answer to this post suggested, the solution to me was that in typings.d.ts file to add the following declarations:
declare interface MediaRecorderErrorEvent extends Event {
name: string;
}
declare interface MediaRecorderDataAvailableEvent extends Event {
data : any;
}
interface MediaRecorderEventMap {
'dataavailable': MediaRecorderDataAvailableEvent;
'error': MediaRecorderErrorEvent ;
'pause': Event;
'resume': Event;
'start': Event;
'stop': Event;
'warning': MediaRecorderErrorEvent ;
}
declare class MediaRecorder extends EventTarget {
readonly mimeType: string;
// readonly MimeType: 'audio/wav';
readonly state: 'inactive' | 'recording' | 'paused';
readonly stream: MediaStream;
ignoreMutedMedia: boolean;
videoBitsPerSecond: number;
audioBitsPerSecond: number;
ondataavailable: (event : MediaRecorderDataAvailableEvent) => void;
onerror: (event: MediaRecorderErrorEvent) => void;
onpause: () => void;
onresume: () => void;
onstart: () => void;
onstop: () => void;
constructor(stream: MediaStream);
start();
stop();
resume();
pause();
isTypeSupported(type: string): boolean;
requestData();
addEventListener<K extends keyof MediaRecorderEventMap>(type: K, listener: (this: MediaStream, ev: MediaRecorderEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof MediaRecorderEventMap>(type: K, listener: (this: MediaStream, ev: MediaRecorderEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
And in my component, I was able to use var mediaRecorder = new MediaRecorder(stream); without any other declarations. Thank you, #firegloves , for the link to this post and thank you, #Tiberiu C. for the answer! It was really helpful.
npm install -D #types/dom-mediacapture-record
I had the same issue with pure JS and React and removing the following line "fixed" the problem:
window.MediaRecorder = require('audio-recorder-polyfill');

moment-duration-format.d.ts Definition Not Extending Moment Module

Any idea why this doesn’t work or how I can extend the duration interface to support the format function?
declare module 'moment' {
interface Duration {
format(template: string, precision?: string, settings?: any): string;
}
}
when used as:
moment.duration(minutes, 'minutes').format('mm');
I’m getting the error that ‘format' does not exist on type ‘Duration'
First, install types:
npm install --save-dev #types/moment-duration-format
Second, import them in your file:
/// <reference path='../..your-path.../node_modules/#types/moment-duration-format/index.d.ts' />
import * as moment from 'moment';
import 'moment-duration-format';
Then you can use
moment.duration(minutes, 'minutes').format('mm');
Imports:
import * as moment from 'moment';
import 'moment-duration-format';
Outside of your class, define the interfaces:
interface Duration extends moment.Duration {
format: (template?: string, precision?: number, settings?: DurationSettings) => string;
}
interface DurationSettings {
forceLength: boolean;
precision: number;
template: string;
trim: boolean | 'left' | 'right';
}
Then in your code:
const duration = moment.duration(minutes, 'minutes') as Duration;
return duration.format('mm');
If you defined your Duration interface in another file, you will need to export and import it as well.
You need to have the following dependencies installed:
"dependencies": {
"#types/moment-duration-format": "2.2.2",
"moment": "2.24.0",
"moment-duration-format": "2.3.2"
}
If that's the case then you need these imports in the exact same order:
import * as moment from 'moment';
import 'moment-duration-format';
Afterwards you should be able to do this:
const seconds: number = Math.floor(process.uptime());
const formatted: string = moment.duration(seconds, 'seconds').format({
precision: 0,
template: 'y [years], w [weeks], d [days], h [hours], m [minutes], s [seconds]',
});
you should use namespace instead of module
declare namespace moment {
interface Duration {
format(template: string, precision?: string, settings?: DurationSettings): string;
}
}
and settings for "moment-duration-format": "^2.3.2"
interface DurationSettings {
trim: boolean | 'left' | 'right';
useGrouping: boolean;
usePlural: boolean;
useLeftUnits: boolean;
precision: number;
useSignificantDigits: boolean;
trunc: boolean;
forceLength: boolean;
minValue: number;
maxValue: number;
largest: number;
}

Use AngularJS 2 Component like a function in the element attribute

Hi guys!
I'm learning AngularJS 2 for a while now and now creating my own app based on Laravel 5 REST API. Anyway - that isn't very important atm.
What is important is that I want to provide the translation for the whole application and I found an issue that is hard to solve for me.
So - from the beginning... I'm created my ResourcesService that's translating the string:
getTranslation ( key: string, replace: Array<TranslationReplace> = null, locale: string = null, fallback: boolean = null ): Observable<Resource> {
var params = "key=" + key +
( replace ? "&replace=" + JSON.stringify(replace) : '') +
( locale ? "&locale=" + locale : '') +
( fallback ? "&fallback=" + fallback : '');
var headers = new Headers({'Content-Type':'application/x-www-form-urlencoded'});
return this.http.post(this.apiUrl + 'getTranslation', params, {headers: headers})
.map(this.extractData)
.startWith({ name: 'Loading...', value: 'Translating...' })
.catch(this.handleError);
}
And I created a TranslateComponent that's providing the translation, here's the whole component:
import {Component, Input, Injectable, OnInit, OnChanges, SimpleChange} from "#angular/core";
import {ResourcesService} from "../services/resources.service";
import {TranslationReplace} from "../models/TranslationReplace";
#Component({
selector: 'translate',
template: `{{translation}}`
})
#Injectable()
export class TranslateComponent implements OnInit, OnChanges {
#Input() ref: string;
#Input() replace: Array<TranslationReplace>;
#Input() locale: string;
#Input() fallback: boolean;
private translation: string;
constructor(private resourcesService: ResourcesService) {}
ngOnInit() : void {
this.getTranslation();
}
ngOnChanges(changes: {[propKey: string]: SimpleChange}) {
for (let propName in changes) {
if(propName == 'replace') {
this.getTranslation();
}
}
}
private getTranslation(): void {
this.resourcesService.getTranslation(this.ref, this.replace, this.locale, this.fallback).forEach(translation => this.translation = translation.value );
}
}
All is working just perfect and to call for the translation I have to simply call the selector like that:
<translate [ref]="'string.to_translate'"></translate>
But...
Now I'd like to use the translation in the attribute.
So I found the ugly way to achieve it by creating the reference of the translation and the call it in the attribute. But it's very nasty...
First of all I need to add this bit to my template:
<translate [ref]="'string.to_translate'" style="display:none;" #myStringTranslation></translate>
And next in my element call it and ask for the property by the reference:
<input type="text" [(ngModel)]="input" #input="ngModel [placeholder]="myStringTranslation.translation">
And I really don't like the idea.
What I'm looking for is to call it somehow, I don't know... emit it? And make it looks better. Don't create extra elements.
So my question is:
Can I do it better? Can I somehow call the translation directly from the attribute without the reference?
** ----- UPDATE ----- **
Ok, I learn my lesson :) Thanks to Meir for showing me the right direction and also the Angular.io site for the tutorials.
So finally I added a TranslateDirective to my application:
import {Directive, Input, ElementRef, OnChanges, OnInit, SimpleChange, Renderer} from "#angular/core";
import {TranslationReplace} from "../models/TranslationReplace";
import {ResourcesService} from "../services/resources.service";
#Directive({
selector: '[translate]'
})
export class TranslateDirective implements OnInit, OnChanges {
#Input('translate') ref: string;
#Input('translateReplace') replace: Array<TranslationReplace>;
#Input('translateLocale') locale: string;
#Input('translateFallback') fallback: boolean;
#Input('translateAttr') attr: string;
private translation: string;
constructor(
private elRef: ElementRef,
private renderer: Renderer,
private resourcesService: ResourcesService
) {}
ngOnInit():void {
this.getTranslation();
}
ngOnChanges(changes: {[propKey: string]: SimpleChange}):void {
for (let propName in changes) {
if(propName == 'replace') {
this.getTranslation();
}
}
}
private getTranslation(): void {
if(this.attr)
this.resourcesService.getTranslation(this.ref, this.replace, this.locale, this.fallback).forEach(translation =>
{
this.translation = translation.value;
this.renderer.setElementAttribute(this.elRef.nativeElement,this.attr,this.translation);
});
}
}
And now can easily add the translations to the attributes like that:
<input type="text" [(ngModel)]="input" #input="ngModel [translate]="'string.to_translate'" [translateAttr]="'placeholder'">
Thanks for your help!!
You can turn it into an attribute directive:
#Directive({
selector: 'translate'
})
export class TranslateDirectiev {
#Input() translate: string;
constructor(private elRef: ElementRef){}
ngOnChanges(changes: SimpleChanges): void {
if(this.translate){
var translatedText: string = translateSvc.translate(this.translate);
this.renderer.setElementProperty(this.elementRef.nativeElement, 'innerHTML', translatedText);
}
}
}
This is a simple example without the service injection. Also, for input fields you might need to have a different approach and update the value attribute and not the innerHtml

Categories

Resources